playhead-cli 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -0
- package/dist/audio/tts.d.ts +5 -3
- package/dist/audio/tts.d.ts.map +1 -1
- package/dist/cli/index.js +66 -9
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +60 -6
- package/dist/index.js.map +1 -1
- package/dist/mcp/bin.js +60 -6
- package/dist/mcp/bin.js.map +1 -1
- package/dist/spec/schema.d.ts +1 -0
- package/dist/spec/schema.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/spec/locators.ts","../../src/spec/schema.ts","../../src/spec/parse.ts","../../src/shared/easing.ts","../../src/shared/log.ts","../../src/capture/playwright-driver.ts","../../src/bundle/hash.ts","../../src/shared/version.ts","../../src/bundle/writer.ts","../../src/shared/geometry.ts","../../src/shared/exit.ts","../../src/capture/executor.ts","../../src/bundle/reader.ts","../../src/theme/index.ts","../../src/compose/types.ts","../../src/compose/kinds.ts","../../src/capture/events.ts","../../src/audio/timing.ts","../../src/compose/timeline/pacing.ts","../../src/compose/camera/interpolate.ts","../../src/compose/camera/planner.ts","../../src/compose/cursor/path.ts","../../src/compose/captions.ts","../../src/compose/overlays/text.ts","../../src/compose/overlays/build.ts","../../src/compose/cursor/render.ts","../../src/compose/overlays/draw.ts","../../src/compose/render/frameStore.ts","../../src/shared/ffmpeg.ts","../../src/compose/render/encoder.ts","../../src/compose/render/renderer.ts","../../src/audio/tts.ts","../../src/audio/mux.ts","../../src/compose/index.ts","../../src/verify/media.ts","../../src/verify/checks.ts","../../src/verify/contact-sheet.ts","../../src/verify/vision.ts","../../src/verify/report.ts","../../src/verify/runner.ts","../../src/beforeafter.ts","../../src/integrations/jira.ts","../../src/authoring/catalog.ts","../../src/authoring/explore.ts","../../src/authoring/validate.ts","../../src/authoring/serialize.ts","../../src/authoring/author.ts","../../src/mcp/server.ts","../../src/cli/index.ts"],"sourcesContent":["/**\n * Playhead locator grammar — resilient, label/role-based element addressing.\n *\n * role=button[name=\"Add user\"] role + accessible name\n * role=cell[name=/api key/i] regex accessible name\n * label=Email form control by label\n * text=\"User added\" visible text\n * placeholder=Search input placeholder\n * testid=add-user data-testid\n * css=#legacy .thing escape hatch (warned)\n * ... >> nth=1 pick among multiple matches\n * frame=#preview >> role=button[name=\"Save\"] pierce into an iframe (chainable)\n * frame=iframe[name=a] >> frame=#inner >> text=\"Hi\" nested frames\n *\n * Parsed form is serializable (regexes stored as {source, flags}) so it can live\n * in spec.resolved.json and events.json.\n */\n\nexport interface RegexSpec {\n source: string;\n flags: string;\n}\n\nexport type TextMatch = { exact: string } | { substring: string } | { regex: RegexSpec };\n\nexport type LocatorBase =\n | { kind: 'role'; role: string; name?: TextMatch }\n | { kind: 'label'; match: TextMatch }\n | { kind: 'text'; match: TextMatch }\n | { kind: 'placeholder'; match: TextMatch }\n | { kind: 'testid'; value: string }\n | { kind: 'css'; selector: string };\n\nexport interface ParsedLocator {\n base: LocatorBase;\n nth?: number;\n /** CSS selectors of the iframe chain to pierce (outermost first) before resolving `base`. */\n frames?: string[];\n /** The original spec string, kept for captions/diagnostics. */\n raw: string;\n}\n\nexport class LocatorParseError extends Error {}\n\nexport function parseLocator(input: string): ParsedLocator {\n const raw = input.trim();\n let nth: number | undefined;\n\n // Segments: [frame=SEL ...] BASE [nth=N]\n const parts = raw.split('>>').map((p) => p.trim());\n const frames: string[] = [];\n while (parts.length > 0 && parts[0]!.startsWith('frame=')) {\n const sel = unquote(parts.shift()!.slice('frame='.length).trim());\n if (!sel) throw new LocatorParseError(`Empty frame selector in \"${raw}\"`);\n frames.push(sel);\n }\n if (parts.length === 0) {\n throw new LocatorParseError(`Locator \"${raw}\" has frames but no element — add a base like role=... after the frame chain`);\n }\n const body = parts.shift()!;\n if (parts.length > 0) {\n const tail = parts.join(' >> ');\n const m = /^nth=(\\d+)$/.exec(tail);\n if (!m) throw new LocatorParseError(`Unsupported locator suffix \"${tail}\" in \"${raw}\" (only \"nth=N\" is supported)`);\n nth = Number(m[1]);\n }\n const withFrames = (p: ParsedLocator): ParsedLocator => (frames.length > 0 ? { ...p, frames } : p);\n\n const eq = body.indexOf('=');\n if (eq === -1) {\n throw new LocatorParseError(\n `Locator \"${raw}\" is missing an engine prefix — expected role=, label=, text=, placeholder=, testid= or css=`,\n );\n }\n const engine = body.slice(0, eq).trim();\n const rest = body.slice(eq + 1).trim();\n\n switch (engine) {\n case 'role': {\n const m = /^([\\w-]+)(?:\\[name=(.+)\\])?$/.exec(rest);\n if (!m) throw new LocatorParseError(`Malformed role locator \"${raw}\" — expected role=button[name=\"...\"]`);\n const base: LocatorBase = { kind: 'role', role: m[1]! };\n if (m[2] !== undefined) base.name = parseTextMatch(m[2]!, raw);\n return withFrames({ base, nth, raw });\n }\n case 'label':\n return withFrames({ base: { kind: 'label', match: parseTextMatch(rest, raw) }, nth, raw });\n case 'text':\n return withFrames({ base: { kind: 'text', match: parseTextMatch(rest, raw) }, nth, raw });\n case 'placeholder':\n return withFrames({ base: { kind: 'placeholder', match: parseTextMatch(rest, raw) }, nth, raw });\n case 'testid': {\n if (!rest) throw new LocatorParseError(`Empty testid in locator \"${raw}\"`);\n return withFrames({ base: { kind: 'testid', value: unquote(rest) }, nth, raw });\n }\n case 'css': {\n if (!rest) throw new LocatorParseError(`Empty css selector in locator \"${raw}\"`);\n return withFrames({ base: { kind: 'css', selector: rest }, nth, raw });\n }\n default:\n throw new LocatorParseError(\n `Unknown locator engine \"${engine}\" in \"${raw}\" — expected role, label, text, placeholder, testid or css`,\n );\n }\n}\n\nfunction parseTextMatch(s: string, context: string): TextMatch {\n const v = s.trim();\n if (v.startsWith('/')) {\n const m = /^\\/(.+)\\/([a-z]*)$/.exec(v);\n if (!m) throw new LocatorParseError(`Malformed regex \"${v}\" in locator \"${context}\"`);\n try {\n new RegExp(m[1]!, m[2]!);\n } catch {\n throw new LocatorParseError(`Invalid regex \"${v}\" in locator \"${context}\"`);\n }\n return { regex: { source: m[1]!, flags: m[2]! } };\n }\n if ((v.startsWith('\"') && v.endsWith('\"') && v.length >= 2) || (v.startsWith(\"'\") && v.endsWith(\"'\") && v.length >= 2)) {\n return { exact: v.slice(1, -1) };\n }\n if (!v) throw new LocatorParseError(`Empty text match in locator \"${context}\"`);\n return { substring: v };\n}\n\nfunction unquote(s: string): string {\n if ((s.startsWith('\"') && s.endsWith('\"')) || (s.startsWith(\"'\") && s.endsWith(\"'\"))) return s.slice(1, -1);\n return s;\n}\n\n/** Human-readable form of what a locator points at, used for captions when the accessible name is unavailable. */\nexport function locatorDisplayName(loc: ParsedLocator): string {\n const b = loc.base;\n switch (b.kind) {\n case 'role':\n return b.name ? textMatchDisplay(b.name) : b.role;\n case 'label':\n case 'text':\n case 'placeholder':\n return textMatchDisplay(b.match);\n case 'testid':\n return b.value;\n case 'css':\n return b.selector;\n }\n}\n\nfunction textMatchDisplay(m: TextMatch): string {\n if ('exact' in m) return m.exact;\n if ('substring' in m) return m.substring;\n return m.regex.source;\n}\n","import { z } from 'zod';\nimport { parseLocator } from './locators.js';\n\n/** \"1280x800\" → {w, h} */\nconst dimensions = z\n .string()\n .regex(/^\\d+x\\d+$/, 'expected WIDTHxHEIGHT, e.g. 1280x800')\n .transform((s) => {\n const [w, h] = s.split('x').map(Number);\n return { w: w!, h: h! };\n });\n\nconst locatorString = z.string().min(1).superRefine((val, ctx) => {\n try {\n parseLocator(val);\n } catch (e) {\n ctx.addIssue({ code: 'custom', message: (e as Error).message });\n }\n});\n\nconst focusHint = z.union([z.literal('target'), z.literal('wide'), locatorString]);\n\n/** Per-step extras shared by every action. */\nconst EXTRA_KEYS = ['caption', 'narration', 'focus', 'mask', 'shot', 'timeout'] as const;\n\n/** Common optional step fields. */\nconst stepExtras = {\n caption: z.string().optional(),\n /** The SPOKEN line for TTS narration — unconstrained by the caption card's size. Resolution:\n * spoken = narration ?? caption ?? auto; on-screen card = caption ?? auto. */\n narration: z.string().optional(),\n focus: focusHint.optional(),\n /** Camera-shot boundary control: 'cut' forces this step into its own shot; 'continue' merges\n * it into the previous shot even when the heuristic would split. Decouples camera cuts from\n * scene structure (scenes stay narrative). */\n shot: z.enum(['cut', 'continue']).optional(),\n /** Per-step budget override (ms) for finding the target / meeting the expectation. */\n timeout: z.number().int().positive().optional(),\n};\n\nconst targetOrShorthand = z.union([\n locatorString,\n z.object({ target: locatorString, ...stepExtras }),\n]);\n\n// ---- normalized step forms (the discriminated union everything downstream consumes) ----\n\n// Every step variant is .strict(): an unknown field inside a step payload (a typo like `txet:`,\n// or a knob that doesn't exist like `zoom:`) must FAIL LOUDLY — silently dropping it makes a\n// misspelled option indistinguishable from a feature that works badly.\nconst gotoStep = z.object({ action: z.literal('goto'), url: z.string(), ...stepExtras }).strict();\nconst pointerStep = z\n .object({\n action: z.enum(['click', 'dblclick', 'hover']),\n target: locatorString,\n ...stepExtras,\n })\n .strict();\nconst typeStep = z\n .object({\n action: z.literal('type'),\n target: locatorString,\n text: z.string(),\n mask: z.boolean().default(false),\n ...stepExtras,\n })\n .strict();\nconst pressStep = z.object({ action: z.literal('press'), keys: z.string(), ...stepExtras }).strict();\nconst selectStep = z\n .object({\n action: z.literal('select'),\n target: locatorString,\n value: z.string(),\n ...stepExtras,\n })\n .strict();\nconst scrollStep = z\n .object({\n action: z.literal('scroll'),\n target: locatorString.optional(),\n by: z.object({ x: z.number().default(0), y: z.number() }).strict().optional(),\n ...stepExtras,\n })\n .strict();\nconst expectStep = z\n .object({\n action: z.literal('expect'),\n target: locatorString,\n visible: z.boolean().optional(),\n text: z.string().optional(),\n /** Exact number of matching elements (e.g. rows in a filtered table). */\n count: z.number().int().min(0).optional(),\n ...stepExtras,\n })\n .strict();\n/** `wait: <ms>` is the discouraged blind sleep; `wait: { for: <locator>, state?, timeout? }`\n * is the structured form — wait until an element is visible/hidden, never a fixed nap. */\nconst waitStep = z\n .object({\n action: z.literal('wait'),\n ms: z.number().int().positive().optional(),\n for: locatorString.optional(),\n state: z.enum(['visible', 'hidden']).default('visible'),\n ...stepExtras,\n })\n .strict()\n .refine((s) => (s.ms !== undefined) !== (s.for !== undefined), {\n message: 'wait needs exactly one of `ms` (blind sleep, discouraged) or `for` (an element to wait on)',\n });\n\nexport const stepSchema = z.discriminatedUnion('action', [\n gotoStep,\n pointerStep,\n typeStep,\n pressStep,\n selectStep,\n scrollStep,\n expectStep,\n waitStep,\n]);\n\nexport type Step = z.infer<typeof stepSchema>;\n\n// ---- YAML authoring form: `- click: '...'` / `- type: { target, text }` with optional sibling keys ----\n\nconst ACTION_KEYS = ['goto', 'click', 'dblclick', 'hover', 'type', 'press', 'select', 'scroll', 'expect', 'wait'] as const;\n\nconst authoredStep = z\n .record(z.string(), z.unknown())\n .superRefine((obj, ctx) => {\n const actions = ACTION_KEYS.filter((k) => k in obj);\n if (actions.length !== 1) {\n // Echo what the author actually wrote and suggest the nearest action — \"expected one of\n // ten actions\" with no mention of the offending key forces a by-eye diff of the file.\n const unknown = Object.keys(obj).filter((k) => !(EXTRA_KEYS as readonly string[]).includes(k));\n const hints = unknown\n .map((k) => ({ k, near: nearestAction(k) }))\n .filter((h): h is { k: string; near: string } => h.near !== null)\n .map((h) => ` — did you mean \"${h.near}\" instead of \"${h.k}\"?`)\n .join('');\n ctx.addIssue({\n code: 'custom',\n message:\n actions.length === 0\n ? `Step has no action (found: ${unknown.join(', ') || 'nothing'})${hints || ` — expected one of: ${ACTION_KEYS.join(', ')}`}`\n : `Step has multiple actions (${actions.join(', ')}) — exactly one is allowed`,\n });\n return;\n }\n const known = new Set<string>([...ACTION_KEYS, ...EXTRA_KEYS]);\n for (const key of Object.keys(obj)) {\n if (!known.has(key)) {\n ctx.addIssue({ code: 'custom', message: `Unknown step field \"${key}\"` });\n }\n }\n })\n .transform((obj) => normalizeStep(obj));\n\n/** Nearest valid action to a typo (edit distance ≤ 2), or null. */\nfunction nearestAction(key: string): string | null {\n let best: string | null = null;\n let bestD = 3;\n for (const a of ACTION_KEYS) {\n const d = editDistance(key.toLowerCase(), a);\n if (d < bestD) {\n bestD = d;\n best = a;\n }\n }\n return best;\n}\n\nexport function editDistance(a: string, b: string): number {\n const dp = Array.from({ length: a.length + 1 }, (_, i) => [i, ...Array(b.length).fill(0)] as number[]);\n for (let j = 0; j <= b.length; j++) dp[0]![j] = j;\n for (let i = 1; i <= a.length; i++) {\n for (let j = 1; j <= b.length; j++) {\n dp[i]![j] = Math.min(\n dp[i - 1]![j]! + 1,\n dp[i]![j - 1]! + 1,\n dp[i - 1]![j - 1]! + (a[i - 1] === b[j - 1] ? 0 : 1),\n );\n }\n }\n return dp[a.length]![b.length]!;\n}\n\nfunction normalizeStep(obj: Record<string, unknown>): unknown {\n const action = ACTION_KEYS.find((k) => k in obj)!;\n const payload = obj[action];\n const extras: Record<string, unknown> = {};\n for (const k of EXTRA_KEYS) {\n if (k in obj) extras[k] = obj[k];\n }\n\n if (typeof payload === 'string') {\n // shorthand value: locator for element actions, url for goto, keys for press\n if (action === 'goto') return { action, url: payload, ...extras };\n if (action === 'press') return { action, keys: payload, ...extras };\n return { action, target: payload, ...extras };\n }\n if (typeof payload === 'number' && action === 'wait') {\n return { action, ms: payload, ...extras };\n }\n if (payload !== null && typeof payload === 'object') {\n return { action, ...(payload as Record<string, unknown>), ...extras };\n }\n return { action, value: payload, ...extras };\n}\n\n// ---- top-level spec ----\n//\n// Every object here is .strict(): a key the schema doesn't know is an ERROR, never silently\n// dropped. The spec must mean what it says — an author must be able to tell \"I configured this\n// wrong\" apart from \"this configuration does nothing\".\n\nexport const specSchema = z\n .object({\n playhead: z.literal(1),\n title: z.string().min(1),\n /** Title-card subtitle. Defaults to the app's host — set this for anything shareable. */\n subtitle: z.string().optional(),\n app: z\n .object({\n url: z.string().url(),\n /** Capture viewport. When omitted it is derived from output.aspect so portrait/square\n * outputs are captured at a matching viewport (the app reflows natively, no cropping). */\n viewport: dimensions.optional(),\n storageState: z.string().optional(),\n /** Fail fast when auth is stale: this locator must match after the initial load, or the\n * capture aborts — instead of confidently filming the login page. */\n assertLoggedIn: locatorString.optional(),\n /** For before/after: a second app to capture the same flow against (the \"before\"). */\n compareUrl: z.string().url().optional(),\n /** Determinism controls: same spec → same pixels regardless of where/when it runs. */\n environment: z\n .object({\n timezone: z.string().optional(),\n locale: z.string().optional(),\n colorScheme: z.enum(['light', 'dark']).optional(),\n /** Freeze Date at this ISO timestamp — \"3 minutes ago\" stops drifting between runs. */\n fixedTime: z.string().optional(),\n reducedMotion: z.boolean().optional(),\n })\n .strict()\n .optional(),\n /** Request interception: block third-party noise, stub responses, replay a HAR. */\n network: z\n .object({\n block: z.array(z.string()).optional(),\n stub: z\n .array(\n z\n .object({\n url: z.string(),\n status: z.number().int().optional(),\n body: z.string().optional(),\n contentType: z.string().optional(),\n })\n .strict(),\n )\n .optional(),\n har: z.string().optional(),\n })\n .strict()\n .optional(),\n /** window.confirm()/alert() policy. Default accept — the silent auto-dismiss films the\n * cancel branch of confirm-guarded flows. */\n dialogs: z.enum(['accept', 'dismiss']).optional(),\n /** Settle tuning for slow backends / chatty apps. */\n settle: z\n .object({\n idleMs: z.number().int().positive().optional(),\n capMs: z.number().int().positive().optional(),\n })\n .strict()\n .optional(),\n })\n .strict(),\n output: z\n .object({\n kind: z\n .enum(['walkthrough', 'demo', 'bug-repro', 'before-after', 'release', 'social'])\n .default('walkthrough'),\n aspect: z.enum(['16:9', '9:16', '1:1']).default('16:9'),\n /** Output resolution; when omitted it is derived from the aspect. */\n resolution: dimensions.optional(),\n fps: z.number().int().min(24).max(60).default(30),\n pacing: z.enum(['relaxed', 'normal', 'brisk']).optional(),\n /**\n * Multiplier on per-step dwell (min-step duration, post-action holds, outro).\n * 1 = the pacing preset as-is. Raise it for long-form teaching walkthroughs\n * where each screen should linger so a viewer can read and absorb it.\n */\n dwellScale: z.number().min(0.5).max(4).optional(),\n /**\n * Audio. `narration: tts` speaks each step's caption (pacing grows so every line finishes\n * before its step ends). `sfx` adds a soft synthesized click at each click beat. `music`\n * lays a user-supplied bed under everything, ducked beneath narration. Any audio work\n * finishes with loudness normalization (EBU R128, I=-16).\n */\n audio: z\n .object({\n narration: z.enum(['none', 'tts']).default('none'),\n provider: z.enum(['say']).default('say'),\n voice: z.string().optional(),\n rate: z.number().int().min(80).max(400).optional(),\n /** Click sound effects at click/select beats. Defaults on when this block is present. */\n sfx: z.boolean().default(true),\n /** Music bed from a local audio file (no asset is bundled — bring your own licensed track). */\n music: z\n .object({\n file: z.string(),\n gainDb: z.number().min(-40).max(6).default(-19),\n })\n .strict()\n .optional(),\n })\n .strict()\n .optional(),\n /** Closing card. When set, the video ends on a title-card-styled end card. */\n endCard: z\n .object({\n title: z.string().min(1),\n subtitle: z.string().optional(),\n })\n .strict()\n .optional(),\n })\n .strict()\n .prefault({}),\n // No `name` field: exactly one theme exists today, and a knob that is accepted but ignored is\n // a lie. It returns when a theme registry does.\n theme: z\n .object({\n accent: z\n .string()\n .regex(/^#[0-9a-fA-F]{6}$/, 'expected a #rrggbb hex color')\n .optional(),\n captions: z.enum(['bottom', 'top', 'off']).default('bottom'),\n })\n .strict()\n .prefault({}),\n masking: z\n .array(\n z\n .object({\n target: locatorString,\n style: z.enum(['solid', 'blur']).default('solid'),\n })\n .strict(),\n )\n .default([]),\n scenes: z\n .array(\n z\n .object({\n id: z.string().regex(/^[a-z0-9][a-z0-9-]*$/, 'scene ids are lowercase kebab-case'),\n title: z.string().optional(),\n steps: z.array(authoredStep.pipe(stepSchema)).min(1),\n })\n .strict(),\n )\n .min(1),\n })\n .strict();\n\nexport type Spec = z.infer<typeof specSchema>;\nexport type Scene = Spec['scenes'][number];\nexport type OutputSettings = Spec['output'];\nexport type MaskRule = Spec['masking'][number];\nexport type OutputKind = Spec['output']['kind'];\nexport type Aspect = Spec['output']['aspect'];\n\n/** Capture viewport + output resolution for each aspect (portrait/square reflow, never crop). */\nexport const ASPECTS: Record<Aspect, { viewport: { w: number; h: number }; resolution: { w: number; h: number } }> = {\n '16:9': { viewport: { w: 1280, h: 720 }, resolution: { w: 1920, h: 1080 } },\n '9:16': { viewport: { w: 720, h: 1280 }, resolution: { w: 1080, h: 1920 } },\n '1:1': { viewport: { w: 900, h: 900 }, resolution: { w: 1080, h: 1080 } },\n};\n\n/** The capture viewport: explicit spec value, else derived from the output aspect. */\nexport function resolveViewport(spec: Spec): { w: number; h: number } {\n return spec.app.viewport ?? ASPECTS[spec.output.aspect].viewport;\n}\n\n/** The output resolution: explicit spec value, else derived from the aspect. */\nexport function resolveResolution(spec: Spec): { w: number; h: number } {\n return spec.output.resolution ?? ASPECTS[spec.output.aspect].resolution;\n}\n\n/** A step with its position in the spec — the unit the capture executor and compositor work in. */\nexport interface AddressedStep {\n sceneId: string;\n sceneIndex: number;\n stepIndex: number;\n /** Global 1-based index across all scenes, used for step numbering. */\n ordinal: number;\n step: Step;\n}\n\nexport function flattenSteps(spec: Spec): AddressedStep[] {\n const out: AddressedStep[] = [];\n let ordinal = 0;\n spec.scenes.forEach((scene, sceneIndex) => {\n scene.steps.forEach((step, stepIndex) => {\n ordinal += 1;\n out.push({ sceneId: scene.id, sceneIndex, stepIndex, ordinal, step });\n });\n });\n return out;\n}\n","import { readFile } from 'node:fs/promises';\nimport { dirname, resolve as resolvePath } from 'node:path';\nimport { parseDocument, LineCounter, type Document } from 'yaml';\nimport { z } from 'zod';\nimport { specSchema, editDistance, type Spec } from './schema.js';\n\nexport class SpecError extends Error {\n constructor(\n message: string,\n public readonly issues: string[] = [],\n ) {\n super(message);\n }\n}\n\n/** Every key the schema knows, for \"did you mean\" suggestions on unrecognized keys. */\nconst KNOWN_KEYS = [\n 'playhead', 'title', 'subtitle', 'app', 'output', 'theme', 'masking', 'scenes', 'vars', 'extends',\n 'url', 'viewport', 'storageState', 'compareUrl', 'assertLoggedIn', 'environment', 'network', 'dialogs', 'settle',\n 'timezone', 'locale', 'colorScheme', 'fixedTime', 'reducedMotion', 'block', 'stub', 'har', 'status', 'body', 'contentType', 'idleMs', 'capMs',\n 'kind', 'aspect', 'resolution', 'fps', 'pacing', 'dwellScale', 'audio', 'endCard',\n 'narration', 'provider', 'voice', 'rate', 'sfx', 'music', 'file', 'gainDb',\n 'accent', 'captions',\n 'target', 'style', 'id', 'steps', 'shot', 'timeout',\n 'goto', 'click', 'dblclick', 'hover', 'type', 'press', 'select', 'scroll', 'expect', 'wait',\n 'caption', 'focus', 'mask', 'text', 'value', 'keys', 'ms', 'by', 'visible', 'hidden', 'count',\n 'for', 'state', 'x', 'y',\n];\n\nfunction suggest(key: string): string | null {\n let best: string | null = null;\n let bestD = 3;\n for (const k of KNOWN_KEYS) {\n const d = editDistance(key.toLowerCase(), k.toLowerCase());\n if (d > 0 && d < bestD) {\n bestD = d;\n best = k;\n }\n }\n return best;\n}\n\n/**\n * Parse + validate YAML text into a Spec. Supports:\n * - `vars:` — `{{name}}` interpolation across every string in the spec; values may reference\n * the environment as `${env.NAME}` or `${env.NAME:-default}`. Unknown `{{var}}` is an error.\n * - line/column positions on every validation error (mapped back to the YAML source).\n * `extends:` requires file context — use loadSpec.\n */\nexport function parseSpec(yamlText: string, sourcePath = '<inline>'): Spec {\n const lineCounter = new LineCounter();\n const doc = parseDocument(yamlText, { lineCounter, keepSourceTokens: true });\n if (doc.errors.length > 0) {\n const first = doc.errors[0]!;\n throw new SpecError(`${sourcePath}: not valid YAML — ${first.message}`);\n }\n const raw = doc.toJS() as Record<string, unknown> | null;\n if (raw && typeof raw === 'object' && 'extends' in raw) {\n throw new SpecError(`${sourcePath}: \"extends\" needs a file on disk — load the spec with loadSpec/the CLI, not inline text`);\n }\n return validateResolved(interpolate(raw, sourcePath), sourcePath, doc, lineCounter);\n}\n\n/** Load a spec file, resolving `extends:` (base file merged under this one) and `vars:`. */\nexport async function loadSpec(path: string): Promise<Spec> {\n const merged = await loadRaw(resolvePath(path), 0);\n // Re-parse the LEAF file for position mapping: merged keys that came from a base file simply\n // won't have positions, which is the honest best effort for multi-file specs.\n const text = await readFile(resolvePath(path), 'utf8');\n const lineCounter = new LineCounter();\n const doc = parseDocument(text, { lineCounter });\n return validateResolved(interpolate(merged, path), path, doc, lineCounter);\n}\n\n/** Read a YAML file to a plain object, recursively merging its `extends:` base underneath it. */\nasync function loadRaw(path: string, depth: number): Promise<Record<string, unknown>> {\n if (depth > 4) throw new SpecError(`${path}: extends chain deeper than 4 — check for a cycle`);\n const text = await readFile(path, 'utf8');\n const doc = parseDocument(text);\n if (doc.errors.length > 0) throw new SpecError(`${path}: not valid YAML — ${doc.errors[0]!.message}`);\n const raw = (doc.toJS() ?? {}) as Record<string, unknown>;\n const base = raw.extends;\n delete raw.extends;\n if (base === undefined) return raw;\n if (typeof base !== 'string') throw new SpecError(`${path}: \"extends\" must be a path string`);\n const baseObj = await loadRaw(resolvePath(dirname(path), base), depth + 1);\n return mergeSpecs(baseObj, raw);\n}\n\n/** Merge rule: objects merge deep, scalars in the child win, `masking`/`scenes` arrays append\n * (base first), any other array is replaced by the child's. */\nfunction mergeSpecs(base: Record<string, unknown>, child: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = { ...base };\n for (const [k, v] of Object.entries(child)) {\n const b = out[k];\n if (Array.isArray(b) && Array.isArray(v) && (k === 'masking' || k === 'scenes')) {\n out[k] = [...b, ...v];\n } else if (isPlainObject(b) && isPlainObject(v)) {\n out[k] = mergeSpecs(b, v);\n } else {\n out[k] = v;\n }\n }\n return out;\n}\n\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n return typeof v === 'object' && v !== null && !Array.isArray(v);\n}\n\n/** Resolve `vars:` (+ `${env.X[:-default]}` in their values) and interpolate `{{name}}` across\n * every string in the document. Fails loudly on an unknown var or unset env with no default —\n * a URL that silently renders \"undefined\" is worse than a parse error. */\nfunction interpolate(raw: unknown, sourcePath: string): unknown {\n if (!isPlainObject(raw)) return raw;\n const varsIn = isPlainObject(raw.vars) ? raw.vars : {};\n const vars = new Map<string, string>();\n for (const [name, value] of Object.entries(varsIn)) {\n vars.set(name, resolveEnv(String(value), sourcePath));\n }\n const doc = { ...raw };\n delete doc.vars;\n\n const seen = (s: string): string => {\n const withEnv = resolveEnv(s, sourcePath);\n return withEnv.replace(/\\{\\{\\s*([a-zA-Z0-9_.-]+)\\s*\\}\\}/g, (_, name: string) => {\n const v = vars.get(name);\n if (v === undefined) {\n const near = suggest(name) ?? [...vars.keys()].find((k) => editDistance(k, name) <= 2);\n throw new SpecError(\n `${sourcePath}: unknown variable {{${name}}}${near ? ` — did you mean {{${near}}}?` : ''} (declared vars: ${[...vars.keys()].join(', ') || 'none'})`,\n );\n }\n return v;\n });\n };\n const walk = (v: unknown): unknown => {\n if (typeof v === 'string') return seen(v);\n if (Array.isArray(v)) return v.map(walk);\n if (isPlainObject(v)) return Object.fromEntries(Object.entries(v).map(([k, val]) => [k, walk(val)]));\n return v;\n };\n return walk(doc);\n}\n\n/** `${env.NAME}` / `${env.NAME:-default}` → the environment value (or default). */\nfunction resolveEnv(s: string, sourcePath: string): string {\n return s.replace(/\\$\\{env\\.([A-Za-z_][A-Za-z0-9_]*)(?::-([^}]*))?\\}/g, (_, name: string, dflt?: string) => {\n const v = process.env[name];\n if (v !== undefined) return v;\n if (dflt !== undefined) return dflt;\n throw new SpecError(`${sourcePath}: environment variable ${name} is not set and has no default (use \\${env.${name}:-fallback})`);\n });\n}\n\nfunction validateResolved(\n resolved: unknown,\n sourcePath: string,\n doc: Document,\n lineCounter: LineCounter,\n): Spec {\n const result = specSchema.safeParse(resolved);\n if (!result.success) {\n const issues = result.error.issues.map((iss) => formatIssue(iss, sourcePath, doc, lineCounter));\n throw new SpecError(`${sourcePath}: invalid spec\\n - ${issues.join('\\n - ')}`, issues);\n }\n return result.data;\n}\n\nfunction formatIssue(\n iss: z.core.$ZodIssue,\n sourcePath: string,\n doc: Document,\n lineCounter: LineCounter,\n): string {\n const where = iss.path.length ? humanPath(iss.path) : 'spec';\n const pos = positionOf(iss.path, doc, lineCounter);\n const at = pos ? `${sourcePath}:${pos.line}:${pos.col} ` : '';\n // Strict-mode \"unrecognized key\" errors get a nearest-known-key suggestion, so a typo like\n // `acent:` reads as \"did you mean accent?\" instead of a bare rejection.\n if (iss.code === 'unrecognized_keys') {\n const keys = (iss as { keys: string[] }).keys;\n const hints = keys\n .map((k) => ({ k, near: suggest(k) }))\n .map((h) => (h.near ? `\"${h.k}\" (did you mean \"${h.near}\"?)` : `\"${h.k}\"`))\n .join(', ');\n return `${at}${where}: unknown key${keys.length > 1 ? 's' : ''} ${hints}`;\n }\n return `${at}${where}: ${iss.message}`;\n}\n\n/** YAML source position for a Zod issue path (walking as deep as the leaf document allows). */\nfunction positionOf(\n path: PropertyKey[],\n doc: Document,\n lineCounter: LineCounter,\n): { line: number; col: number } | null {\n for (let depth = path.length; depth > 0; depth--) {\n try {\n const node = doc.getIn(path.slice(0, depth) as (string | number)[], true) as\n | { range?: [number, number, number] }\n | undefined;\n if (node?.range) {\n const pos = lineCounter.linePos(node.range[0]);\n return { line: pos.line, col: pos.col };\n }\n } catch {\n /* keep walking up */\n }\n }\n return null;\n}\n\nfunction humanPath(path: PropertyKey[]): string {\n // scenes.0.steps.2 → scenes[0].steps[2]\n return path\n .map((seg, i) => (typeof seg === 'number' ? `[${seg}]` : i === 0 ? String(seg) : `.${String(seg)}`))\n .join('');\n}\n","/** Cubic bezier easing (CSS-style: fixed endpoints (0,0) and (1,1)). Serializable by its four control values. */\nexport type BezierParams = [number, number, number, number];\n\nexport const EASE_ZOOM: BezierParams = [0.4, 0, 0.2, 1];\nexport const EASE_PAN: BezierParams = [0.3, 0, 0.15, 1];\n\n/** Evaluate a CSS cubic-bezier at progress t ∈ [0,1] (solves x(t)=t for the parameter, returns y). */\nexport function cubicBezier(p: BezierParams, t: number): number {\n if (t <= 0) return 0;\n if (t >= 1) return 1;\n const [x1, y1, x2, y2] = p;\n // Newton-Raphson on x(u) = t\n let u = t;\n for (let i = 0; i < 8; i++) {\n const x = bez(u, x1, x2) - t;\n if (Math.abs(x) < 1e-6) break;\n const dx = dbez(u, x1, x2);\n if (Math.abs(dx) < 1e-6) break;\n u -= x / dx;\n }\n return bez(Math.max(0, Math.min(1, u)), y1, y2);\n}\n\nfunction bez(u: number, a: number, b: number): number {\n const v = 1 - u;\n return 3 * v * v * u * a + 3 * v * u * u * b + u * u * u;\n}\n\nfunction dbez(u: number, a: number, b: number): number {\n const v = 1 - u;\n return 3 * v * v * a + 6 * v * u * (b - a) + 3 * u * u * (1 - b);\n}\n\n/** Minimum-jerk position profile: smooth human-like travel, s(0)=0, s(1)=1, zero velocity/acceleration at ends. */\nexport function minJerk(t: number): number {\n if (t <= 0) return 0;\n if (t >= 1) return 1;\n return t * t * t * (10 - 15 * t + 6 * t * t);\n}\n","import pc from 'picocolors';\n\nlet verbose = false;\n\nexport function setVerbose(v: boolean): void {\n verbose = v;\n}\n\n// ALL human logging goes to stderr: stdout belongs to machine output (--json, catalogs),\n// so `playhead render --json | jq` works without ANSI noise corrupting the payload.\nexport const log = {\n info(msg: string): void {\n console.error(pc.dim('[playhead]') + ' ' + msg);\n },\n step(msg: string): void {\n console.error(pc.cyan(' ▸ ') + msg);\n },\n ok(msg: string): void {\n console.error(pc.green(' ✓ ') + msg);\n },\n warn(msg: string): void {\n console.error(pc.yellow(' ⚠ ') + msg);\n },\n error(msg: string): void {\n console.error(pc.red(' ✗ ') + msg);\n },\n debug(msg: string): void {\n if (verbose) console.error(pc.dim(' · ' + msg));\n },\n};\n","import { chromium, type Browser, type BrowserContext, type Page, type CDPSession, type Locator, type FrameLocator } from 'playwright';\nimport type {\n Driver,\n DriverLaunchOptions,\n MaskInstruction,\n RawInteractable,\n ScreencastFrame,\n ScreencastOptions,\n} from './driver-api.js';\nimport type { ParsedLocator, TextMatch } from '../spec/locators.js';\nimport type { TargetInfo, CursorWaypoint } from './events.js';\nimport type { Point } from '../shared/geometry.js';\nimport { minJerk } from '../shared/easing.js';\nimport { log } from '../shared/log.js';\n\n/** Budget for a single input dispatch (mouse/keyboard) — these have no Playwright timeout of\n * their own and a wedged renderer otherwise blocks them forever. */\nconst INPUT_TIMEOUT_MS = 5000;\n\nconst MASK_INIT_SCRIPT = `\n(() => {\n if (window.__playheadMaskInstalled) return;\n window.__playheadMaskInstalled = true;\n // Each masked element gets its own overlay box parented into that element's own DOM subtree.\n // This is what makes masking survive the top layer: an element inside a <dialog> modal (or a\n // popover) paints above a document-level overlay, so the box must be a descendant of the same\n // top-layer subtree to cover it. A position:fixed box stays out of flow, so parenting it into a\n // flex/grid container does not disturb layout.\n const boxes = new Map();\n const base = (box) => {\n box.setAttribute('aria-hidden', 'true');\n box.style.position = 'fixed';\n box.style.pointerEvents = 'none';\n box.style.zIndex = '2147483647';\n box.style.borderRadius = '5px';\n box.style.margin = '0';\n };\n const sync = (box, el, style) => {\n const r = el.getBoundingClientRect();\n const pad = 3; // cover focus rings / borders just outside the element box\n box.style.left = (r.left - pad) + 'px';\n box.style.top = (r.top - pad) + 'px';\n box.style.width = (r.width + pad * 2) + 'px';\n box.style.height = (r.height + pad * 2) + 'px';\n box.style.display = r.width > 0 && r.height > 0 ? 'block' : 'none';\n if (style === 'blur') {\n box.style.backdropFilter = 'blur(18px)';\n box.style.webkitBackdropFilter = 'blur(18px)';\n box.style.background = 'rgba(120,124,140,0.45)';\n } else {\n box.style.backdropFilter = '';\n box.style.background = '#2a2f3a';\n }\n };\n // In-page rule matching: CSS-expressible mask rules (testid=, css=) are pushed into\n // window.__playheadMaskCssRules and re-scanned continuously, so an element that APPEARS\n // MID-STEP (a token in a modal, an email in a toast, a row from the fetch settle waits on)\n // is tagged the frame it appears — not seconds later at the next step boundary. Node-side\n // tagging remains the backstop for rules needing Playwright semantics (role/label/text).\n let scanTick = 0;\n const scanRules = () => {\n const rules = window.__playheadMaskCssRules || [];\n for (const r of rules) {\n try {\n for (const el of document.querySelectorAll(r.css)) {\n if (!el.hasAttribute('data-playhead-mask')) el.setAttribute('data-playhead-mask', r.style);\n }\n } catch (e) {}\n }\n };\n const tick = () => {\n try {\n if (scanTick++ % 3 === 0) scanRules(); // every ~3 frames — cheap, and a 1-frame leak beats a 1-step leak\n const tagged = new Set(document.querySelectorAll('[data-playhead-mask]'));\n for (const [el, box] of boxes) {\n if (!tagged.has(el) || !el.isConnected) { box.remove(); boxes.delete(el); }\n }\n for (const el of tagged) {\n const parent = el.parentElement || document.body;\n let box = boxes.get(el);\n if (!box) {\n box = document.createElement('div');\n base(box);\n parent.appendChild(box);\n boxes.set(el, box);\n } else if (box.parentElement !== parent) {\n parent.appendChild(box);\n }\n sync(box, el, el.getAttribute('data-playhead-mask'));\n }\n } catch (e) {}\n requestAnimationFrame(tick);\n };\n requestAnimationFrame(tick);\n})();\n`;\n\n/** In-page fallback accessible-name computation for when the CDP AX lookup fails. */\nconst FALLBACK_NAME_FN = `(el) => {\n const norm = (s) => (s || '').replace(/\\\\s+/g, ' ').trim();\n const label = el.getAttribute('aria-label');\n if (label) return norm(label);\n const labelledBy = el.getAttribute('aria-labelledby');\n if (labelledBy) {\n const parts = labelledBy.split(/\\\\s+/).map((id) => {\n const ref = document.getElementById(id);\n return ref ? ref.textContent : '';\n });\n const joined = norm(parts.join(' '));\n if (joined) return joined;\n }\n if (el.labels && el.labels.length) return norm(el.labels[0].textContent);\n if (el.alt) return norm(el.alt);\n const text = norm(el.textContent);\n if (text) return text.slice(0, 80);\n if (el.placeholder) return norm(el.placeholder);\n if (el.title) return norm(el.title);\n return null;\n}`;\n\n/** In-page: gather every interactable element with the fields needed to author a grounded locator. */\nconst COLLECT_INTERACTABLES_FN = `() => {\n const norm = (s) => (s || '').replace(/\\\\s+/g, ' ').trim();\n // Accessible text = visible text excluding aria-hidden / hidden subtrees, matching how the\n // ARIA name is computed (so a decorative icon inside a link doesn't leak into the name).\n const accText = (el) => {\n let t = '';\n const walk = (node) => {\n if (node.nodeType === 3) { t += node.textContent; return; }\n if (node.nodeType !== 1) return;\n if (node.getAttribute && (node.getAttribute('aria-hidden') === 'true' || node.hasAttribute('hidden'))) return;\n for (const c of node.childNodes) walk(c);\n };\n walk(el);\n return norm(t);\n };\n const IMPLICIT = { A: 'link', BUTTON: 'button', SELECT: 'combobox', TEXTAREA: 'textbox', SUMMARY: 'button' };\n const inputRole = (el) => {\n const t = (el.getAttribute('type') || 'text').toLowerCase();\n if (t === 'checkbox') return 'checkbox';\n if (t === 'radio') return 'radio';\n if (t === 'range') return 'slider';\n if (t === 'button' || t === 'submit' || t === 'reset') return 'button';\n if (t === 'search') return 'searchbox';\n return 'textbox';\n };\n const accName = (el) => {\n const al = el.getAttribute('aria-label'); if (al) return norm(al);\n const lb = el.getAttribute('aria-labelledby');\n if (lb) { const parts = lb.split(/\\\\s+/).map((id) => { const r = document.getElementById(id); return r ? r.textContent : ''; }); const j = norm(parts.join(' ')); if (j) return j; }\n if (el.labels && el.labels.length) return accText(el.labels[0]);\n if (el.alt) return norm(el.alt);\n // NEVER walk a <select>'s subtree: that concatenates every <option> into a monster\n // \"Choose option...grayrednavy…\" pseudo-name that no human would write as a locator.\n if (el.tagName === 'SELECT' || el.tagName === 'DATALIST') {\n const sel = el.selectedOptions && el.selectedOptions[0];\n return sel ? norm(sel.textContent) : null;\n }\n const txt = accText(el); if (txt) return txt.slice(0, 80);\n if (el.placeholder) return norm(el.placeholder);\n if (el.title) return norm(el.title);\n return null;\n };\n // Landmark region for catalog grouping: which part of the page the element lives in.\n const regionOf = (el) => {\n const lm = el.closest('[role=dialog], dialog, nav, [role=navigation], header, [role=banner], aside, [role=complementary], footer, [role=contentinfo], main, [role=main]');\n if (!lm) return 'page';\n const tag = lm.tagName.toLowerCase();\n const role = lm.getAttribute && lm.getAttribute('role');\n if (tag === 'dialog' || role === 'dialog') return 'dialog';\n if (tag === 'nav' || role === 'navigation') return 'nav';\n if (tag === 'header' || role === 'banner') return 'header';\n if (tag === 'aside' || role === 'complementary') return 'sidebar';\n if (tag === 'footer' || role === 'contentinfo') return 'footer';\n return 'main';\n };\n const sel = 'button, a[href], input, select, textarea, summary, [role=button], [role=link], [role=tab], [role=switch], [role=menuitem], [role=checkbox], [contenteditable=\"\"], [contenteditable=true], h1, h2, h3';\n const seen = new Set();\n const out = [];\n for (const el of document.querySelectorAll(sel)) {\n if (seen.has(el)) continue; seen.add(el);\n const r = el.getBoundingClientRect();\n const style = getComputedStyle(el);\n const visible = r.width > 1 && r.height > 1 && style.visibility !== 'hidden' && style.display !== 'none' &&\n r.bottom > 0 && r.top < innerHeight && r.right > 0 && r.left < innerWidth;\n const tag = el.tagName;\n const explicit = el.getAttribute('role');\n const role = explicit || IMPLICIT[tag] || (tag === 'INPUT' ? inputRole(el) : (tag[0] === 'H' && tag.length === 2 ? 'heading' : null));\n let label = null;\n if (el.labels && el.labels.length) label = norm(el.labels[0].textContent);\n const options = tag === 'SELECT' ? Array.from(el.options).map((o) => norm(o.textContent)) : undefined;\n out.push({\n tag, role,\n accessibleName: accName(el),\n label,\n placeholder: el.getAttribute && el.getAttribute('placeholder') ? norm(el.getAttribute('placeholder')) : null,\n testId: el.getAttribute && (el.getAttribute('data-testid') || el.getAttribute('data-test-id')) || null,\n text: accText(el).slice(0, 80) || null,\n bbox: { x: r.x, y: r.y, w: r.width, h: r.height },\n visible,\n inputType: tag === 'INPUT' ? (el.getAttribute('type') || 'text').toLowerCase() : (tag === 'SELECT' ? 'select' : null),\n region: regionOf(el),\n ...(options ? { options } : {}),\n });\n }\n return out;\n}`;\n\nexport class PlaywrightDriver implements Driver {\n private browser!: Browser;\n private context!: BrowserContext;\n private page!: Page;\n private cdp!: CDPSession;\n /** Dedicated CDP session for the capture loop so its screenshots never contend with the\n * executor's accessibility/geometry lookups on the main session (which could deadlock). */\n private captureCdp!: CDPSession;\n private cursor: Point = { x: 0, y: 0 };\n private navCallbacks: ((url: string, t: number) => void)[] = [];\n private captureActive = false;\n private captureLoop: Promise<void> | null = null;\n private captureOnFrame: ((f: ScreencastFrame) => void) | null = null;\n private captureOpts: ScreencastOptions | null = null;\n private inflightGrab: Promise<void> | null = null;\n private lastFrameNodeMs = 0;\n private clockOffset = 0;\n private tagCounter = 0;\n private typingMaskLoc: ParsedLocator | null = null;\n\n async launch(opts: DriverLaunchOptions): Promise<void> {\n const env = opts.environment;\n this.browser = await chromium.launch({ headless: opts.headless ?? true });\n this.context = await this.browser.newContext({\n viewport: { width: opts.viewport.w, height: opts.viewport.h },\n deviceScaleFactor: opts.dpr,\n colorScheme: env?.colorScheme ?? 'light',\n ...(env?.timezone ? { timezoneId: env.timezone } : {}),\n ...(env?.locale ? { locale: env.locale } : {}),\n ...(env?.reducedMotion ? { reducedMotion: 'reduce' as const } : {}),\n ...(opts.storageStatePath ? { storageState: opts.storageStatePath } : {}),\n });\n this.context.setDefaultTimeout(10_000);\n this.context.setDefaultNavigationTimeout(20_000);\n\n // Network interception: blocked third-party noise, canned responses, HAR replay.\n const net = opts.network;\n if (net?.har) await this.context.routeFromHAR(net.har, { notFound: 'fallback' });\n for (const glob of net?.block ?? []) {\n await this.context.route(glob, (route) => route.fulfill({ status: 204, body: '' }));\n }\n for (const stub of net?.stub ?? []) {\n await this.context.route(stub.url, (route) =>\n route.fulfill({\n status: stub.status ?? 200,\n body: stub.body ?? '',\n contentType: stub.contentType ?? 'application/json',\n }),\n );\n }\n\n this.page = await this.context.newPage();\n if (env?.fixedTime) await this.page.clock.setFixedTime(new Date(env.fixedTime));\n await this.page.addInitScript(MASK_INIT_SCRIPT);\n this.cdp = await this.context.newCDPSession(this.page);\n this.captureCdp = await this.context.newCDPSession(this.page);\n this.page.on('framenavigated', (frame) => {\n if (frame === this.page.mainFrame()) {\n const t = Date.now();\n for (const cb of this.navCallbacks) cb(frame.url(), t);\n }\n });\n\n // Evidence + correctness listeners.\n this.page.on('console', (msg) => this.pushConsole(msg.type(), msg.text()));\n this.page.on('pageerror', (err) => this.pushConsole('pageerror', err.message));\n this.page.on('crash', () => this.pushConsole('crash', 'page crashed'));\n // Dialogs: Playwright's default DISMISSES, so a confirm()-guarded delete silently films the\n // cancel branch. Accept by default (spec-controllable), and always record it.\n const dialogPolicy = opts.dialogs ?? 'accept';\n this.page.on('dialog', (dialog) => {\n this.pushConsole('dialog', `${dialog.type()}(\"${dialog.message()}\") → ${dialogPolicy}`);\n void (dialogPolicy === 'accept' ? dialog.accept() : dialog.dismiss()).catch(() => {});\n });\n // Popups/new tabs: capture stays on the main page — record loudly instead of failing silently.\n this.context.on('page', (p) => {\n if (p !== this.page) {\n this.pushConsole('popup', `new tab/popup opened: ${p.url()} (not filmed — capture follows the main page)`);\n log.warn(`popup opened (${p.url()}) — multi-tab capture is not yet supported; footage stays on the main page`);\n }\n });\n\n this.cursor = { x: opts.viewport.w / 2, y: opts.viewport.h * 0.6 };\n await this.page.mouse.move(this.cursor.x, this.cursor.y);\n }\n\n private consoleBuf: { t: number; type: string; text: string }[] = [];\n\n private pushConsole(type: string, text: string): void {\n this.consoleBuf.push({ t: Date.now(), type, text: text.slice(0, 500) });\n if (this.consoleBuf.length > 500) this.consoleBuf.shift();\n }\n\n consoleLog(): { t: number; type: string; text: string }[] {\n return [...this.consoleBuf];\n }\n\n async close(): Promise<void> {\n if (!this.browser) return;\n await withTimeout(this.browser.close(), 8000).catch(() => {});\n }\n\n async measureClockOffset(): Promise<number> {\n const samples: number[] = [];\n for (let i = 0; i < 5; i++) {\n const t0 = Date.now();\n const browserNow = await withTimeout(this.page.evaluate(() => Date.now()), 2000).catch(() => t0);\n const t1 = Date.now();\n samples.push(browserNow - (t0 + t1) / 2);\n }\n samples.sort((a, b) => a - b);\n this.clockOffset = samples[2]!;\n return this.clockOffset;\n }\n\n async goto(url: string): Promise<void> {\n await this.page.goto(url, { waitUntil: 'load' });\n // fonts.ready can stay pending FOREVER on a wedged dev server (one stalled font asset never\n // resolves the promise — .catch() only covers rejection). Race it in-page against a short\n // timer, and bound the evaluate itself so a blocked main thread can't hang the capture.\n await withTimeout(\n this.page.evaluate(\n () => Promise.race([(document as any).fonts?.ready, new Promise((r) => setTimeout(r, 2000))]),\n ),\n 3000,\n ).catch(() => {});\n }\n\n onNavigation(cb: (url: string, t: number) => void): void {\n this.navCallbacks.push(cb);\n }\n\n currentUrl(): string {\n return this.page.url();\n }\n\n async currentTitle(): Promise<string> {\n return this.page.title().catch(() => '');\n }\n\n async ariaSnapshot(): Promise<string> {\n return this.page.locator('body').ariaSnapshot().catch(() => '');\n }\n\n async countMatches(loc: ParsedLocator): Promise<number> {\n try {\n return await this.toLocator(loc).count();\n } catch {\n return 0;\n }\n }\n\n async collectInteractables(): Promise<RawInteractable[]> {\n const collect = new Function(`return (${COLLECT_INTERACTABLES_FN})()`) as () => RawInteractable[];\n const out = await withTimeout(this.page.evaluate(collect), 10_000).catch(() => [] as RawInteractable[]);\n\n // Pierce one level of iframes that have an addressable selector, so exploration SEES frame\n // content (a Storybook canvas, an embedded widget) and emits frame-qualified locators.\n const handles = await this.page.$$('iframe').catch(() => []);\n for (const h of handles) {\n try {\n const sel = await h.evaluate((el: HTMLIFrameElement) => {\n if (el.id) return `#${CSS.escape(el.id)}`;\n const name = el.getAttribute('name');\n if (name) return `iframe[name=\"${name}\"]`;\n const tid = el.getAttribute('data-testid');\n if (tid) return `iframe[data-testid=\"${tid}\"]`;\n return null;\n });\n if (!sel) continue;\n const frame = await h.contentFrame();\n if (!frame) continue;\n const rect = await h.boundingBox();\n const inner = await withTimeout(\n frame.evaluate(collect),\n 8000,\n ).catch(() => [] as RawInteractable[]);\n for (const e of inner) {\n out.push({\n ...e,\n framePrefix: `frame=${sel}`,\n bbox: rect ? { x: e.bbox.x + rect.x, y: e.bbox.y + rect.y, w: e.bbox.w, h: e.bbox.h } : e.bbox,\n });\n }\n } catch {\n /* cross-origin or detached frame — unexplorable, skip */\n }\n }\n return out;\n }\n\n // ---------- locating & measuring ----------\n\n private toLocator(loc: ParsedLocator): Locator {\n // Frame chain first: `frame=#preview >> role=...` pierces into the iframe(s). Page-level\n // locators pierce shadow DOM for free but NEVER iframes — this is what makes an app whose\n // content lives in a frame (Storybook canvases, embedded checkouts, MFEs) addressable.\n let scope: Page | FrameLocator = this.page;\n for (const sel of loc.frames ?? []) scope = scope.frameLocator(sel);\n const b = loc.base;\n let l: Locator;\n switch (b.kind) {\n case 'role':\n l = scope.getByRole(b.role as Parameters<Page['getByRole']>[0], b.name ? { name: toPw(b.name), exact: isExact(b.name) } : {});\n break;\n case 'label':\n l = scope.getByLabel(toPw(b.match), { exact: isExact(b.match) });\n break;\n case 'text':\n l = scope.getByText(toPw(b.match), { exact: isExact(b.match) });\n break;\n case 'placeholder':\n l = scope.getByPlaceholder(toPw(b.match), { exact: isExact(b.match) });\n break;\n case 'testid':\n l = scope.getByTestId(b.value);\n break;\n case 'css':\n l = scope.locator(b.selector);\n break;\n }\n if (loc.nth !== undefined) l = l.nth(loc.nth);\n return l;\n }\n\n async resolveTarget(loc: ParsedLocator, timeoutMs: number): Promise<TargetInfo> {\n const locator = this.toLocator(loc);\n try {\n await locator.waitFor({ state: 'visible', timeout: timeoutMs });\n } catch (e) {\n // Never collapse distinct failures into one string: an ambiguous locator (strict-mode\n // violation), a hidden-but-present element, and a genuinely missing element each need a\n // different fix from the author — say which one this is.\n const msg = (e as Error).message ?? '';\n if (/strict mode violation/i.test(msg)) {\n const count = await locator.count().catch(() => -1);\n throw new Error(\n `Locator is ambiguous: ${loc.raw} matches ${count >= 0 ? count : 'multiple'} elements — add '>> nth=N' to pick one`,\n );\n }\n const count = await this.countMatches(loc);\n const reason =\n count === 0\n ? 'no matching element on the page'\n : `${count} match(es) present but none became visible`;\n throw new Error(\n `Target not resolvable: ${loc.raw} — ${reason} within ${timeoutMs}ms on ${this.page.url()} (${firstLine(msg)})`,\n );\n }\n await locator.scrollIntoViewIfNeeded().catch(() => {});\n // Layout stability: two identical geometry samples one frame apart.\n const deadline = Date.now() + timeoutMs;\n let prev: string | null = null;\n while (Date.now() < deadline) {\n const box = await locator.boundingBox();\n const sig = box ? `${box.x},${box.y},${box.width},${box.height}` : null;\n if (sig && sig === prev) break;\n prev = sig;\n await this.nextFrame();\n }\n const info = await this.measure(locator, loc);\n if (!info) throw new Error(`Target disappeared while measuring: ${loc.raw}`);\n return info;\n }\n\n /** Wait for the page to paint one frame, bounded — a concurrent screenshot must never let this hang. */\n private async nextFrame(): Promise<void> {\n await withTimeout(\n this.page.evaluate(() => new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(r)))),\n 1500,\n ).catch(() => {});\n }\n\n async tryMeasure(loc: ParsedLocator): Promise<TargetInfo | null> {\n const locator = this.toLocator(loc);\n try {\n if (!(await locator.isVisible())) return null;\n return await this.measure(locator, loc);\n } catch {\n return null;\n }\n }\n\n private async measure(locator: Locator, loc: ParsedLocator): Promise<TargetInfo | null> {\n const tag = `ph-${++this.tagCounter}`;\n const geom = await locator\n .evaluate((el, t) => {\n el.setAttribute('data-playhead-t', t);\n const r = el.getBoundingClientRect();\n return {\n bbox: { x: r.x, y: r.y, w: r.width, h: r.height },\n scroll: { x: window.scrollX, y: window.scrollY },\n };\n }, tag)\n .catch(() => null);\n if (!geom) return null;\n // Frame-scoped elements: getBoundingClientRect is relative to the FRAME's viewport, but\n // every consumer (camera, verification pixel sampling, click coordinates) works in MAIN\n // viewport space. locator.boundingBox() is main-frame-relative — use it for position.\n if (loc.frames && loc.frames.length > 0) {\n const box = await withTimeout(locator.boundingBox(), 3000).catch(() => null);\n if (box) geom.bbox = { x: box.x, y: box.y, w: box.width, h: box.height };\n }\n\n let role: string | null = null;\n let name: string | null = null;\n try {\n const evalRes = (await withTimeout(\n this.cdp.send('Runtime.evaluate', {\n expression: `document.querySelector('[data-playhead-t=\"${tag}\"]')`,\n }),\n 4000,\n )) as { result: { objectId?: string } };\n if (evalRes.result.objectId) {\n const desc = (await withTimeout(\n this.cdp.send('DOM.describeNode', { objectId: evalRes.result.objectId }),\n 4000,\n )) as { node: { backendNodeId: number } };\n const ax = (await withTimeout(\n this.cdp.send('Accessibility.getPartialAXTree', {\n backendNodeId: desc.node.backendNodeId,\n fetchRelatives: false,\n }),\n 4000,\n )) as { nodes: { role?: { value?: string }; name?: { value?: string }; ignored?: boolean }[] };\n const node = ax.nodes?.[0];\n if (node && !node.ignored) {\n role = node.role?.value ?? null;\n name = node.name?.value ?? null;\n }\n await this.cdp.send('Runtime.releaseObject', { objectId: evalRes.result.objectId }).catch(() => {});\n }\n } catch (e) {\n log.debug(`AX lookup failed for ${loc.raw}: ${(e as Error).message}`);\n }\n if (!name) {\n name = await locator.evaluate(new Function('el', `return (${FALLBACK_NAME_FN})(el)`) as (el: Element) => string | null).catch(() => null);\n }\n await locator.evaluate((el) => el.removeAttribute('data-playhead-t')).catch(() => {});\n return { role, accessibleName: name, bbox: geom.bbox, scroll: geom.scroll };\n }\n\n // ---------- input ----------\n\n cursorPos(): Point {\n return { ...this.cursor };\n }\n\n async moveCursor(to: Point, durationMs: number): Promise<CursorWaypoint[]> {\n const from = { ...this.cursor };\n const waypoints: CursorWaypoint[] = [{ x: from.x, y: from.y, t: Date.now() }];\n const stepMs = 12;\n const steps = Math.max(2, Math.round(durationMs / stepMs));\n for (let i = 1; i <= steps; i++) {\n const p = minJerk(i / steps);\n const x = from.x + (to.x - from.x) * p;\n const y = from.y + (to.y - from.y) * p;\n // Input dispatch has no Playwright timeout and a wedged renderer can block it forever.\n await withTimeout(this.page.mouse.move(x, y), INPUT_TIMEOUT_MS);\n waypoints.push({ x, y, t: Date.now() });\n if (i < steps) await sleep(stepMs);\n }\n this.cursor = { ...to };\n return waypoints;\n }\n\n async clickAt(p: Point, opts?: { double?: boolean }): Promise<{ tDown: number; tUp: number }> {\n await withTimeout(this.page.mouse.move(p.x, p.y), INPUT_TIMEOUT_MS);\n this.cursor = { ...p };\n const tDown = Date.now();\n await withTimeout(this.page.mouse.down(), INPUT_TIMEOUT_MS);\n await sleep(70);\n await withTimeout(this.page.mouse.up(), INPUT_TIMEOUT_MS);\n if (opts?.double) {\n await sleep(60);\n await withTimeout(this.page.mouse.down({ clickCount: 2 }), INPUT_TIMEOUT_MS);\n await sleep(60);\n await withTimeout(this.page.mouse.up({ clickCount: 2 }), INPUT_TIMEOUT_MS);\n }\n return { tDown, tUp: Date.now() };\n }\n\n async typeText(text: string, delayMs: number): Promise<{ tFirst: number; tLast: number }> {\n const tFirst = Date.now();\n // Budget scales with the text: the typing itself takes length × delay by design.\n await withTimeout(this.page.keyboard.type(text, { delay: delayMs }), 10_000 + text.length * delayMs * 2);\n return { tFirst, tLast: Date.now() };\n }\n\n async press(keys: string): Promise<{ tDown: number }> {\n const tDown = Date.now();\n await withTimeout(this.page.keyboard.press(keys), INPUT_TIMEOUT_MS);\n return { tDown };\n }\n\n /**\n * The REAL click: Playwright's locator.click with actionability + hit-target verification and\n * retry. The cosmetic cursor has already animated to the target; this dispatches the action\n * through the checks a raw coordinate click bypasses (a toast/sticky header drifting under\n * the point between measure and click silently redirects a coordinate click).\n */\n async actClick(loc: ParsedLocator, opts?: { double?: boolean; timeoutMs?: number }): Promise<{ tDown: number; tUp: number }> {\n const locator = this.toLocator(loc);\n const tDown = Date.now();\n if (opts?.double) await locator.dblclick({ delay: 60, timeout: opts?.timeoutMs ?? 10_000 });\n else await locator.click({ delay: 70, timeout: opts?.timeoutMs ?? 10_000 });\n return { tDown, tUp: Date.now() };\n }\n\n async selectOption(loc: ParsedLocator, value: string): Promise<void> {\n const locator = this.toLocator(loc);\n try {\n await locator.selectOption({ label: value });\n } catch {\n await locator.selectOption(value);\n }\n // Leave the page CLEAN: dismiss any native popup the interaction opened and drop focus, so\n // the next step's locators aren't fighting a lingering dropdown or :focus-visible state.\n await withTimeout(this.page.keyboard.press('Escape'), INPUT_TIMEOUT_MS).catch(() => {});\n await withTimeout(\n locator.evaluate((el) => (el as HTMLElement).blur?.()),\n 2000,\n ).catch(() => {});\n }\n\n async scrollIntoView(loc: ParsedLocator): Promise<void> {\n const locator = this.toLocator(loc);\n await withTimeout(\n locator.evaluate((el) => el.scrollIntoView({ behavior: 'smooth', block: 'center' })),\n 5000,\n );\n }\n\n async scrollBy(by: { x: number; y: number }): Promise<void> {\n await withTimeout(\n this.page.evaluate(({ x, y }) => window.scrollBy({ left: x, top: y, behavior: 'smooth' }), by),\n 5000,\n );\n }\n\n async waitForScrollSettle(timeoutMs: number): Promise<void> {\n const deadline = Date.now() + timeoutMs;\n let prev = Number.NaN;\n let stable = 0;\n while (Date.now() < deadline) {\n // Bound the evaluate itself: the outer deadline is only consulted between iterations, so a\n // single evaluate blocked by a busy main thread would otherwise blow straight past it.\n const y = await withTimeout(this.page.evaluate(() => window.scrollY), 1500).catch(() => prev);\n if (y === prev) {\n if (++stable >= 2) return;\n } else {\n stable = 0;\n prev = y;\n }\n await sleep(60);\n }\n }\n\n async expectState(\n loc: ParsedLocator,\n opts: { visible?: boolean; text?: string; count?: number },\n timeoutMs: number,\n ): Promise<void> {\n const locator = this.toLocator(loc);\n const deadline = Date.now() + timeoutMs;\n let lastErr = 'condition not met';\n while (Date.now() < deadline) {\n try {\n if (opts.count !== undefined) {\n const n = await locator.count();\n if (n === opts.count) return;\n lastErr = `expected ${opts.count} match(es), found ${n}`;\n await sleep(100);\n continue;\n }\n const visible = await locator.first().isVisible();\n if (opts.visible !== undefined && visible !== opts.visible) {\n lastErr = `expected visible=${opts.visible}, got ${visible}`;\n } else if (opts.text !== undefined) {\n const content = visible ? await locator.first().innerText() : '';\n if (!content.includes(opts.text)) {\n lastErr = `expected text to include \"${opts.text}\"`;\n } else {\n return;\n }\n } else {\n return;\n }\n } catch (e) {\n lastErr = (e as Error).message;\n }\n await sleep(100);\n }\n throw new Error(`expect failed for ${loc.raw}: ${lastErr}`);\n }\n\n // ---------- settling ----------\n\n /** Open requests → their start time. Long-lived streams (HMR sockets, SSE, long-polls) stop\n * counting after LONG_REQUEST_MS so a dev server can't pin the settle at its cap forever. */\n private pending = new Map<unknown, number>();\n private lastNetActivity = 0;\n private netTrackingInstalled = false;\n\n private installNetTracking(): void {\n if (this.netTrackingInstalled) return;\n this.netTrackingInstalled = true;\n this.lastNetActivity = Date.now();\n const IGNORED_TYPES = new Set(['eventsource', 'websocket', 'ping']);\n this.page.on('request', (req) => {\n if (IGNORED_TYPES.has(req.resourceType())) return;\n this.pending.set(req, Date.now());\n this.lastNetActivity = Date.now();\n });\n const done = (req: unknown) => {\n if (this.pending.delete(req)) this.lastNetActivity = Date.now();\n };\n this.page.on('requestfinished', done);\n this.page.on('requestfailed', done);\n }\n\n private static readonly LONG_REQUEST_MS = 2000;\n\n async settle(opts: { idleMs: number; capMs: number }): Promise<void> {\n this.installNetTracking();\n const start = Date.now();\n // Network idle — counting only requests younger than LONG_REQUEST_MS, so persistent\n // streams don't hold the gate.\n let capped = true;\n while (Date.now() - start < opts.capMs) {\n const now = Date.now();\n let inflight = 0;\n for (const t of this.pending.values()) {\n if (now - t < PlaywrightDriver.LONG_REQUEST_MS) inflight += 1;\n }\n if (inflight === 0 && now - this.lastNetActivity >= opts.idleMs) {\n capped = false;\n break;\n }\n await sleep(30);\n }\n if (capped) log.debug(`settle hit its ${opts.capMs}ms cap — footage may include in-flight loading`);\n // Real quiescence: no DOM mutations for 250ms AND no running finite animations (infinite\n // spinners are excluded — they'd block forever and their looping is the state, not a\n // transition). Bounded: a busy page costs at most ~1.8s here.\n await withTimeout(\n this.page.evaluate(\n () =>\n new Promise<void>((resolve) => {\n const done = () => {\n obs.disconnect();\n resolve();\n };\n let timer: ReturnType<typeof setTimeout>;\n const arm = () => {\n clearTimeout(timer);\n timer = setTimeout(() => {\n const running = (document.getAnimations?.() ?? []).filter((a) => {\n const t = a.effect?.getTiming?.();\n return a.playState === 'running' && t && t.iterations !== Infinity;\n });\n if (running.length === 0) done();\n else arm();\n }, 250);\n };\n const obs = new MutationObserver(() => arm());\n obs.observe(document.documentElement, { subtree: true, childList: true, attributes: true, characterData: true });\n arm();\n setTimeout(done, 1500); // hard floor: never block longer than this\n }),\n ),\n 1800,\n ).catch(() => {});\n // Final paint flush.\n await this.nextFrame();\n }\n\n async saveStorageState(path: string): Promise<void> {\n await this.context.storageState({ path });\n }\n\n // ---------- masking ----------\n\n /**\n * Install CSS-expressible mask rules for continuous in-page tagging (see MASK_INIT_SCRIPT).\n * Rules that can't be expressed as CSS (role/label/text) return false and stay Node-tagged.\n */\n async installMaskRules(rules: MaskInstruction[]): Promise<void> {\n const cssRules = rules\n .map((r) => ({ css: maskRuleToCss(r.loc), style: r.style }))\n .filter((r): r is { css: string; style: 'solid' | 'blur' } => r.css !== null);\n if (cssRules.length === 0) return;\n const payload = JSON.stringify(cssRules);\n // Init script → future documents (navigations); evaluate → the current one.\n await this.page.addInitScript(`window.__playheadMaskCssRules = ${payload};`);\n await withTimeout(\n this.page.evaluate((json) => ((window as any).__playheadMaskCssRules = JSON.parse(json)), payload),\n 3000,\n ).catch(() => {});\n }\n\n async applyMasks(\n rules: MaskInstruction[],\n ): Promise<{ style: 'solid' | 'blur'; x: number; y: number; w: number; h: number }[]> {\n const tagged: { style: 'solid' | 'blur'; x: number; y: number; w: number; h: number }[] = [];\n for (const rule of rules) {\n const locator = this.toLocator(rule.loc);\n // .all() (not a single-match locator) so rules matching many elements — e.g. every API-key\n // cell — are each tagged and measured, without tripping strict-mode.\n const all = await locator.all().catch(() => [] as Locator[]);\n for (const el of all) {\n const box = await el\n .evaluate((node, style) => {\n node.setAttribute('data-playhead-mask', style);\n const r = (node as HTMLElement).getBoundingClientRect();\n return { x: r.x, y: r.y, w: r.width, h: r.height };\n }, rule.style)\n .catch(() => null);\n if (box && box.w > 0 && box.h > 0) tagged.push({ style: rule.style, ...box });\n }\n }\n return tagged;\n }\n\n async setTypingMask(loc: ParsedLocator | null): Promise<void> {\n if (loc) {\n this.typingMaskLoc = loc;\n const locator = this.toLocator(loc);\n await locator.evaluate((el) => el.setAttribute('data-playhead-mask', 'solid')).catch(() => {});\n } else if (this.typingMaskLoc) {\n const locator = this.toLocator(this.typingMaskLoc);\n await locator.evaluate((el) => el.removeAttribute('data-playhead-mask')).catch(() => {});\n this.typingMaskLoc = null;\n }\n }\n\n // ---------- frame capture ----------\n //\n // Headless Chromium's CDP screencast is hard-locked to CSS-pixel resolution and ignores\n // deviceScaleFactor, so a paced Page.captureScreenshot loop with clip.scale is what actually\n // yields 2x frames (the zoom headroom the camera planner needs).\n\n async startCapture(onFrame: (f: ScreencastFrame) => void, opts: ScreencastOptions): Promise<void> {\n this.captureOnFrame = onFrame;\n this.captureOpts = opts;\n this.captureActive = true;\n const intervalMs = 1000 / opts.fps;\n this.captureLoop = (async () => {\n while (this.captureActive) {\n const started = Date.now();\n await this.grabFrame();\n const elapsed = Date.now() - started;\n if (elapsed < intervalMs) await sleep(intervalMs - elapsed);\n }\n })();\n }\n\n /** Grab a frame, coalescing on any in-flight grab (so callers can await the current one). */\n private grabFrame(): Promise<void> {\n if (this.inflightGrab) return this.inflightGrab;\n this.inflightGrab = this.doGrab().finally(() => {\n this.inflightGrab = null;\n });\n return this.inflightGrab;\n }\n\n private grabFailures = 0;\n\n private async doGrab(): Promise<void> {\n if (!this.captureOpts || !this.captureOnFrame) return;\n try {\n const opts = this.captureOpts;\n const vp = this.page.viewportSize() ?? { width: 1280, height: 720 };\n // The screenshot clip is in PAGE coordinates, so it must track the current scroll offset;\n // a fixed {0,0} clip captures document-top (scrolled out of view) as blank once the page\n // scrolls. Clipping to [scrollX, scrollY, vp] captures exactly the visible viewport, which\n // is also the space the event bounding boxes live in. Read the offset via getLayoutMetrics\n // (a native CDP call) rather than page JS, so it never contends with the page thread and\n // stall the capture loop during navigation.\n const scroll = await this.readScroll();\n // 1.5s budget: a stall costs one frame, not eighty. (Was 4s — during navigations that\n // produced measured 4-second frame voids at exactly the action beat.)\n const shot = (await withTimeout(\n this.captureCdp.send('Page.captureScreenshot', {\n format: opts.format,\n quality: opts.quality,\n clip: { x: scroll.x, y: scroll.y, width: vp.width, height: vp.height, scale: opts.scale },\n captureBeyondViewport: false,\n }),\n 1500,\n )) as { data: string };\n const tNodeMs = Date.now();\n this.lastFrameNodeMs = tNodeMs;\n this.grabFailures = 0;\n this.captureOnFrame({ data: Buffer.from(shot.data, 'base64'), tNodeMs });\n } catch {\n // withTimeout abandons but cannot cancel the CDP send, and Chromium serves a session's\n // sends IN ORDER — so a wedged screenshot head-of-line blocks every later grab on this\n // session. After consecutive failures, tear the session down and start a fresh one.\n this.grabFailures += 1;\n if (this.grabFailures >= 2) {\n try {\n await this.captureCdp.detach().catch(() => {});\n this.captureCdp = await this.context.newCDPSession(this.page);\n log.warn('capture: recreated CDP session after stalled screenshots');\n this.grabFailures = 0;\n } catch {\n /* context mid-navigation — next grab retries */\n }\n }\n }\n }\n\n private async readScroll(): Promise<{ x: number; y: number }> {\n try {\n const m = (await withTimeout(this.captureCdp.send('Page.getLayoutMetrics'), 1500)) as {\n cssVisualViewport?: { pageX?: number; pageY?: number };\n visualViewport?: { pageX?: number; pageY?: number };\n };\n const vv = m.cssVisualViewport ?? m.visualViewport;\n return { x: Math.round(vv?.pageX ?? 0), y: Math.round(vv?.pageY ?? 0) };\n } catch {\n return { x: 0, y: 0 };\n }\n }\n\n async stopCapture(): Promise<void> {\n this.captureActive = false;\n await this.captureLoop?.catch(() => {});\n this.captureLoop = null;\n }\n\n lastFrameAt(): number {\n return this.lastFrameNodeMs;\n }\n\n async captureNow(): Promise<void> {\n // Wait out any in-flight grab (it may predate the action), then force a guaranteed fresh one\n // that reflects the settled post-action state. Never gives up early under load.\n if (this.inflightGrab) await this.inflightGrab.catch(() => {});\n await this.grabFrame();\n }\n}\n\nfunction toPw(m: TextMatch): string | RegExp {\n if ('exact' in m) return m.exact;\n if ('substring' in m) return m.substring;\n return new RegExp(m.regex.source, m.regex.flags);\n}\n\nfunction isExact(m: TextMatch): boolean {\n return 'exact' in m;\n}\n\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n\n/** CSS selector for a mask rule when the locator engine is CSS-expressible; null otherwise. */\nfunction maskRuleToCss(loc: ParsedLocator): string | null {\n const b = loc.base;\n if (b.kind === 'css') return b.selector;\n if (b.kind === 'testid') return `[data-testid=${JSON.stringify(b.value)}]`;\n return null;\n}\n\nfunction firstLine(s: string): string {\n const line = s.split('\\n')[0] ?? '';\n return line.length > 160 ? `${line.slice(0, 159)}…` : line;\n}\n\n/** Reject if a promise (typically a CDP send) doesn't settle in time, so a stalled call can't freeze the pipeline. */\nfunction withTimeout<T>(p: Promise<T>, ms: number): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => reject(new Error(`operation timed out after ${ms}ms`)), ms);\n p.then(\n (v) => {\n clearTimeout(timer);\n resolve(v);\n },\n (e) => {\n clearTimeout(timer);\n reject(e);\n },\n );\n });\n}\n","import { createHash } from 'node:crypto';\nimport { createReadStream } from 'node:fs';\n\nexport function sha256Json(value: unknown): string {\n return createHash('sha256').update(JSON.stringify(value)).digest('hex');\n}\n\nexport function sha256File(path: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const hash = createHash('sha256');\n createReadStream(path)\n .on('data', (d) => hash.update(d))\n .on('end', () => resolve(hash.digest('hex')))\n .on('error', reject);\n });\n}\n","import { createRequire } from 'node:module';\n\n/** The ONE version source: package.json. Bundle manifests, the CLI, the MCP server, and\n * verdict provenance all read this — they can never disagree with the installed package. */\nexport const PLAYHEAD_VERSION: string = (\n createRequire(import.meta.url)('../../package.json') as { version: string }\n).version;\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport sharp from 'sharp';\nimport type { Spec } from '../spec/schema.js';\nimport type { EventLog } from '../capture/events.js';\nimport type { BundleManifest, FrameIndexEntry, MaskSample } from './types.js';\nimport { sha256Json } from './hash.js';\nimport { PLAYHEAD_VERSION } from '../shared/version.js';\n\n\nexport class BundleWriter {\n private frames: FrameIndexEntry[] = [];\n private pendingWrites: Promise<unknown>[] = [];\n private maskSamples: MaskSample[] = [];\n private counter = 0;\n private ready: Promise<void>;\n\n constructor(\n private readonly dir: string,\n private readonly captureFormat: 'jpeg' | 'png',\n ) {\n this.ready = mkdir(join(dir, 'frames'), { recursive: true }).then(() => {});\n }\n\n /** Queue a frame write. `t` is capture-relative ms. */\n addFrame(data: Buffer, t: number): void {\n this.counter += 1;\n const name = `${String(this.counter).padStart(6, '0')}.${this.captureFormat === 'jpeg' ? 'jpg' : 'png'}`;\n this.frames.push({ f: name, t: round1(t) });\n this.pendingWrites.push(\n this.ready.then(() => writeFile(join(this.dir, 'frames', name), data)),\n );\n }\n\n addMaskSample(sample: MaskSample): void {\n this.maskSamples.push(sample);\n }\n\n frameCount(): number {\n return this.counter;\n }\n\n async finish(meta: {\n spec: Spec;\n events: EventLog;\n appUrl: string;\n viewport: { w: number; h: number };\n dpr: number;\n clockOffsetMs: number;\n durationMs: number;\n partial?: boolean;\n failure?: { stepRef: string; message: string };\n }): Promise<BundleManifest> {\n await this.ready;\n await Promise.all(this.pendingWrites);\n this.frames.sort((a, b) => a.t - b.t);\n\n // Actual frame pixel size is the source of truth for frame-space scale.\n let frameW = meta.viewport.w * meta.dpr;\n let frameH = meta.viewport.h * meta.dpr;\n const first = this.frames[0];\n if (first) {\n const info = await sharp(join(this.dir, 'frames', first.f)).metadata();\n if (info.width && info.height) {\n frameW = info.width;\n frameH = info.height;\n }\n }\n\n const manifest: BundleManifest = {\n schema: 'playhead/bundle@1',\n playheadVersion: PLAYHEAD_VERSION,\n specHash: sha256Json(meta.spec),\n appUrl: meta.appUrl,\n viewport: meta.viewport,\n dpr: meta.dpr,\n frameW,\n frameH,\n clockOffsetMs: meta.clockOffsetMs,\n frameCount: this.frames.length,\n durationMs: round1(meta.durationMs),\n createdAtIso: new Date().toISOString(),\n captureFormat: this.captureFormat,\n hashes: {\n events: sha256Json(meta.events),\n framesIndex: sha256Json(this.frames),\n },\n ...(meta.partial ? { partial: true } : {}),\n ...(meta.failure ? { failure: meta.failure } : {}),\n };\n\n await Promise.all([\n writeFile(join(this.dir, 'frames', 'index.json'), JSON.stringify(this.frames)),\n writeFile(join(this.dir, 'events.json'), JSON.stringify(meta.events, null, 2)),\n writeFile(join(this.dir, 'masks.json'), JSON.stringify(this.maskSamples, null, 2)),\n writeFile(join(this.dir, 'spec.resolved.json'), JSON.stringify(meta.spec, null, 2)),\n writeFile(join(this.dir, 'manifest.json'), JSON.stringify(manifest, null, 2)),\n ]);\n return manifest;\n }\n}\n\nfunction round1(n: number): number {\n return Math.round(n * 10) / 10;\n}\n","/** Axis-aligned rectangle. Space is documented at each use site (viewport CSS px, frame px, or output px). */\nexport interface Rect {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\nexport interface Point {\n x: number;\n y: number;\n}\n\nexport function rectCenter(r: Rect): Point {\n return { x: r.x + r.w / 2, y: r.y + r.h / 2 };\n}\n\nexport function rectUnion(a: Rect, b: Rect): Rect {\n const x = Math.min(a.x, b.x);\n const y = Math.min(a.y, b.y);\n return {\n x,\n y,\n w: Math.max(a.x + a.w, b.x + b.w) - x,\n h: Math.max(a.y + a.h, b.y + b.h) - y,\n };\n}\n\nexport function padRect(r: Rect, pad: number): Rect {\n return { x: r.x - pad, y: r.y - pad, w: r.w + pad * 2, h: r.h + pad * 2 };\n}\n\n/** True when `inner` lies fully inside `outer`, with an optional margin inside `outer`. */\nexport function rectContains(outer: Rect, inner: Rect, margin = 0): boolean {\n return (\n inner.x >= outer.x + margin &&\n inner.y >= outer.y + margin &&\n inner.x + inner.w <= outer.x + outer.w - margin &&\n inner.y + inner.h <= outer.y + outer.h - margin\n );\n}\n\nexport function clamp(v: number, min: number, max: number): number {\n return v < min ? min : v > max ? max : v;\n}\n\nexport function lerp(a: number, b: number, t: number): number {\n return a + (b - a) * t;\n}\n\nexport function dist(a: Point, b: Point): number {\n return Math.hypot(a.x - b.x, a.y - b.y);\n}\n\n/**\n * Camera state on the source viewport plane. The visible window always has the\n * OUTPUT aspect ratio (width-anchored): zoom=1 shows the full viewport width,\n * with height vpW/zoom/outAspect — the camera pans vertically over pages taller\n * than 16:9 rather than distorting them.\n */\nexport interface CameraState {\n cx: number;\n cy: number;\n zoom: number;\n}\n\nexport interface CameraPlane {\n vpW: number;\n vpH: number;\n outW: number;\n outH: number;\n}\n\n/** The viewport-space rect visible at a camera state (output-aspect, width-anchored). */\nexport function visibleRect(cam: CameraState, plane: CameraPlane): Rect {\n const w = plane.vpW / cam.zoom;\n const h = (w * plane.outH) / plane.outW;\n return { x: cam.cx - w / 2, y: cam.cy - h / 2, w, h };\n}\n\n/** Minimum zoom that keeps the visible window inside a page of this height. */\nexport function minZoom(plane: CameraPlane): number {\n return Math.max(1, plane.vpW / ((plane.vpH * plane.outW) / plane.outH));\n}\n\n/** Clamp a camera so its visible rect stays inside the viewport. */\nexport function clampCamera(cam: CameraState, plane: CameraPlane): CameraState {\n const zoom = Math.max(cam.zoom, minZoom(plane));\n const w = plane.vpW / zoom;\n const h = (w * plane.outH) / plane.outW;\n return {\n zoom,\n cx: clamp(cam.cx, w / 2, plane.vpW - w / 2),\n cy: clamp(cam.cy, h / 2, plane.vpH - h / 2),\n };\n}\n\n/** Project a viewport-space rect into output space given a camera state. */\nexport function projectRect(r: Rect, cam: CameraState, plane: CameraPlane): Rect {\n const vis = visibleRect(cam, plane);\n const s = plane.outW / vis.w;\n return { x: (r.x - vis.x) * s, y: (r.y - vis.y) * s, w: r.w * s, h: r.h * s };\n}\n\n/** Project a viewport-space point into output space given a camera state. */\nexport function projectPoint(p: Point, cam: CameraState, plane: CameraPlane): Point {\n const vis = visibleRect(cam, plane);\n const s = plane.outW / vis.w;\n return { x: (p.x - vis.x) * s, y: (p.y - vis.y) * s };\n}\n","/**\n * Typed exit codes — a CI pipeline must be able to tell WHICH kind of red this is:\n *\n * 0 pass — rendered and publishable\n * 1 flow failure — the APP broke the flow (locator gone, expect failed, step timeout);\n * a partial bundle + failure clip exist\n * 2 quality fail — the flow ran but the video failed verification (framing, captions, audio)\n * 3 infra failure — environment problems (browser/ffmpeg missing, launch failed)\n * 4 usage error — bad spec / bad arguments\n *\n * A test tool that can't distinguish \"your app is broken\" from \"the video is ugly\" from\n * \"the runner is misconfigured\" gets `|| true`'d. This is the contract that prevents that.\n */\nexport const EXIT = {\n OK: 0,\n FLOW: 1,\n QUALITY: 2,\n INFRA: 3,\n USAGE: 4,\n} as const;\n\n/** The app broke the scripted flow (capture-time step failure). */\nexport class FlowError extends Error {\n readonly exitCode = EXIT.FLOW;\n}\n\n/** Environment/tooling problem — nothing about the app or the spec. */\nexport class InfraError extends Error {\n readonly exitCode = EXIT.INFRA;\n}\n\n/** Classify an arbitrary thrown error into an exit code. SpecErrors are matched by name to\n * avoid a circular import with the spec parser. */\nexport function exitCodeFor(e: unknown): number {\n if (e && typeof e === 'object') {\n if ('exitCode' in e && typeof (e as { exitCode: unknown }).exitCode === 'number') {\n return (e as { exitCode: number }).exitCode;\n }\n if ((e as Error).name === 'SpecError' || e instanceof Object && (e as Error).constructor?.name === 'SpecError') {\n return EXIT.USAGE;\n }\n }\n return EXIT.INFRA;\n}\n","import { join } from 'node:path';\nimport type { Spec, AddressedStep } from '../spec/schema.js';\nimport { flattenSteps, resolveViewport } from '../spec/schema.js';\nimport { parseLocator } from '../spec/locators.js';\nimport type { Driver, MaskInstruction } from './driver-api.js';\nimport { PlaywrightDriver } from './playwright-driver.js';\nimport type { ActionEvent, CaptureEvent, CursorWaypoint, EventLog, TargetInfo } from './events.js';\nimport { BundleWriter } from '../bundle/writer.js';\nimport { rectCenter, clamp, dist } from '../shared/geometry.js';\nimport { log } from '../shared/log.js';\nimport { FlowError } from '../shared/exit.js';\n\nexport interface CaptureOptions {\n outDir: string;\n headless?: boolean;\n captureFormat?: 'jpeg' | 'png';\n quality?: number;\n driver?: Driver;\n /**\n * Iteration accelerator: steps BEFORE this scene run fast (no cursor choreography, no\n * filming, no events) purely to build app state; capture starts at this scene. The bundle\n * is a partial covering only the filmed scenes — for iterating on one scene, not shipping.\n */\n fromScene?: string;\n}\n\nconst SETTLE = { idleMs: 300, capMs: 5000 };\nconst TARGET_TIMEOUT_MS = 10_000;\nconst EXPECT_TIMEOUT_MS = 10_000;\nconst TYPE_DELAY_MS = 45;\n/** Hard budget for one step end-to-end (resolve + cursor + action). A step that can't finish in\n * this window is failed with its stepRef instead of hanging the whole capture. */\nconst STEP_BUDGET_MS = 45_000;\n/** Watchdog: overall capture deadline. Long specs are bounded per-step anyway; this is the\n * backstop that guarantees a capture NEVER runs unbounded (the 7-minute-hang class). */\nconst CAPTURE_DEADLINE_MS = 10 * 60_000;\n\nexport async function capture(spec: Spec, opts: CaptureOptions): Promise<{ bundleDir: string }> {\n const bundleDir = join(opts.outDir, 'capture');\n const driver = opts.driver ?? new PlaywrightDriver();\n const dpr = 2;\n const format = opts.captureFormat ?? 'jpeg';\n const writer = new BundleWriter(bundleDir, format);\n const events: CaptureEvent[] = [];\n const maskRules: MaskInstruction[] = spec.masking.map((m) => ({\n loc: parseLocator(m.target),\n style: m.style,\n }));\n\n const viewport = resolveViewport(spec);\n const settleCfg = {\n idleMs: spec.app.settle?.idleMs ?? SETTLE.idleMs,\n capMs: spec.app.settle?.capMs ?? SETTLE.capMs,\n };\n log.info(`capturing \"${spec.title}\" from ${spec.app.url}`);\n await driver.launch({\n viewport,\n dpr,\n headless: opts.headless ?? true,\n ...(spec.app.storageState ? { storageStatePath: spec.app.storageState } : {}),\n ...(spec.app.environment ? { environment: spec.app.environment } : {}),\n ...(spec.app.network ? { network: spec.app.network } : {}),\n ...(spec.app.dialogs ? { dialogs: spec.app.dialogs } : {}),\n });\n\n // Clock scaffolding lives OUTSIDE the try so the finally can finalize the bundle: a failed\n // step must never destroy the footage already captured (the failure is when video evidence\n // matters most). t0 is re-based after clock sync below.\n let t0 = Date.now();\n const rel = (nodeMs: number) => nodeMs - t0;\n const now = () => rel(Date.now());\n let clockOffsetMs = 0;\n let failure: { stepRef: string; message: string } | undefined;\n let currentStepRef = '';\n\n try {\n clockOffsetMs = await driver.measureClockOffset();\n t0 = Date.now();\n\n driver.onNavigation((url, tNode) => {\n events.push({ type: 'navigation', url, t: rel(tNode) });\n });\n\n const startFilming = () =>\n driver.startCapture((frame) => writer.addFrame(frame.data, rel(frame.tNodeMs)), {\n format,\n quality: opts.quality ?? 82,\n scale: dpr,\n // 24 requested ≈ 20-22 achieved with the screenshot loop's ~25ms capture cost; frame\n // blending at compose smooths the rest. (True 30+ needs the screencast source — planned.)\n fps: 24,\n });\n // Filming starts up-front normally, but AFTER the fast-forward pre-roll with --from-scene:\n // pre-roll steps build state and must never appear on film.\n if (!opts.fromScene) await startFilming();\n\n // Initial navigation + masks. CSS-expressible rules also go in-page for continuous tagging,\n // so elements that appear MID-step get masked the frame they appear.\n await driver.installMaskRules(maskRules);\n await driver.goto(spec.app.url);\n await applyMasksAndSample(driver, maskRules, writer, now);\n await driver.settle(settleCfg);\n if (spec.app.assertLoggedIn) {\n // Fail FAST on stale auth instead of confidently filming the login page.\n await driver\n .expectState(parseLocator(spec.app.assertLoggedIn), { visible: true }, 8000)\n .catch(() => {\n throw new Error(\n `assertLoggedIn failed: ${spec.app.assertLoggedIn} not visible — storageState stale? Re-run: playhead login ${spec.app.url}`,\n );\n });\n }\n // Guarantee PRE-first-action footage: heavy initial loads can stall the first grabs (CDP\n // contention), and a first frame that lands after the first click makes the before-state\n // unprovable — for verification and for the viewer alike.\n if (!opts.fromScene) await driver.captureNow();\n\n let steps = flattenSteps(spec);\n const totalSteps = steps.length;\n if (opts.fromScene) {\n const idx = steps.findIndex((s) => s.sceneId === opts.fromScene);\n if (idx < 0) throw new Error(`--from-scene: no scene with id \"${opts.fromScene}\" in the spec`);\n log.info(`fast-forwarding ${idx} step(s) to scene \"${opts.fromScene}\" (state only, not filmed)`);\n for (const pre of steps.slice(0, idx)) {\n currentStepRef = `${pre.sceneId}/${pre.stepIndex} (fast-forward)`;\n await fastForwardStep(driver, pre.step);\n }\n currentStepRef = '';\n steps = steps.slice(idx);\n await driver.settle(settleCfg);\n await startFilming();\n await driver.captureNow();\n }\n\n for (const addressed of steps) {\n currentStepRef = `${addressed.sceneId}/${addressed.stepIndex}`;\n if (now() > CAPTURE_DEADLINE_MS) {\n throw new Error(`capture watchdog: exceeded ${CAPTURE_DEADLINE_MS / 60000} minutes at step ${currentStepRef}`);\n }\n log.step(`${addressed.ordinal}/${totalSteps} ${describeStep(addressed)}`);\n const event = await withStepBudget(\n executeStep(driver, addressed, { rel, now }, spec.app.url),\n STEP_BUDGET_MS,\n currentStepRef,\n );\n // Re-tag masks (new DOM may match rules), then settle.\n await applyMasksAndSample(driver, maskRules, writer, now);\n await driver.settle(settleCfg);\n // A focus HINT naming a third locator (\"click here, LOOK there\") points at the step's\n // PAYOFF — waiting for it is part of settling this step. Poll briefly: the payoff often\n // appears a beat after network-idle (the app's own mutation delay), and stamping tSettled\n // before it exists would freeze the hold on pre-payoff footage.\n const focus = 'focus' in addressed.step ? addressed.step.focus : undefined;\n if (focus && focus !== 'target' && focus !== 'wide') {\n const loc = parseLocator(focus);\n for (let i = 0; i < 10 && !event.focusTarget; i++) {\n event.focusTarget = await driver.tryMeasure(loc);\n if (!event.focusTarget) await sleep(250);\n }\n if (!event.focusTarget) {\n log.warn(`${addressed.sceneId}/${addressed.stepIndex}: focus locator never appeared: ${focus}`);\n }\n }\n await ensurePostActionFrame(driver, event.tAction, rel);\n // tSettled must point at a frame that reflects the settled state (payoff included).\n // captureNow above guarantees a fresh one, so stamp after it — even instant hash-route\n // navigations whose settle returned in ~100ms then have on-film proof of their effect.\n event.tSettled = now();\n if (event.targetPre && event.locator) {\n event.targetPost = await driver.tryMeasure(parseLocator(event.locator));\n }\n if (addressed.step.action === 'type' && addressed.step.mask && event.locator) {\n const info = await driver.tryMeasure(parseLocator(event.locator));\n if (info) writer.addMaskSample({ t: now(), rects: [{ style: 'solid', ...info.bbox }] });\n }\n events.push(event);\n }\n currentStepRef = '';\n\n // Trailing beat so the final state has footage to hold on.\n await driver.settle(settleCfg);\n await driver.captureNow();\n await sleep(400);\n return { bundleDir };\n } catch (e) {\n const message = (e as Error).message;\n failure = { stepRef: currentStepRef || '(setup)', message };\n // Failure diagnostics, best-effort: where we were and what the page looked like.\n try {\n const aria = await driver.ariaSnapshot();\n const url = driver.currentUrl();\n const { writeFile } = await import('node:fs/promises');\n await writeFile(\n join(bundleDir, 'failure.json'),\n JSON.stringify({ stepRef: failure.stepRef, message, url, at: new Date().toISOString() }, null, 2),\n );\n if (aria) await writeFile(join(bundleDir, 'failure-aria.txt'), aria);\n } catch {\n /* diagnostics are best-effort */\n }\n // A capture-time failure is the APP breaking the flow — exit code 1, not an infra error.\n throw new FlowError(\n `${message}\\n (partial bundle with ${writer.frameCount()} frames saved to ${bundleDir} — failure.json has the details)`,\n );\n } finally {\n // Finalize the bundle EVEN ON FAILURE: frames/index.json + manifest are what make the\n // captured footage openable, and a failed run's footage is the most valuable footage.\n await driver.stopCapture().catch(() => {});\n // Console/pageerror/dialog/popup evidence — what bug-repro needs and failure diagnosis reads.\n try {\n const consoleLog = driver.consoleLog();\n if (consoleLog.length > 0) {\n const { writeFile } = await import('node:fs/promises');\n await writeFile(\n join(bundleDir, 'console.json'),\n JSON.stringify(consoleLog.map((c) => ({ ...c, t: rel(c.t) })), null, 2),\n );\n }\n } catch {\n /* best-effort */\n }\n const durationMs = now();\n const eventLog: EventLog = {\n schema: 'playhead/events@1',\n meta: {\n viewport,\n dpr,\n frameW: 0, // finalized by writer from the first frame's real dimensions\n frameH: 0,\n clockOffsetMs,\n startedAtIso: new Date(t0).toISOString(),\n durationMs,\n appUrl: spec.app.url,\n },\n events,\n };\n try {\n const manifest = await writer.finish({\n spec,\n events: eventLog,\n appUrl: spec.app.url,\n viewport,\n dpr,\n clockOffsetMs,\n durationMs,\n ...(failure ? { partial: true, failure } : {}),\n });\n if (!failure) {\n log.ok(`bundle: ${manifest.frameCount} frames, ${(durationMs / 1000).toFixed(1)}s → ${bundleDir}`);\n } else {\n log.warn(`partial bundle: ${manifest.frameCount} frames up to ${failure.stepRef} → ${bundleDir}`);\n }\n } catch (finishErr) {\n log.warn(`could not finalize bundle: ${(finishErr as Error).message}`);\n }\n await driver.close();\n }\n}\n\n/** Advance app state with no filming, no cursor choreography, minimal waits (fast-forward\n * pre-roll for --from-scene). Blind `wait: ms` sleeps are skipped; expects are best-effort. */\nasync function fastForwardStep(driver: Driver, step: import('../spec/schema.js').Step): Promise<void> {\n const T = step.timeout ?? 8000;\n switch (step.action) {\n case 'goto':\n await driver.goto(step.url);\n break;\n case 'click':\n case 'dblclick': {\n const t = await driver.resolveTarget(parseLocator(step.target), T);\n await driver.clickAt(rectCenter(t.bbox), { double: step.action === 'dblclick' });\n break;\n }\n case 'hover':\n break; // no lasting state\n case 'type': {\n const t = await driver.resolveTarget(parseLocator(step.target), T);\n await driver.clickAt(rectCenter(t.bbox));\n await driver.typeText(step.text, 0);\n break;\n }\n case 'press':\n await driver.press(step.keys);\n break;\n case 'select':\n await driver.selectOption(parseLocator(step.target), step.value);\n break;\n case 'scroll':\n if (step.target) await driver.scrollIntoView(parseLocator(step.target));\n else if (step.by) await driver.scrollBy(step.by);\n await driver.waitForScrollSettle(1500);\n break;\n case 'expect':\n await driver\n .expectState(parseLocator(step.target), { ...(step.visible !== undefined ? { visible: step.visible } : {}) }, T)\n .catch(() => {});\n break;\n case 'wait':\n if (step.for) {\n await driver.expectState(parseLocator(step.for), { visible: step.state !== 'hidden' }, T).catch(() => {});\n }\n break;\n }\n await driver.settle({ idleMs: 200, capMs: 2500 });\n}\n\n/** Fail a step with its ref when it exceeds the budget, instead of hanging the capture. */\nfunction withStepBudget<T>(p: Promise<T>, ms: number, stepRef: string): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(\n () => reject(new Error(`step ${stepRef} exceeded its ${ms / 1000}s budget`)),\n ms,\n );\n p.then(\n (v) => { clearTimeout(timer); resolve(v); },\n (e) => { clearTimeout(timer); reject(e); },\n );\n });\n}\n\ninterface Clock {\n rel: (nodeMs: number) => number;\n now: () => number;\n}\n\nasync function executeStep(driver: Driver, addressed: AddressedStep, clock: Clock, appUrl: string): Promise<ActionEvent> {\n const { step, sceneId, stepIndex, ordinal } = addressed;\n const base: ActionEvent = {\n type: 'action',\n kind: step.action,\n sceneId,\n stepIndex,\n ordinal,\n cursorPath: [],\n tStart: clock.now(),\n tAction: 0,\n tActionEnd: 0,\n tSettled: 0,\n ...(step.caption ? { caption: step.caption } : {}),\n ...(step.narration ? { narration: step.narration } : {}),\n ...(step.shot ? { shot: step.shot } : {}),\n ...('focus' in step && step.focus ? { focus: step.focus } : {}),\n };\n // Per-step override for target-resolution / expectation budgets.\n const budgetMs = step.timeout ?? TARGET_TIMEOUT_MS;\n\n switch (step.action) {\n case 'goto': {\n // Relative URLs resolve against app.url, so a spec can say `goto: /deals` and be pointed\n // at any environment by changing one line.\n const url = new URL(step.url, appUrl).href;\n base.locator = url;\n base.tAction = clock.now();\n await driver.goto(url);\n base.tActionEnd = clock.now();\n return base;\n }\n case 'click':\n case 'dblclick':\n case 'hover': {\n base.locator = step.target;\n const loc = parseLocator(step.target);\n const pre = await driver.resolveTarget(loc, budgetMs);\n base.targetPre = pre;\n base.cursorPath = await moveToTarget(driver, pre, clock);\n if (step.action === 'hover') {\n base.tAction = clock.now();\n base.tActionEnd = base.tAction;\n } else {\n // Cosmetic cursor is already on the target; the ACTION goes through locator.click so\n // actionability + hit-target verification + retry come for free (a raw coordinate\n // click is silently redirected by anything drifting under the point).\n const { tDown, tUp } = await driver.actClick(loc, {\n double: step.action === 'dblclick',\n timeoutMs: budgetMs,\n });\n base.tAction = clock.rel(tDown);\n base.tActionEnd = clock.rel(tUp);\n }\n return base;\n }\n case 'type': {\n base.locator = step.target;\n const loc = parseLocator(step.target);\n const pre = await driver.resolveTarget(loc, budgetMs);\n base.targetPre = pre;\n base.cursorPath = await moveToTarget(driver, pre, clock);\n await driver.actClick(loc, { timeoutMs: budgetMs });\n if (step.mask) {\n // Tag before any keystroke lands; the overlay stays for the rest of the capture.\n await driver.setTypingMask(loc);\n }\n const { tFirst, tLast } = await driver.typeText(step.text, TYPE_DELAY_MS);\n base.tAction = clock.rel(tFirst);\n base.tActionEnd = clock.rel(tLast);\n base.masked = step.mask;\n base.typedText = step.mask ? '•'.repeat(Math.min(step.text.length, 8)) : step.text;\n return base;\n }\n case 'press': {\n base.locator = step.keys;\n const { tDown } = await driver.press(step.keys);\n base.tAction = clock.rel(tDown);\n base.tActionEnd = clock.now();\n return base;\n }\n case 'select': {\n base.locator = step.target;\n const loc = parseLocator(step.target);\n const pre = await driver.resolveTarget(loc, budgetMs);\n base.targetPre = pre;\n base.cursorPath = await moveToTarget(driver, pre, clock);\n // No raw pre-click: it opens the native popup that nothing dismisses. selectOption\n // handles focus + change events; the cursor visit above supplies the visual beat.\n base.tAction = clock.now();\n await driver.selectOption(loc, step.value);\n base.typedText = step.value;\n base.tActionEnd = clock.now();\n return base;\n }\n case 'scroll': {\n base.tAction = clock.now();\n if (step.target) {\n base.locator = step.target;\n const loc = parseLocator(step.target);\n await driver.scrollIntoView(loc);\n await driver.waitForScrollSettle(2500); // measure only once the scroll has stopped\n base.targetPre = await driver.tryMeasure(loc);\n } else if (step.by) {\n await driver.scrollBy(step.by);\n await driver.waitForScrollSettle(2500);\n }\n base.tActionEnd = clock.now();\n return base;\n }\n case 'expect': {\n base.locator = step.target;\n const loc = parseLocator(step.target);\n await driver.expectState(\n loc,\n { ...(step.visible !== undefined ? { visible: step.visible } : {}), ...(step.text !== undefined ? { text: step.text } : {}), ...(step.count !== undefined ? { count: step.count } : {}) },\n step.timeout ?? EXPECT_TIMEOUT_MS,\n );\n base.targetPre = await driver.tryMeasure(loc);\n base.tAction = clock.now();\n base.tActionEnd = base.tAction;\n return base;\n }\n case 'wait': {\n base.tAction = clock.now();\n if (step.for) {\n // Structured wait: block on an element state instead of a blind sleep.\n base.locator = step.for;\n await driver.expectState(\n parseLocator(step.for),\n { visible: step.state !== 'hidden' },\n step.timeout ?? EXPECT_TIMEOUT_MS,\n );\n } else {\n await sleep(step.ms ?? 0);\n }\n base.tActionEnd = clock.now();\n return base;\n }\n }\n}\n\nasync function moveToTarget(driver: Driver, target: TargetInfo, clock: Clock): Promise<CursorWaypoint[]> {\n const to = rectCenter(target.bbox);\n const travel = clamp(250 + dist(driver.cursorPos(), to) * 0.5, 300, 700);\n const waypoints = await driver.moveCursor(to, travel);\n return waypoints.map((w) => ({ x: round1(w.x), y: round1(w.y), t: round1(clock.rel(w.t)) }));\n}\n\n/**\n * Guarantee a fresh frame reflecting the settled post-action state. Always captures one (not\n * only when footage looks stale): a fast hash-route navigation settles in ~100ms, and without a\n * forced post-settle frame the \"after\" sample can land on the pre-navigation paint.\n */\nasync function ensurePostActionFrame(\n driver: Driver,\n tAction: number,\n rel: (nodeMs: number) => number,\n): Promise<void> {\n await sleep(24); // let the post-action paint flush\n await driver.captureNow();\n if (rel(driver.lastFrameAt()) <= tAction) {\n for (let i = 0; i < 2 && rel(driver.lastFrameAt()) <= tAction; i++) {\n await sleep(40);\n await driver.captureNow();\n }\n if (rel(driver.lastFrameAt()) <= tAction) {\n log.warn(`no captured frame after action at t=${tAction.toFixed(0)}ms — footage may hold a stale frame`);\n }\n }\n}\n\nasync function applyMasksAndSample(\n driver: Driver,\n rules: MaskInstruction[],\n writer: BundleWriter,\n now: () => number,\n): Promise<void> {\n if (rules.length === 0) return;\n const rects = await driver.applyMasks(rules);\n if (rects.length > 0) writer.addMaskSample({ t: now(), rects });\n}\n\nfunction describeStep(a: AddressedStep): string {\n const s = a.step;\n switch (s.action) {\n case 'goto':\n return `goto ${s.url}`;\n case 'type':\n return `type into ${s.target}${s.mask ? ' (masked)' : ''}`;\n case 'press':\n return `press ${s.keys}`;\n case 'wait':\n return `wait ${s.ms}ms`;\n case 'scroll':\n return `scroll ${s.target ?? JSON.stringify(s.by)}`;\n default:\n return `${s.action} ${'target' in s ? s.target : ''}`;\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n\nfunction round1(n: number): number {\n return Math.round(n * 10) / 10;\n}\n","import { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { BundleData, BundleManifest, FrameIndexEntry, MaskSample } from './types.js';\nimport type { EventLog } from '../capture/events.js';\n\nexport async function openBundle(dir: string): Promise<BundleData> {\n const [manifestRaw, eventsRaw, framesRaw, masksRaw] = await Promise.all([\n readFile(join(dir, 'manifest.json'), 'utf8'),\n readFile(join(dir, 'events.json'), 'utf8'),\n readFile(join(dir, 'frames', 'index.json'), 'utf8'),\n readFile(join(dir, 'masks.json'), 'utf8').catch(() => '[]'),\n ]);\n const manifest = JSON.parse(manifestRaw) as BundleManifest;\n if (manifest.schema !== 'playhead/bundle@1') {\n throw new Error(`Unsupported bundle schema \"${manifest.schema}\" in ${dir}`);\n }\n const events = JSON.parse(eventsRaw) as EventLog;\n const frames = JSON.parse(framesRaw) as FrameIndexEntry[];\n const maskSamples = JSON.parse(masksRaw) as MaskSample[];\n if (frames.length === 0) throw new Error(`Bundle ${dir} contains no frames`);\n return { dir, manifest, events, frames, maskSamples };\n}\n\n/** Index of the latest frame with t ≤ tMs (hold semantics); clamps to the first frame. */\nexport function frameIndexForTime(frames: FrameIndexEntry[], tMs: number): number {\n let lo = 0;\n let hi = frames.length - 1;\n if (tMs <= frames[0]!.t) return 0;\n if (tMs >= frames[hi]!.t) return hi;\n while (lo < hi) {\n const mid = (lo + hi + 1) >> 1;\n if (frames[mid]!.t <= tMs) lo = mid;\n else hi = mid - 1;\n }\n return lo;\n}\n\nexport function framePath(bundle: BundleData, index: number): string {\n return join(bundle.dir, 'frames', bundle.frames[index]!.f);\n}\n","import { existsSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\nimport { createRequire } from 'node:module';\nimport { GlobalFonts } from '@napi-rs/canvas';\nimport type { Spec } from '../spec/schema.js';\n\nexport interface ResolvedTheme {\n name: string;\n /** Accent color for cursor ripple, badges, highlights. */\n accent: string;\n /** Title-card and letterbox background. */\n bg: string;\n bgSubtle: string;\n /** Caption card background (rgba string). */\n surface: string;\n onSurface: string;\n onSurfaceDim: string;\n fontFamily: string;\n captionFontPx: number;\n captionMinFontPx: number;\n captionMaxLines: number;\n captionPosition: 'bottom' | 'top' | 'off';\n radius: number;\n}\n\nconst DEFAULT_THEME: ResolvedTheme = {\n name: 'default',\n accent: '#5B8DEF',\n bg: '#12161f',\n bgSubtle: '#1a2029',\n surface: 'rgba(18, 22, 31, 0.92)',\n onSurface: '#ffffff',\n onSurfaceDim: 'rgba(255,255,255,0.72)',\n fontFamily: 'Inter',\n // Broadcast-subtitle scale: ~3.3% of a 1080p frame. At the old 26px the caption was the same\n // size as the app's upscaled body copy and read as part of the UI, not narration above it.\n captionFontPx: 36,\n captionMinFontPx: 28,\n captionMaxLines: 2,\n captionPosition: 'bottom',\n radius: 12,\n};\n\nexport function resolveTheme(spec: Spec): ResolvedTheme {\n return {\n ...DEFAULT_THEME,\n ...(spec.theme.accent ? { accent: spec.theme.accent } : {}),\n captionPosition: spec.theme.captions,\n };\n}\n\nlet fontsRegistered = false;\n\n/** Register bundled Inter faces so rendering is deterministic across machines. */\nexport function registerFonts(): void {\n if (fontsRegistered) return;\n fontsRegistered = true;\n const require = createRequire(import.meta.url);\n let pkgDir: string;\n try {\n pkgDir = dirname(require.resolve('@expo-google-fonts/inter/package.json'));\n } catch {\n throw new Error('Font package @expo-google-fonts/inter not found — run npm install');\n }\n const faces: [string, string][] = [\n ['400Regular/Inter_400Regular.ttf', 'Inter'],\n ['500Medium/Inter_500Medium.ttf', 'Inter Medium'],\n ['600SemiBold/Inter_600SemiBold.ttf', 'Inter SemiBold'],\n ['700Bold/Inter_700Bold.ttf', 'Inter Bold'],\n ];\n for (const [rel, family] of faces) {\n const p = join(pkgDir, rel);\n if (existsSync(p)) GlobalFonts.registerFromPath(p, family);\n }\n}\n","import type { Rect, Point, CameraState } from '../shared/geometry.js';\nimport type { BezierParams } from '../shared/easing.js';\nimport type { ResolvedTheme } from '../theme/index.js';\nimport type { ActionKind } from '../capture/events.js';\n\nexport interface OutputProfile {\n width: number;\n height: number;\n fps: number;\n /** Output-px margins content must respect; bottom includes the caption band. */\n safeArea: { top: number; right: number; bottom: number; left: number };\n zoomQuantums: number[];\n /** Minimum rendered size (output px) of a focus rect's smaller dimension. */\n minFocusPx: number;\n captionMaxWidth: number;\n /**\n * The stage: footage renders inside `content` (a matte with rounded corners, shadow, and an\n * optional browser-chrome bar above it) instead of edge-to-edge. ALL camera math — planner,\n * renderer, cursor projection, verification — runs in content space via `stageContent()`,\n * so plan and pixels can never disagree about where footage lives. Absent = full-frame.\n */\n stage?: {\n /** Output-px rect the footage is drawn into. */\n content: Rect;\n /** Height of the browser-chrome bar drawn directly above `content` (0 = none). */\n chromeH: number;\n radius: number;\n };\n}\n\n/** The rect footage renders into: the stage's content when present, else the full frame. */\nexport function stageContent(profile: OutputProfile): Rect {\n return profile.stage?.content ?? { x: 0, y: 0, w: profile.width, h: profile.height };\n}\n\n/** Compute a stage for the profile: uniform matte margins + a chrome bar, preserving the\n * content's aspect (= the capture viewport's), so camera math scales cleanly. */\nexport function withStage(profile: OutputProfile, chrome: boolean): OutputProfile {\n const { width, height } = profile;\n const marginY = Math.round(height * 0.055);\n const chromeH = chrome ? Math.round(44 * (Math.min(width, height) / 1080)) : 0;\n const contentH = height - 2 * marginY - chromeH;\n const contentW = Math.round(contentH * (width / height));\n const x = Math.round((width - contentW) / 2);\n const y = marginY + chromeH;\n return {\n ...profile,\n stage: { content: { x, y, w: contentW, h: contentH }, chromeH, radius: Math.round(14 * (Math.min(width, height) / 1080)) },\n };\n}\n\nexport const PROFILE_16x9: OutputProfile = {\n width: 1920,\n height: 1080,\n fps: 30,\n safeArea: { top: 54, right: 96, bottom: 160, left: 96 },\n zoomQuantums: [1.0, 1.15, 1.3, 1.5, 1.7, 2.0],\n minFocusPx: 110,\n captionMaxWidth: 1040,\n};\n\n/** Portrait: reserve more top/bottom for platform UI chrome; captions span most of the width. */\nexport const PROFILE_9x16: OutputProfile = {\n width: 1080,\n height: 1920,\n fps: 30,\n safeArea: { top: 230, right: 56, bottom: 320, left: 56 },\n zoomQuantums: [1.0, 1.15, 1.3, 1.5, 1.7, 2.0],\n minFocusPx: 96,\n captionMaxWidth: 980,\n};\n\nexport const PROFILE_1x1: OutputProfile = {\n width: 1080,\n height: 1080,\n fps: 30,\n safeArea: { top: 80, right: 72, bottom: 200, left: 72 },\n zoomQuantums: [1.0, 1.15, 1.3, 1.5, 1.7, 2.0],\n minFocusPx: 100,\n captionMaxWidth: 940,\n};\n\n/** Resolve the output profile for an aspect, overlaying the spec's resolution + fps. */\nexport function profileForAspect(\n aspect: '16:9' | '9:16' | '1:1',\n resolution: { w: number; h: number },\n fps: number,\n): OutputProfile {\n const base = aspect === '9:16' ? PROFILE_9x16 : aspect === '1:1' ? PROFILE_1x1 : PROFILE_16x9;\n const scaleX = resolution.w / base.width;\n const scaleY = resolution.h / base.height;\n return {\n ...base,\n width: resolution.w,\n height: resolution.h,\n fps,\n safeArea: {\n top: Math.round(base.safeArea.top * scaleY),\n bottom: Math.round(base.safeArea.bottom * scaleY),\n left: Math.round(base.safeArea.left * scaleX),\n right: Math.round(base.safeArea.right * scaleX),\n },\n captionMaxWidth: Math.round(base.captionMaxWidth * scaleX),\n };\n}\n\nexport type TimeSegment =\n | { kind: 'source'; outStart: number; outEnd: number; srcStart: number; srcEnd: number }\n | { kind: 'freeze'; outStart: number; outEnd: number; srcAt: number }\n | { kind: 'card'; outStart: number; outEnd: number; cardId: string };\n\nexport interface CameraKeyframe {\n tOut: number;\n state: CameraState;\n /** Ease applied travelling from the previous keyframe to this one. */\n ease: BezierParams;\n}\n\nexport interface CursorSegment {\n tStart: number;\n tEnd: number;\n /** Arc-length-resampled polyline in viewport space. */\n path: Point[];\n clickAtEnd: boolean;\n}\n\nexport interface ClickRipple {\n tOut: number;\n /** Viewport space. */\n x: number;\n y: number;\n}\n\nexport interface CaptionOverlay {\n kind: 'caption';\n stepRef: string;\n ordinal: number;\n totalSteps: number;\n /** Whether to draw the numbered step badge (off for demo/release/social/factual styles). */\n showBadge: boolean;\n text: string;\n lines: string[];\n fontPx: number;\n /** Output-space card rect as rendered. */\n box: Rect;\n tStart: number;\n tEnd: number;\n shrunk: boolean;\n truncated: boolean;\n}\n\nexport interface TitleCardOverlay {\n kind: 'titleCard';\n cardId: string;\n title: string;\n subtitle?: string;\n tStart: number;\n tEnd: number;\n}\n\nexport interface DipTransition {\n kind: 'dip';\n tStart: number;\n tEnd: number;\n /** 'in' fades FROM the theme background into footage (post-title); 'out' fades footage\n * INTO the background (pre-end-card). Default 'in'. */\n direction?: 'in' | 'out';\n}\n\n/**\n * Act→react camera windows for a step that clicks one place and focuses another (\"click here,\n * LOOK there\"): the camera frames the action target around the beat, then hands off to the\n * focused payoff for the settled hold. Shared by the planner (to emit the handoff) and the\n * verifier (to assert each rect during ITS window) so plan and checks agree by construction.\n * Returns null when the step has no handoff (single rect, or too little hold to travel in).\n */\nexport function actReactWindows(step: StepMapEntry): {\n act: { rect: Rect; from: number; to: number };\n react: { rect: Rect; from: number; to: number };\n} | null {\n if (!step.focusRectVp || !step.targetRectVp) return null;\n if (step.focus === 'target' || step.focus === 'wide') return null;\n if (step.outEnd - step.outBeat < 1600) return null; // not enough hold to travel and settle\n return {\n act: { rect: step.targetRectVp, from: step.outBeat - 60, to: step.outBeat + 400 },\n react: { rect: step.focusRectVp, from: step.outBeat + 1100, to: step.outEnd },\n };\n}\n\n/** A persistent elapsed-time readout (bug-repro evidence). Rendered against the output clock. */\nexport interface ElapsedClockOverlay {\n kind: 'elapsedClock';\n tStart: number;\n tEnd: number;\n /** Output ms to subtract so the clock reads 0 at the first real action, not the title card. */\n zeroAtMs: number;\n}\n\n/** A brief scene-title label at each new scene (demo/before-after narrative structure). */\nexport interface ChapterLabelOverlay {\n kind: 'chapterLabel';\n title: string;\n ordinal: number;\n tStart: number;\n tEnd: number;\n}\n\n/** Closing card for a FAILED capture: the failure clip ends on what broke and why. */\nexport interface FailureCardOverlay {\n kind: 'failureCard';\n stepRef: string;\n message: string;\n tStart: number;\n tEnd: number;\n}\n\nexport type OverlayEntry =\n | CaptionOverlay\n | TitleCardOverlay\n | DipTransition\n | ElapsedClockOverlay\n | ChapterLabelOverlay\n | FailureCardOverlay;\n\nexport interface StepMapEntry {\n stepRef: string;\n sceneId: string;\n ordinal: number;\n kind: ActionKind;\n locator?: string;\n /** True for masked type steps — their visible effect is intentionally suppressed. */\n masked?: boolean;\n /** Viewport-space target rect at action time (bboxPre), when the step had a target. */\n targetRectVp?: Rect;\n /** Camera hint from the spec: 'target' | 'wide' | a locator string. */\n focus?: string;\n /** Shot-boundary control from the spec: 'cut' | 'continue'. */\n shot?: string;\n /** Measured rect of a locator-valued focus hint at the settled moment — the payoff the\n * camera should frame instead of the action target (\"click here, look there\"). */\n focusRectVp?: Rect;\n outStart: number;\n /** Output-clock moment the action lands. */\n outBeat: number;\n outEnd: number;\n srcAction: number;\n srcSettled: number;\n}\n\nexport interface ComposeDiagnostics {\n overflows: { stepRef: string; text: string; action: 'shrunk' | 'truncated' }[];\n cameraFallbacks: string[];\n clockWarnings: string[];\n}\n\nexport interface ComposeManifest {\n schema: 'playhead/compose@1';\n profile: OutputProfile;\n viewport: { w: number; h: number };\n durationMs: number;\n totalFrames: number;\n segments: TimeSegment[];\n camera: CameraKeyframe[];\n cursor: CursorSegment[];\n ripples: ClickRipple[];\n overlays: OverlayEntry[];\n /** Cross-dissolve windows at scene boundaries: old footage (held at srcFrom) fades into new. */\n transitions?: { tStart: number; tEnd: number; srcFrom: number }[];\n steps: StepMapEntry[];\n theme: ResolvedTheme;\n diagnostics: ComposeDiagnostics;\n bundleHashes: { events: string; framesIndex: string };\n videoSha256?: string;\n /** Present when voice narration was muxed in. `clips` records where each spoken line landed\n * on the output clock, so verification can reason about voice-covered windows. */\n audio?: {\n narrated: boolean;\n provider: string;\n voice: string;\n lines: number;\n clips?: { stepRef: string; tStart: number; durMs: number }[];\n };\n}\n","import type { OutputKind } from '../spec/schema.js';\n\nexport type CaptionStyle = 'instruction' | 'factual' | 'chapter';\n\n/** How a given output kind is composed — the same capture, a different treatment. */\nexport interface KindProfile {\n kind: OutputKind;\n /** Default pacing when the spec doesn't set one. */\n pacing: 'relaxed' | 'normal' | 'brisk';\n /** Caption phrasing: instructional (\"Click X\"), factual repro (\"Step 1 — click X\"), or narrative. */\n captionStyle: CaptionStyle;\n /** Prefix each caption with its number (\"1.\", \"2.\" …). */\n numberedCaptions: boolean;\n /** Draw a running elapsed-time clock (bug evidence). */\n elapsedClock: boolean;\n /** Insert a full-frame chapter card at each new scene (demo narrative structure). */\n chapterCards: boolean;\n /** Hold on the final state this long (ms) — bug-repro dwells on the defect. */\n outroMs: number;\n /** Typed input is shown as evidence even in fields that look sensitive (repro needs the values). */\n showTypedInput: boolean;\n /** Composition-driven camera emphasis + click spotlights. Off for bug-repro, which must stay\n * a literal record of the screen. */\n cameraEmphasis: boolean;\n /** Render footage on a stage (matte + rounded card + browser chrome) instead of edge-to-edge. */\n stage: boolean;\n}\n\nconst BASE: Omit<KindProfile, 'kind'> = {\n pacing: 'normal',\n captionStyle: 'instruction',\n numberedCaptions: true,\n elapsedClock: false,\n chapterCards: false,\n outroMs: 1600,\n showTypedInput: true,\n cameraEmphasis: true,\n stage: true,\n};\n\nconst PROFILES: Record<OutputKind, KindProfile> = {\n walkthrough: { kind: 'walkthrough', ...BASE },\n demo: {\n kind: 'demo',\n ...BASE,\n pacing: 'relaxed',\n captionStyle: 'chapter',\n numberedCaptions: false,\n chapterCards: true,\n outroMs: 2200,\n },\n 'bug-repro': {\n kind: 'bug-repro',\n ...BASE,\n pacing: 'normal',\n captionStyle: 'factual',\n numberedCaptions: true,\n elapsedClock: true,\n outroMs: 3000,\n // A repro is EVIDENCE: no directorial zoom, no spotlights, no matte — the literal screen.\n cameraEmphasis: false,\n stage: false,\n },\n 'before-after': { kind: 'before-after', ...BASE, pacing: 'normal', chapterCards: true, numberedCaptions: false },\n release: { kind: 'release', ...BASE, pacing: 'brisk', numberedCaptions: false, outroMs: 1400 },\n social: { kind: 'social', ...BASE, pacing: 'brisk', numberedCaptions: false, outroMs: 1400 },\n};\n\nexport function kindProfile(kind: OutputKind): KindProfile {\n return PROFILES[kind] ?? PROFILES.walkthrough;\n}\n","import type { Rect, Point } from '../shared/geometry.js';\n\n/** All event/frame times are milliseconds relative to capture start, on one normalized clock. */\n\nexport interface TargetInfo {\n role: string | null;\n accessibleName: string | null;\n /** Viewport-relative (client) CSS px — exactly the space the captured frames show. */\n bbox: Rect;\n /** Window scroll offsets at measure time, CSS px. */\n scroll: Point;\n}\n\nexport interface CursorWaypoint {\n x: number;\n y: number;\n t: number;\n}\n\nexport type ActionKind =\n | 'goto'\n | 'click'\n | 'dblclick'\n | 'hover'\n | 'type'\n | 'press'\n | 'select'\n | 'scroll'\n | 'expect'\n | 'wait';\n\nexport interface ActionEvent {\n type: 'action';\n kind: ActionKind;\n sceneId: string;\n stepIndex: number;\n /** Global 1-based step number across the whole spec. */\n ordinal: number;\n locator?: string;\n targetPre?: TargetInfo | null;\n targetPost?: TargetInfo | null;\n cursorPath: CursorWaypoint[];\n /** Redacted to bullets when masked — the real string never enters any artifact. */\n typedText?: string;\n masked?: boolean;\n /** Caption override from the spec, carried through for the compositor. */\n caption?: string;\n /** Spoken-line override from the spec (TTS narration), carried as a record — the live spec\n * wins at compose time. */\n narration?: string;\n /** Camera-shot boundary control from the spec ('cut' | 'continue'). */\n shot?: string;\n /** Camera hint from the spec: 'target' | 'wide' | a locator string. */\n focus?: string;\n /** When `focus` names a locator, its measured geometry at the settled moment — the payoff\n * rect the camera should frame (\"click here, look there\"). */\n focusTarget?: TargetInfo | null;\n tStart: number;\n /** Moment the action lands (mouse-down, first keystroke, key chord). */\n tAction: number;\n /** Action fully delivered (mouse-up, last keystroke). */\n tActionEnd: number;\n /** UI settled after the action (network idle + layout stable). */\n tSettled: number;\n}\n\nexport interface NavigationEvent {\n type: 'navigation';\n url: string;\n t: number;\n}\n\nexport type CaptureEvent = ActionEvent | NavigationEvent;\n\nexport interface EventLogMeta {\n viewport: { w: number; h: number };\n dpr: number;\n /** Actual pixel dimensions of captured frames (source of truth for frame-space scale). */\n frameW: number;\n frameH: number;\n clockOffsetMs: number;\n startedAtIso: string;\n durationMs: number;\n appUrl: string;\n}\n\nexport interface EventLog {\n schema: 'playhead/events@1';\n meta: EventLogMeta;\n events: CaptureEvent[];\n}\n\nexport function actionEvents(log: EventLog): ActionEvent[] {\n return log.events.filter((e): e is ActionEvent => e.type === 'action');\n}\n\nexport function navigationEvents(log: EventLog): NavigationEvent[] {\n return log.events.filter((e): e is NavigationEvent => e.type === 'navigation');\n}\n","/** Narration placement constants, shared by the timeline (dwell fitting) and the muxer. */\n\n/** A step's spoken line starts this long after the step (and its caption) begin. */\nexport const AUDIO_LEAD_MS = 150;\n/** Silence kept after a spoken line finishes before the step is allowed to end. */\nexport const AUDIO_TAIL_MS = 450;\n","import type { EventLog, ActionEvent, ActionKind } from '../../capture/events.js';\nimport { actionEvents } from '../../capture/events.js';\nimport type { TimeSegment, StepMapEntry } from '../types.js';\nimport { AUDIO_LEAD_MS, AUDIO_TAIL_MS } from '../../audio/timing.js';\n\nexport interface PacingConfig {\n factor: number;\n titleCardMs: number;\n introMaxMs: number;\n outroMs: number;\n idleGapMaxMs: number;\n idleGapOutMs: number;\n minStepMs: number;\n maxTypeOutMs: number;\n holds: Record<ActionKind, number>;\n}\n\nexport function pacingConfig(mode: 'relaxed' | 'normal' | 'brisk', kind?: { outroMs: number }): PacingConfig {\n const factor = mode === 'relaxed' ? 1.25 : mode === 'brisk' ? 0.8 : 1;\n return {\n factor,\n titleCardMs: 2200,\n introMaxMs: 1200,\n outroMs: kind?.outroMs ?? 1600,\n idleGapMaxMs: 1500,\n idleGapOutMs: 400,\n minStepMs: 1800 * factor,\n maxTypeOutMs: 4500,\n holds: {\n goto: 1200 * factor,\n click: 600 * factor,\n dblclick: 600 * factor,\n hover: 450 * factor,\n type: 450 * factor,\n press: 450 * factor,\n select: 600 * factor,\n scroll: 350 * factor,\n expect: 800 * factor,\n wait: 150,\n },\n };\n}\n\nexport interface TimelinePlan {\n segments: TimeSegment[];\n steps: StepMapEntry[];\n durationMs: number;\n}\n\n/**\n * Build the output timeline: title card, per-step source spans with compose-time\n * pacing (idle-gap trimming, post-action freezes, min-step extension), and an\n * outro hold on the final state.\n */\nexport function buildTimeline(log: EventLog, cfg: PacingConfig, audioMs?: Map<string, number>): TimelinePlan {\n const events = actionEvents(log);\n const segments: TimeSegment[] = [];\n const steps: StepMapEntry[] = [];\n\n segments.push({ kind: 'card', outStart: 0, outEnd: cfg.titleCardMs, cardId: 'title' });\n let out = cfg.titleCardMs;\n let src = events.length > 0 ? Math.max(0, events[0]!.tStart - cfg.introMaxMs) : 0;\n\n for (const e of events) {\n // Gap between the previous settle and this step's start.\n const gap = e.tStart - src;\n if (gap > 1) {\n const outDur = gap > cfg.idleGapMaxMs ? cfg.idleGapOutMs : gap;\n segments.push({ kind: 'source', outStart: out, outEnd: out + outDur, srcStart: src, srcEnd: e.tStart });\n out += outDur;\n }\n const stepOutStart = out;\n\n // Action span at natural rate (typing capped and sped up uniformly).\n const srcEnd = Math.max(e.tSettled, e.tActionEnd, e.tStart + 1);\n const spanSrc = srcEnd - e.tStart;\n let spanOut = spanSrc;\n if (e.kind === 'type' && spanSrc > cfg.maxTypeOutMs) spanOut = cfg.maxTypeOutMs;\n segments.push({ kind: 'source', outStart: out, outEnd: out + spanOut, srcStart: e.tStart, srcEnd });\n const outBeat = out + (e.tAction - e.tStart) * (spanOut / spanSrc);\n out += spanOut;\n\n // Post-action freeze: fixed hold, extended to satisfy the minimum step duration.\n let hold = cfg.holds[e.kind];\n if (out + hold - stepOutStart < cfg.minStepMs) hold = cfg.minStepMs - (out - stepOutStart);\n // Narration-driven pacing: grow the hold so the step lasts long enough for its\n // spoken line (lead-in + speech + tail) to finish before the step ends.\n const aud = audioMs?.get(`${e.sceneId}/${e.stepIndex}`);\n if (aud && aud > 0) {\n const need = AUDIO_LEAD_MS + aud + AUDIO_TAIL_MS;\n const have = out - stepOutStart + hold;\n if (have < need) hold += need - have;\n }\n // Act→react pacing: a step whose focus hands the camera off to a payoff element needs\n // enough post-beat hold for the travel plus a settled look at the destination.\n if (e.focusTarget && e.focus && e.focus !== 'target' && e.focus !== 'wide') {\n const needAfterBeat = 2100;\n const haveAfterBeat = out + hold - outBeat;\n if (haveAfterBeat < needAfterBeat) hold += needAfterBeat - haveAfterBeat;\n }\n if (hold > 0.5) {\n segments.push({ kind: 'freeze', outStart: out, outEnd: out + hold, srcAt: srcEnd });\n out += hold;\n }\n\n steps.push({\n stepRef: `${e.sceneId}/${e.stepIndex}`,\n sceneId: e.sceneId,\n ordinal: e.ordinal,\n kind: e.kind,\n ...(e.locator ? { locator: e.locator } : {}),\n ...(e.masked ? { masked: true } : {}),\n ...(e.targetPre ? { targetRectVp: e.targetPre.bbox } : {}),\n ...(e.focus ? { focus: e.focus } : {}),\n ...(e.shot ? { shot: e.shot } : {}),\n ...(e.focusTarget ? { focusRectVp: e.focusTarget.bbox } : {}),\n outStart: stepOutStart,\n outBeat,\n outEnd: out,\n srcAction: e.tAction,\n srcSettled: srcEnd,\n });\n src = srcEnd;\n }\n\n // Outro: hold the final state.\n const lastSrc = Math.max(src, log.meta.durationMs - 1);\n segments.push({ kind: 'freeze', outStart: out, outEnd: out + cfg.outroMs, srcAt: lastSrc });\n out += cfg.outroMs;\n\n return { segments, steps, durationMs: out };\n}\n\n/** Map an output time to a source time (null on card segments). */\nexport function sampleSource(segments: TimeSegment[], tOut: number): { srcAt: number | null; segment: TimeSegment } {\n const seg = segmentAt(segments, tOut);\n switch (seg.kind) {\n case 'card':\n return { srcAt: null, segment: seg };\n case 'freeze':\n return { srcAt: seg.srcAt, segment: seg };\n case 'source': {\n const u = (tOut - seg.outStart) / Math.max(1e-6, seg.outEnd - seg.outStart);\n return { srcAt: seg.srcStart + u * (seg.srcEnd - seg.srcStart), segment: seg };\n }\n }\n}\n\nexport function segmentAt(segments: TimeSegment[], tOut: number): TimeSegment {\n let lo = 0;\n let hi = segments.length - 1;\n if (tOut <= segments[0]!.outStart) return segments[0]!;\n if (tOut >= segments[hi]!.outEnd) return segments[hi]!;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (segments[mid]!.outEnd <= tOut) lo = mid + 1;\n else hi = mid;\n }\n return segments[lo]!;\n}\n\n/** Events keyed by stepRef, for callers pairing steps back to their events. */\nexport function eventByStepRef(log: EventLog): Map<string, ActionEvent> {\n const map = new Map<string, ActionEvent>();\n for (const e of actionEvents(log)) map.set(`${e.sceneId}/${e.stepIndex}`, e);\n return map;\n}\n","import type { CameraKeyframe } from '../types.js';\nimport type { CameraState } from '../../shared/geometry.js';\nimport { cubicBezier } from '../../shared/easing.js';\n\n/**\n * Sample the camera path at an output time. Keyframes are (time, state, ease-from-previous);\n * holds are expressed as consecutive keyframes with identical states. Zoom interpolates in\n * log space (linear zoom feels like it accelerates).\n */\nexport function sampleCamera(keyframes: CameraKeyframe[], tOut: number): CameraState {\n if (keyframes.length === 0) return { cx: 0, cy: 0, zoom: 1 };\n if (tOut <= keyframes[0]!.tOut) return { ...keyframes[0]!.state };\n const last = keyframes[keyframes.length - 1]!;\n if (tOut >= last.tOut) return { ...last.state };\n\n let lo = 0;\n let hi = keyframes.length - 1;\n while (lo < hi - 1) {\n const mid = (lo + hi) >> 1;\n if (keyframes[mid]!.tOut <= tOut) lo = mid;\n else hi = mid;\n }\n const a = keyframes[lo]!;\n const b = keyframes[hi]!;\n const u = (tOut - a.tOut) / Math.max(1e-6, b.tOut - a.tOut);\n const e = cubicBezier(b.ease, u);\n return {\n cx: a.state.cx + (b.state.cx - a.state.cx) * e,\n cy: a.state.cy + (b.state.cy - a.state.cy) * e,\n zoom: Math.exp(Math.log(a.state.zoom) + (Math.log(b.state.zoom) - Math.log(a.state.zoom)) * e),\n };\n}\n","import type { CameraKeyframe, OutputProfile, StepMapEntry } from '../types.js';\nimport { stageContent, actReactWindows } from '../types.js';\nimport type { EventLog } from '../../capture/events.js';\nimport { navigationEvents } from '../../capture/events.js';\nimport {\n type CameraPlane,\n type CameraState,\n type Rect,\n clamp,\n clampCamera,\n minZoom,\n padRect,\n projectRect,\n rectCenter,\n rectContains,\n rectUnion,\n} from '../../shared/geometry.js';\nimport { EASE_PAN, EASE_ZOOM } from '../../shared/easing.js';\nimport { sampleCamera } from './interpolate.js';\n\nconst FOCUS_PAD_VP = 24;\nconst SHOT_MAX_GAP_MS = 4000;\nconst PAN_DEADBAND_VP = 48;\nconst TRAVEL_MIN_MS = 500;\nconst TRAVEL_MAX_MS = 900;\nconst ARRIVE_LEAD_MS = 80;\n/** Target rendered height (output px) the zoom aims to give the smallest target — comfortably\n * above the verifier's 28px legibility floor so quantization rounding stays safe. */\nconst LEGIBLE_TARGET_PX = 34;\n\ninterface Shot {\n stepRefs: string[];\n sceneId: string;\n focus: Rect;\n /** Smallest unpadded target dimension across the shot's members (viewport px) — this, not the\n * union size, is what the legibility zoom must satisfy so every member stays readable. */\n minTargetDim: number;\n wide: boolean;\n outStart: number;\n firstBeat: number;\n outEnd: number;\n zoomIndex: number;\n state?: CameraState;\n}\n\nexport interface CameraPlanResult {\n keyframes: CameraKeyframe[];\n fallbacks: string[];\n}\n\n/**\n * Plan the camera path from measured step geometry. Craft rules: quantized zoom levels,\n * legibility-driven zoom selection, caption-safe-area bias, pull-backs on navigation and\n * long pans, and an analytic constraint pass that guarantees each target stays framed.\n */\nexport function planCamera(\n steps: StepMapEntry[],\n log: EventLog,\n profile: OutputProfile,\n durationMs: number,\n opts?: { emphasis?: boolean },\n): CameraPlanResult {\n // The camera projects into the STAGE's content rect (or the full frame without a stage):\n // one shared space for planner, renderer, cursor, and verification.\n const content = stageContent(profile);\n const plane: CameraPlane = {\n vpW: log.meta.viewport.w,\n vpH: log.meta.viewport.h,\n outW: content.w,\n outH: content.h,\n };\n const emphasis = opts?.emphasis ?? true;\n const fallbacks: string[] = [];\n\n // Sharpness-bounded zoom quantums: the frame buffer only has frameW real pixels across.\n // Upscales beyond ~1.28x read as soft, so cap quantums there. (The stage helps here: content\n // renders smaller than the frame, so the same capture supports deeper sharp zooms.)\n const sharpZoom = log.meta.frameW > 0 ? log.meta.frameW / content.w : 1.3;\n const zMaxAllowed = Math.max(minZoom(plane), sharpZoom * 1.28);\n const quantums = profile.zoomQuantums.filter((q) => q <= zMaxAllowed + 1e-6);\n if (quantums.length === 0) quantums.push(1);\n\n const navTimes = navigationEvents(log).map((n) => n.t);\n const shots = groupShots(steps, navTimes, plane, durationMs);\n\n for (let attempt = 0; attempt < 4; attempt++) {\n for (const shot of shots) shot.state = shotState(shot, quantums, plane, profile, emphasis);\n const keyframes = emitKeyframes(shots, plane, durationMs);\n const violation = checkConstraints(keyframes, steps, plane, profile);\n if (!violation) return { keyframes, fallbacks };\n\n // An act→react step owns TWO shots with the same stepRef — pick the one whose time window\n // contains the violation, falling back to stepRef membership.\n const shot =\n shots.find(\n (s) => s.stepRefs.includes(violation.stepRef) && violation.tOut >= s.outStart && violation.tOut <= s.outEnd,\n ) ?? shots.find((s) => s.stepRefs.includes(violation.stepRef));\n if (!shot || shot.zoomIndex === 0 || shot.wide) {\n fallbacks.push(`${violation.stepRef}: unresolvable framing violation — falling back to wide`);\n if (shot) shot.wide = true;\n else break;\n } else {\n shot.zoomIndex -= 1;\n fallbacks.push(`${violation.stepRef}: reduced shot zoom to satisfy framing constraints`);\n }\n }\n for (const shot of shots) shot.state = shotState(shot, quantums, plane, profile, emphasis);\n return { keyframes: emitKeyframes(shots, plane, durationMs), fallbacks };\n}\n\nfunction groupShots(steps: StepMapEntry[], navTimes: number[], plane: CameraPlane, durationMs: number): Shot[] {\n const shots: Shot[] = [];\n let current: Shot | null = null;\n\n const navBetween = (a: number, b: number) => navTimes.some((t) => t > a && t <= b);\n\n for (const step of steps) {\n // Act→react: the step clicks one place and focuses another, with enough hold to travel.\n // Emit TWO shots — frame the action target through the beat, then hand the camera off to\n // the payoff for the settled hold (\"click here, look there\" inside one step).\n const handoff = actReactWindows(step);\n if (handoff) {\n const actFocus = padRect(handoff.act.rect, FOCUS_PAD_VP);\n const reactFocus = padRect(handoff.react.rect, FOCUS_PAD_VP);\n shots.push({\n stepRefs: [step.stepRef],\n sceneId: step.sceneId,\n focus: actFocus,\n minTargetDim: Math.min(handoff.act.rect.w, handoff.act.rect.h),\n wide: false,\n outStart: step.outStart,\n firstBeat: step.outBeat,\n outEnd: handoff.act.to,\n zoomIndex: Number.MAX_SAFE_INTEGER,\n });\n shots.push({\n stepRefs: [step.stepRef],\n sceneId: step.sceneId,\n focus: reactFocus,\n minTargetDim: Math.min(handoff.react.rect.w, handoff.react.rect.h),\n wide: false,\n outStart: handoff.act.to,\n firstBeat: handoff.react.from, // arrive by the react window's start\n outEnd: step.outEnd,\n zoomIndex: Number.MAX_SAFE_INTEGER,\n });\n current = null; // never merge across a handoff\n continue;\n }\n\n let rect = step.kind === 'goto' ? undefined : step.targetRectVp;\n // goto and scroll are wide by nature: goto changes everything; a scroll's meaning is the\n // motion, not a specific small element (so scroll targets are exempt from the legibility\n // floor elsewhere — they need only be in frame).\n let wide = !rect || step.kind === 'goto' || step.kind === 'scroll';\n // The spec's focus hint is AUTHORITY, not a suggestion: 'wide' forces a wide shot; 'target'\n // forces this step's own framed shot (never merged away); a locator-valued focus swaps the\n // framed rect for the measured payoff element — this is what lets a goto or a sidebar click\n // frame the thing that CHANGED rather than the thing that was clicked.\n if (step.focus === 'wide') {\n wide = true;\n } else if (step.focusRectVp) {\n rect = step.focusRectVp;\n wide = false;\n } else if (step.focus === 'target' && rect) {\n wide = false;\n }\n // Spec shot control: 'cut' forces this step into a fresh shot; 'continue' merges into the\n // previous shot even when the heuristic would split — the author's cut list wins.\n if (step.shot === 'cut') current = null;\n const forceContinue = step.shot === 'continue';\n if (forceContinue && current && rect && current.sceneId === step.sceneId) {\n current.stepRefs.push(step.stepRef);\n current.focus = rectUnion(current.focus, padRect(rect, FOCUS_PAD_VP));\n current.minTargetDim = Math.min(current.minTargetDim, Math.min(rect.w, rect.h));\n current.outEnd = step.outEnd;\n continue;\n }\n const noMerge = step.focus === 'target' || step.focusRectVp !== undefined;\n // A shot never spans scenes: hash-route changes don't fire a navigation event, so scene\n // identity — not navBetween alone — is what keeps a tour's views from merging into one\n // un-zoomable mega-shot.\n if (current && !noMerge && current.sceneId === step.sceneId && !current.wide && !wide && rect) {\n const prevSrc = current.stepRefs.length > 0 ? steps.find((s) => s.stepRef === current!.stepRefs[current!.stepRefs.length - 1])!.srcSettled : 0;\n const union = rectUnion(current.focus, padRect(rect, FOCUS_PAD_VP));\n // A merge must keep the SMALLEST member legible: if the union can only be shown at a zoom\n // below what the smallest target needs, merging would dilute it (a small pipeline card\n // pulled into a wide modal shot renders too small) — so keep them as separate shots.\n const baseScale = plane.outW / plane.vpW;\n const mergedMinDim = Math.min(current.minTargetDim, Math.min(rect.w, rect.h));\n const zNeeded = Math.min(LEGIBLE_TARGET_PX / (mergedMinDim * baseScale), 1.6);\n const zFitUnion = fitZoom(union, plane) * 0.92;\n const fitsTogether = fitZoom(union, plane) >= 1.2 && zFitUnion >= zNeeded - 0.02;\n const closeInTime = step.outStart - current.outEnd < SHOT_MAX_GAP_MS;\n if (fitsTogether && closeInTime && !navBetween(prevSrc, step.srcAction)) {\n current.stepRefs.push(step.stepRef);\n current.focus = union;\n current.minTargetDim = Math.min(current.minTargetDim, Math.min(rect.w, rect.h));\n current.outEnd = step.outEnd;\n continue;\n }\n }\n current = {\n stepRefs: [step.stepRef],\n sceneId: step.sceneId,\n focus: rect ? padRect(rect, FOCUS_PAD_VP) : { x: 0, y: 0, w: plane.vpW, h: plane.vpH },\n minTargetDim: rect ? Math.min(rect.w, rect.h) : Math.min(plane.vpW, plane.vpH),\n wide,\n outStart: step.outStart,\n firstBeat: step.outBeat,\n outEnd: step.outEnd,\n zoomIndex: Number.MAX_SAFE_INTEGER, // resolved in shotState\n };\n shots.push(current);\n }\n if (shots.length > 0) shots[shots.length - 1]!.outEnd = Math.min(shots[shots.length - 1]!.outEnd, durationMs);\n return shots;\n}\n\n/** Max zoom at which a viewport rect still fits in the visible window with margin. */\nfunction fitZoom(rect: Rect, plane: CameraPlane): number {\n const zw = plane.vpW / rect.w;\n const zh = (plane.vpW * plane.outH) / plane.outW / rect.h;\n return Math.min(zw, zh);\n}\n\n/** Fraction of the fit-zoom a focus rect should occupy when the camera emphasises it: at 0.5\n * the subject fills roughly half the frame's limiting dimension — close enough to direct the\n * eye, wide enough to keep context. This, not legibility, is what makes shots feel FRAMED. */\nconst OCCUPANCY = 0.5;\n\nfunction shotState(\n shot: Shot,\n quantums: number[],\n plane: CameraPlane,\n profile: OutputProfile,\n emphasis: boolean,\n): CameraState {\n const zMin = minZoom(plane);\n if (shot.wide) {\n return clampCamera({ cx: plane.vpW / 2, cy: rectCenter(shot.focus).y, zoom: zMin }, plane);\n }\n const baseScale = plane.outW / plane.vpW;\n // Legibility is driven by the SMALLEST member target (so a small element merged into a large\n // shot still gets enough zoom), while fit is driven by the whole union (so nothing is cropped).\n const minDim = Math.max(6, shot.minTargetDim);\n const zLegibility = LEGIBLE_TARGET_PX / (minDim * baseScale);\n const zFit = fitZoom(shot.focus, plane) * 0.92;\n\n // Composition: zoom is a DIRECTORIAL choice, not just a legibility floor. Without this, any\n // target above ~23 viewport px resolves to zoom 1.0 and the whole video plays wide and flat.\n const zComposition = emphasis ? OCCUPANCY * fitZoom(shot.focus, plane) : 0;\n const zWant = Math.max(zLegibility, zComposition);\n\n // Choose the smallest quantum ≥ the wanted zoom (round UP — an under-framed subject is the\n // defect we most want to avoid), but never past what fits without cropping.\n const maxFit = Math.min(zFit, quantums[quantums.length - 1]!);\n let zoomIndex = 0;\n let reachedWant = false;\n for (let i = 0; i < quantums.length; i++) {\n if (quantums[i]! > maxFit + 1e-6) break;\n zoomIndex = i; // largest quantum that still fits, as a fallback\n if (!reachedWant && quantums[i]! >= zWant - 1e-6) {\n zoomIndex = i;\n reachedWant = true;\n break;\n }\n }\n shot.zoomIndex = Math.min(shot.zoomIndex, zoomIndex);\n const zoom = Math.max(quantums[shot.zoomIndex]!, zMin);\n\n const center = rectCenter(shot.focus);\n let state = clampCamera({ cx: center.x, cy: center.y, zoom }, plane);\n\n // Bias the focus rect into the content safe area (out of the caption band).\n for (let i = 0; i < 3; i++) {\n const proj = projectRect(shot.focus, state, plane);\n const safe = contentArea(profile);\n let dyOut = 0;\n if (proj.y + proj.h > safe.y + safe.h) dyOut = proj.y + proj.h - (safe.y + safe.h);\n else if (proj.y < safe.y) dyOut = proj.y - safe.y;\n let dxOut = 0;\n if (proj.x + proj.w > safe.x + safe.w) dxOut = proj.x + proj.w - (safe.x + safe.w);\n else if (proj.x < safe.x) dxOut = proj.x - safe.x;\n if (Math.abs(dxOut) < 1 && Math.abs(dyOut) < 1) break;\n const visW = plane.vpW / state.zoom;\n const scale = visW / plane.outW;\n state = clampCamera({ cx: state.cx + dxOut * scale, cy: state.cy + dyOut * scale, zoom: state.zoom }, plane);\n }\n return state;\n}\n\n/** The safe area, expressed in PLANE space (stage content coords when a stage is set): frame\n * margins translated into the content rect, with a small floor so it never collapses. */\nexport function contentArea(profile: OutputProfile): Rect {\n const s = stageContent(profile);\n const left = Math.max(profile.safeArea.left - s.x, 8);\n const top = Math.max(profile.safeArea.top - s.y, 8);\n const right = Math.min(s.w - 8, profile.width - profile.safeArea.right - s.x);\n const bottom = Math.min(s.h - 8, profile.height - profile.safeArea.bottom - s.y);\n return { x: left, y: top, w: Math.max(16, right - left), h: Math.max(16, bottom - top) };\n}\n\nfunction emitKeyframes(shots: Shot[], plane: CameraPlane, durationMs: number): CameraKeyframe[] {\n const kfs: CameraKeyframe[] = [];\n const wideState = clampCamera({ cx: plane.vpW / 2, cy: plane.vpH / 2, zoom: minZoom(plane) }, plane);\n let prevState = wideState;\n let prevEnd = 0;\n kfs.push({ tOut: 0, state: wideState, ease: EASE_ZOOM });\n\n for (const shot of shots) {\n const target = shot.state!;\n const panDist = Math.hypot(target.cx - prevState.cx, target.cy - prevState.cy);\n const zoomChanged = Math.abs(Math.log(target.zoom / prevState.zoom)) > 0.01;\n if (panDist < PAN_DEADBAND_VP / 2 && !zoomChanged) {\n prevEnd = shot.outEnd;\n continue;\n }\n\n // Long pans while zoomed read badly: pull wide first, then dive in.\n const viaWide =\n panDist > plane.vpW * 0.6 && prevState.zoom > 1.15 && target.zoom > 1.15 ? wideState : null;\n\n const arriveBy = Math.max(shot.firstBeat - ARRIVE_LEAD_MS, shot.outStart + 100);\n const travel = clamp(300 + panDist * 0.8, TRAVEL_MIN_MS, TRAVEL_MAX_MS);\n let moveStart = Math.max(prevEnd, arriveBy - travel);\n if (viaWide) {\n const mid = Math.max(prevEnd, moveStart - 350);\n kfs.push({ tOut: mid, state: prevState, ease: EASE_PAN });\n kfs.push({ tOut: Math.min(mid + 400, arriveBy - 200), state: viaWide, ease: EASE_ZOOM });\n moveStart = Math.min(mid + 400, arriveBy - 200);\n } else {\n kfs.push({ tOut: moveStart, state: prevState, ease: EASE_PAN });\n }\n const moveEnd = Math.max(arriveBy, moveStart + 250);\n kfs.push({ tOut: moveEnd, state: target, ease: zoomChanged ? EASE_ZOOM : EASE_PAN });\n prevState = target;\n prevEnd = shot.outEnd;\n }\n\n // Final pull-back to wide during the outro.\n if (prevState.zoom > wideState.zoom + 0.01 || Math.hypot(prevState.cx - wideState.cx, prevState.cy - wideState.cy) > PAN_DEADBAND_VP) {\n const start = Math.min(prevEnd + 100, durationMs - 900);\n kfs.push({ tOut: start, state: prevState, ease: EASE_ZOOM });\n kfs.push({ tOut: Math.min(start + 800, durationMs - 50), state: wideState, ease: EASE_ZOOM });\n }\n return dedupeSorted(kfs);\n}\n\nfunction dedupeSorted(kfs: CameraKeyframe[]): CameraKeyframe[] {\n kfs.sort((a, b) => a.tOut - b.tOut);\n const out: CameraKeyframe[] = [];\n for (const kf of kfs) {\n const last = out[out.length - 1];\n if (last && kf.tOut - last.tOut < 1) {\n out[out.length - 1] = kf;\n } else {\n out.push(kf);\n }\n }\n return out;\n}\n\ninterface Violation {\n stepRef: string;\n tOut: number;\n}\n\n/**\n * The \"never crop mid-element\" guarantee: analytically sample the planned path and assert\n * every target is fully in frame (not cropped) during its hold. The comfortable safe-area\n * margin is a preference in shotState, not a hard constraint here.\n */\nfunction checkConstraints(\n keyframes: CameraKeyframe[],\n steps: StepMapEntry[],\n plane: CameraPlane,\n profile: OutputProfile,\n): Violation | null {\n // The camera projects into stage-content space, so the containment frame is the content rect.\n const content = stageContent(profile);\n const frame: Rect = { x: 0, y: 0, w: content.w, h: content.h };\n for (const step of steps) {\n // Windows to validate: an act→react step promises the ACTION target around the beat and the\n // FOCUSED payoff during the settled hold (the camera travels between — unchecked by design).\n // Otherwise: the focused rect (or the target) across the whole hold.\n const handoff = actReactWindows(step);\n const rect = step.focusRectVp ?? step.targetRectVp;\n const windows = handoff\n ? [handoff.act, handoff.react]\n : rect\n ? [{ rect, from: Math.max(step.outStart, step.outBeat - 60), to: step.outEnd }]\n : [];\n for (const w of windows) {\n for (let t = w.from; t <= w.to; t += 100) {\n const cam = sampleCamera(keyframes, t);\n const proj = projectRect(w.rect, cam, plane);\n if (!rectContains(frame, proj, 2)) {\n return { stepRef: step.stepRef, tOut: t };\n }\n }\n }\n }\n return null;\n}\n","import type { CursorSegment, ClickRipple, StepMapEntry } from '../types.js';\nimport type { EventLog } from '../../capture/events.js';\nimport { eventByStepRef } from '../timeline/pacing.js';\nimport { type Point, clamp, dist } from '../../shared/geometry.js';\nimport { minJerk } from '../../shared/easing.js';\n\nconst RESAMPLE_POINTS = 32;\nconst CLICK_KINDS = new Set(['click', 'dblclick', 'select']);\nconst POINTER_KINDS = new Set(['click', 'dblclick', 'hover', 'type', 'select']);\n\nexport interface CursorPlan {\n segments: CursorSegment[];\n ripples: ClickRipple[];\n restStart: Point;\n}\n\n/**\n * Re-synthesize cursor motion on the output clock: recorded waypoints give the path SHAPE,\n * arrival is re-timed so the cursor lands on the target exactly at the action beat with a\n * minimum-jerk profile.\n */\nexport function planCursor(steps: StepMapEntry[], log: EventLog): CursorPlan {\n const events = eventByStepRef(log);\n const segments: CursorSegment[] = [];\n const ripples: ClickRipple[] = [];\n let rest: Point = { x: log.meta.viewport.w / 2, y: log.meta.viewport.h * 0.6 };\n const restStart = { ...rest };\n\n for (const step of steps) {\n if (!POINTER_KINDS.has(step.kind)) continue;\n const event = events.get(step.stepRef);\n if (!event || event.cursorPath.length < 2) continue;\n\n const raw: Point[] = event.cursorPath.map((w) => ({ x: w.x, y: w.y }));\n // Continuity: motion starts wherever the cursor last rested on the output clock.\n raw[0] = { ...rest };\n const path = resampleByArcLength(raw, RESAMPLE_POINTS);\n const travelDist = dist(path[0]!, path[path.length - 1]!);\n const travel = clamp(300 + travelDist * 0.6, 300, 900);\n\n const prevEnd = segments.length > 0 ? segments[segments.length - 1]!.tEnd : 0;\n const tEnd = step.outBeat;\n const tStart = Math.max(Math.min(step.outStart, tEnd - 100), tEnd - travel, prevEnd + 40);\n\n if (tEnd - tStart > 30) {\n segments.push({ tStart, tEnd, path, clickAtEnd: CLICK_KINDS.has(step.kind) });\n }\n rest = path[path.length - 1]!;\n if (CLICK_KINDS.has(step.kind)) {\n ripples.push({ tOut: step.outBeat, x: rest.x, y: rest.y });\n }\n }\n return { segments, ripples, restStart };\n}\n\n/** Position of the cursor at an output time (viewport space). */\nexport function sampleCursor(plan: CursorPlan, tOut: number): Point {\n const segs = plan.segments;\n if (segs.length === 0) return plan.restStart;\n if (tOut <= segs[0]!.tStart) return segs[0]!.path[0]!;\n\n for (let i = 0; i < segs.length; i++) {\n const s = segs[i]!;\n if (tOut < s.tStart) return segs[i - 1]!.path[segs[i - 1]!.path.length - 1]!;\n if (tOut <= s.tEnd) {\n const u = minJerk((tOut - s.tStart) / Math.max(1e-6, s.tEnd - s.tStart));\n const fi = u * (s.path.length - 1);\n const i0 = Math.floor(fi);\n const i1 = Math.min(i0 + 1, s.path.length - 1);\n const f = fi - i0;\n return {\n x: s.path[i0]!.x + (s.path[i1]!.x - s.path[i0]!.x) * f,\n y: s.path[i0]!.y + (s.path[i1]!.y - s.path[i0]!.y) * f,\n };\n }\n }\n const last = segs[segs.length - 1]!;\n return last.path[last.path.length - 1]!;\n}\n\n/** Resample a polyline to n points equally spaced by arc length. */\nfunction resampleByArcLength(points: Point[], n: number): Point[] {\n const cum: number[] = [0];\n for (let i = 1; i < points.length; i++) {\n cum.push(cum[i - 1]! + dist(points[i - 1]!, points[i]!));\n }\n const total = cum[cum.length - 1]!;\n if (total < 1e-6) return Array.from({ length: n }, () => ({ ...points[0]! }));\n const out: Point[] = [];\n let j = 0;\n for (let i = 0; i < n; i++) {\n const target = (i / (n - 1)) * total;\n while (j < cum.length - 2 && cum[j + 1]! < target) j++;\n const span = Math.max(1e-6, cum[j + 1]! - cum[j]!);\n const f = (target - cum[j]!) / span;\n out.push({\n x: points[j]!.x + (points[j + 1]!.x - points[j]!.x) * f,\n y: points[j]!.y + (points[j + 1]!.y - points[j]!.y) * f,\n });\n }\n return out;\n}\n","import type { ActionEvent } from '../capture/events.js';\nimport { parseLocator, locatorDisplayName } from '../spec/locators.js';\n\n/** Per-step text overrides from a LIVE spec, keyed by stepRef — the compose-time source of\n * truth for caption/narration text. The copies baked into events.json are only the record of\n * what was captured; preferring the live spec makes text edits a sub-second re-compose, never\n * a re-capture (capture once, compose forever — including the words). */\nexport interface StepTexts {\n caption?: string;\n narration?: string;\n}\n\n/**\n * Deterministic caption writer: turns a step + its recorded accessible label into\n * instruction text. Text resolution: live-spec caption ?? captured caption ?? auto-written.\n * Returns null for steps that produce no caption (expect/wait without caption).\n */\nexport function writeCaption(event: ActionEvent, texts?: StepTexts): string | null {\n if (texts?.caption) return texts.caption;\n if (event.caption) return event.caption;\n\n const label = bestLabel(event);\n switch (event.kind) {\n case 'click':\n return label ? `Click “${label}”` : 'Click the highlighted element';\n case 'dblclick':\n return label ? `Double-click “${label}”` : 'Double-click the highlighted element';\n case 'hover':\n return label ? `Hover over “${label}”` : 'Hover over the highlighted element';\n case 'type':\n return label ? `Enter the ${lowerFirst(label)}` : 'Enter a value';\n case 'press':\n return `Press ${event.locator ?? 'the key'}`;\n case 'select':\n return label && event.typedText\n ? `Choose “${event.typedText}” under ${label}`\n : label\n ? `Choose an option under ${label}`\n : 'Choose an option';\n case 'goto':\n return `Open ${prettyUrl(event.locator ?? '')}`;\n case 'scroll':\n return label ? `Scroll to ${label}` : 'Scroll down';\n case 'expect':\n case 'wait':\n return null;\n }\n}\n\n/**\n * The SPOKEN line for a step: live-spec narration ?? live-spec caption ?? captured narration ??\n * the caption. Narration is unconstrained by the caption card, so a spec can show a terse\n * on-screen label while the voice says the full sentence.\n */\nexport function writeNarration(event: ActionEvent, texts?: StepTexts): string | null {\n return texts?.narration ?? event.narration ?? writeCaption(event, texts);\n}\n\nfunction bestLabel(event: ActionEvent): string | null {\n const name = event.targetPre?.accessibleName?.trim();\n if (name) return truncate(name, 60);\n if (event.locator) {\n try {\n return truncate(locatorDisplayName(parseLocator(event.locator)), 60);\n } catch {\n return null;\n }\n }\n return null;\n}\n\nfunction lowerFirst(s: string): string {\n // Keep acronyms/proper-looking tokens intact (\"API key\" stays, \"Email\" lowers).\n if (s.length > 1 && s[1] === s[1]!.toUpperCase() && /[A-Z]/.test(s[1]!)) return s;\n return s.charAt(0).toLowerCase() + s.slice(1);\n}\n\nfunction prettyUrl(url: string): string {\n try {\n const u = new URL(url);\n return u.host + (u.pathname !== '/' ? u.pathname : '');\n } catch {\n return url;\n }\n}\n\nfunction truncate(s: string, max: number): string {\n return s.length <= max ? s : s.slice(0, max - 1) + '…';\n}\n","import { createCanvas, type SKRSContext2D } from '@napi-rs/canvas';\n\nlet measureCtx: SKRSContext2D | null = null;\n\nfunction ctx(): SKRSContext2D {\n if (!measureCtx) measureCtx = createCanvas(8, 8).getContext('2d');\n return measureCtx;\n}\n\nexport function measureText(text: string, font: string): number {\n const c = ctx();\n c.font = font;\n return c.measureText(text).width;\n}\n\nexport interface WrapResult {\n lines: string[];\n fontPx: number;\n widest: number;\n shrunk: boolean;\n truncated: boolean;\n}\n\n/**\n * Greedy word-wrap with overflow as a first-class fact: try at fontPx; if the text needs\n * more than maxLines, shrink once to minFontPx; if it still overflows, truncate the last\n * line with an ellipsis AND report it — never silently clip.\n */\nexport function wrapText(\n text: string,\n fontFor: (px: number) => string,\n maxWidth: number,\n fontPx: number,\n minFontPx: number,\n maxLines: number,\n): WrapResult {\n let attempt = wrapAt(text, fontFor(fontPx), maxWidth);\n if (attempt.length <= maxLines) {\n return { lines: attempt, fontPx, widest: widestOf(attempt, fontFor(fontPx)), shrunk: false, truncated: false };\n }\n attempt = wrapAt(text, fontFor(minFontPx), maxWidth);\n if (attempt.length <= maxLines) {\n return { lines: attempt, fontPx: minFontPx, widest: widestOf(attempt, fontFor(minFontPx)), shrunk: true, truncated: false };\n }\n const kept = attempt.slice(0, maxLines);\n let last = kept[maxLines - 1]!;\n const font = fontFor(minFontPx);\n while (last.length > 1 && measureText(last + '…', font) > maxWidth) {\n last = last.slice(0, -1).trimEnd();\n }\n kept[maxLines - 1] = last + '…';\n return { lines: kept, fontPx: minFontPx, widest: widestOf(kept, font), shrunk: true, truncated: true };\n}\n\nfunction wrapAt(text: string, font: string, maxWidth: number): string[] {\n const words = text.split(/\\s+/).filter(Boolean);\n const lines: string[] = [];\n let line = '';\n for (const word of words) {\n const candidate = line ? line + ' ' + word : word;\n if (line && measureText(candidate, font) > maxWidth) {\n lines.push(line);\n line = word;\n } else {\n line = candidate;\n }\n }\n if (line) lines.push(line);\n return lines.length > 0 ? lines : [''];\n}\n\nfunction widestOf(lines: string[], font: string): number {\n return Math.max(...lines.map((l) => measureText(l, font)));\n}\n\n/** Rounded-rect path helper shared by overlay drawing. */\nexport function roundRect(c: SKRSContext2D, x: number, y: number, w: number, h: number, r: number): void {\n const rr = Math.min(r, w / 2, h / 2);\n c.beginPath();\n c.moveTo(x + rr, y);\n c.arcTo(x + w, y, x + w, y + h, rr);\n c.arcTo(x + w, y + h, x, y + h, rr);\n c.arcTo(x, y + h, x, y, rr);\n c.arcTo(x, y, x + w, y, rr);\n c.closePath();\n}\n","import type { CameraKeyframe, CaptionOverlay, ComposeDiagnostics, OutputProfile, OverlayEntry, StepMapEntry } from '../types.js';\nimport { stageContent } from '../types.js';\nimport type { EventLog } from '../../capture/events.js';\nimport type { ResolvedTheme } from '../../theme/index.js';\nimport type { KindProfile } from '../kinds.js';\nimport { writeCaption, type StepTexts } from '../captions.js';\nimport { eventByStepRef } from '../timeline/pacing.js';\nimport { wrapText, measureText } from './text.js';\nimport { sampleCamera } from '../camera/interpolate.js';\nimport { projectRect, type CameraPlane, type Rect } from '../../shared/geometry.js';\n\nconst CARD_PAD_X = 26;\nconst CARD_PAD_Y = 16;\nconst BADGE_GAP = 14;\nconst CARD_BOTTOM_MARGIN = 44;\nconst CHAPTER_LABEL_MS = 1800;\n/** Adjacent captions overlap by this much and cross-dissolve (fade handles the blend). */\nconst CAPTION_CROSSFADE_MS = 240;\n\nfunction overlaps(a: Rect, b: Rect): boolean {\n return a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y;\n}\n\nexport function buildOverlays(\n steps: StepMapEntry[],\n log: EventLog,\n theme: ResolvedTheme,\n profile: OutputProfile,\n title: string,\n subtitle: string,\n titleCardEndMs: number,\n diagnostics: ComposeDiagnostics,\n kind: KindProfile,\n sceneTitles?: Map<string, string>,\n camera?: CameraKeyframe[],\n specTexts?: Map<string, StepTexts>,\n): OverlayEntry[] {\n const overlays: OverlayEntry[] = [];\n overlays.push({ kind: 'titleCard', cardId: 'title', title, subtitle, tStart: 0, tEnd: titleCardEndMs });\n overlays.push({ kind: 'dip', tStart: titleCardEndMs, tEnd: titleCardEndMs + 400 });\n\n const events = eventByStepRef(log);\n const captioned = steps.filter((s) => {\n const e = events.get(s.stepRef);\n return e && writeCaption(e, specTexts?.get(s.stepRef)) !== null;\n });\n const total = captioned.length;\n let number = 0;\n\n // Chapter labels at each new scene, and an elapsed clock spanning the flow (bug-repro).\n if (kind.chapterCards) {\n const boundaries = sceneBoundaries(steps, sceneTitles);\n let chapter = 0;\n for (const b of boundaries) {\n chapter += 1;\n overlays.push({ kind: 'chapterLabel', title: b.title, ordinal: chapter, tStart: b.outStart, tEnd: b.outStart + CHAPTER_LABEL_MS });\n }\n }\n if (kind.elapsedClock) {\n const firstBeat = captioned[0]?.outBeat ?? titleCardEndMs;\n const last = steps[steps.length - 1];\n overlays.push({ kind: 'elapsedClock', tStart: titleCardEndMs, tEnd: last ? last.outEnd : titleCardEndMs, zeroAtMs: firstBeat });\n }\n\n // `captions: off` renders no caption cards (used for the voice-only cut); the\n // spoken narration still comes from the same text, derived separately in compose.\n for (let i = 0; theme.captionPosition !== 'off' && i < captioned.length; i++) {\n const step = captioned[i]!;\n const event = events.get(step.stepRef)!;\n const base = writeCaption(event, specTexts?.get(step.stepRef))!;\n number += 1;\n const text = kind.captionStyle === 'factual' ? `Step ${number} — ${lowerFirst(base)}` : base;\n\n const fontFor = (px: number) => `${px}px Inter Medium`;\n const showBadge = kind.numberedCaptions && kind.captionStyle !== 'factual';\n const badgeFontPx = 15;\n const badgeText = `${number}/${total}`;\n const badgeW = showBadge ? Math.ceil(measureText(badgeText, `600 ${badgeFontPx}px Inter SemiBold`)) + 20 : 0;\n const badgeGap = showBadge ? BADGE_GAP : 0;\n const maxTextWidth = Math.min(profile.captionMaxWidth, profile.width - 2 * profile.safeArea.left) - CARD_PAD_X * 2 - badgeW - badgeGap;\n\n const wrap = wrapText(text, fontFor, maxTextWidth, theme.captionFontPx, theme.captionMinFontPx, theme.captionMaxLines);\n if (wrap.truncated) diagnostics.overflows.push({ stepRef: step.stepRef, text, action: 'truncated' });\n else if (wrap.shrunk) diagnostics.overflows.push({ stepRef: step.stepRef, text, action: 'shrunk' });\n\n const lineH = Math.round(wrap.fontPx * 1.35);\n const cardW = CARD_PAD_X * 2 + badgeW + badgeGap + Math.ceil(wrap.widest);\n const cardH = CARD_PAD_Y * 2 + wrap.lines.length * lineH;\n const x = (profile.width - cardW) / 2;\n let y =\n theme.captionPosition === 'bottom'\n ? profile.height - CARD_BOTTOM_MARGIN - cardH\n : profile.safeArea.top;\n\n // Collision flip: if the framed subject sits under the caption during the hold, move the\n // caption to the top rather than covering the very thing the step is about.\n if (camera && theme.captionPosition === 'bottom') {\n const rect = step.focusRectVp ?? step.targetRectVp;\n if (rect) {\n const content = stageContent(profile);\n const capPlane: CameraPlane = { vpW: log.meta.viewport.w, vpH: log.meta.viewport.h, outW: content.w, outH: content.h };\n const cam = sampleCamera(camera, Math.min(step.outBeat + 250, step.outEnd));\n const proj = projectRect(rect, cam, capPlane);\n const projFrame: Rect = { x: proj.x + content.x, y: proj.y + content.y, w: proj.w, h: proj.h };\n const capBox: Rect = { x, y, w: cardW, h: cardH };\n if (overlaps(projFrame, capBox)) y = profile.safeArea.top;\n }\n }\n\n // Caption runs slightly INTO the next caption's window so adjacent captions cross-dissolve\n // instead of blinking out to an empty band at every step boundary.\n const next = captioned[i + 1];\n const tEnd = next ? Math.min(step.outEnd, next.outStart + CAPTION_CROSSFADE_MS) : step.outEnd;\n\n const overlay: CaptionOverlay = {\n kind: 'caption',\n stepRef: step.stepRef,\n ordinal: number,\n totalSteps: total,\n showBadge,\n text,\n lines: wrap.lines,\n fontPx: wrap.fontPx,\n box: { x, y, w: cardW, h: cardH },\n tStart: step.outStart,\n tEnd,\n shrunk: wrap.shrunk,\n truncated: wrap.truncated,\n };\n overlays.push(overlay);\n }\n return overlays;\n}\n\n/** First step of each scene, with a human title, for chapter labels. The spec's own\n * `scene.title` wins; deriving from the kebab-case id is only the fallback. */\nfunction sceneBoundaries(\n steps: StepMapEntry[],\n sceneTitles?: Map<string, string>,\n): { title: string; outStart: number }[] {\n const out: { title: string; outStart: number }[] = [];\n let lastScene = '';\n for (const s of steps) {\n if (s.sceneId !== lastScene) {\n lastScene = s.sceneId;\n out.push({ title: sceneTitles?.get(s.sceneId) ?? titleFromSceneId(s.sceneId), outStart: s.outStart });\n }\n }\n return out;\n}\n\nfunction titleFromSceneId(id: string): string {\n const t = id.replace(/-/g, ' ');\n return t.charAt(0).toUpperCase() + t.slice(1);\n}\n\nfunction lowerFirst(s: string): string {\n if (s.length > 1 && s[1] === s[1]!.toUpperCase() && /[A-Z]/.test(s[1]!)) return s;\n return s.charAt(0).toLowerCase() + s.slice(1);\n}\n","import type { SKRSContext2D } from '@napi-rs/canvas';\nimport type { Point } from '../../shared/geometry.js';\nimport type { ClickRipple } from '../types.js';\nimport type { ResolvedTheme } from '../../theme/index.js';\n\nconst RIPPLE_MS = 350;\nconst PRESS_DOWN_MS = 90;\nconst PRESS_UP_MS = 120;\n\nexport type CursorGlyph = 'arrow' | 'ibeam';\n\n/** Draw the vector cursor at an output-space point.\n * `baseScale` (output px per viewport px) keeps the cursor proportioned to the UI it points\n * at — without it the cursor renders 1.5× too small against upscaled content. */\nexport function drawCursor(\n ctx: SKRSContext2D,\n p: Point,\n zoom: number,\n tOut: number,\n ripples: ClickRipple[],\n rippleCenters: Point[],\n theme: ResolvedTheme,\n baseScale = 1,\n glyph: CursorGlyph = 'arrow',\n): void {\n // Press animation: scale dips to 0.85 around each click beat.\n let scale = 1;\n for (const r of ripples) {\n const dt = tOut - r.tOut;\n if (dt >= -PRESS_DOWN_MS && dt < 0) scale = 1 - 0.15 * (1 + dt / PRESS_DOWN_MS);\n else if (dt >= 0 && dt <= PRESS_UP_MS) scale = 0.85 + 0.15 * (dt / PRESS_UP_MS);\n }\n\n // Expanding ring at click points (drawn under the cursor).\n for (let i = 0; i < ripples.length; i++) {\n const r = ripples[i]!;\n const dt = tOut - r.tOut;\n if (dt < 0 || dt > RIPPLE_MS) continue;\n const u = dt / RIPPLE_MS;\n const c = rippleCenters[i]!;\n ctx.save();\n ctx.beginPath();\n ctx.arc(c.x, c.y, (6 + 42 * easeOut(u)) * baseScale, 0, Math.PI * 2);\n ctx.strokeStyle = theme.accent;\n ctx.globalAlpha = 0.6 * (1 - u);\n ctx.lineWidth = 3.5 * baseScale * (1 - u * 0.5);\n ctx.stroke();\n ctx.restore();\n }\n\n const size = 24 * baseScale * (1 + 0.15 * (zoom - 1)) * scale;\n ctx.save();\n ctx.translate(p.x, p.y);\n ctx.scale(size / 24, size / 24);\n ctx.shadowColor = 'rgba(0,0,0,0.35)';\n ctx.shadowBlur = 5;\n ctx.shadowOffsetY = 1.5;\n if (glyph === 'ibeam') {\n // I-beam (text) cursor, hotspot at the beam center.\n ctx.beginPath();\n ctx.moveTo(-4, -9);\n ctx.lineTo(4, -9);\n ctx.moveTo(0, -9);\n ctx.lineTo(0, 9);\n ctx.moveTo(-4, 9);\n ctx.lineTo(4, 9);\n ctx.lineWidth = 2.4;\n ctx.strokeStyle = '#ffffff';\n ctx.stroke();\n ctx.shadowColor = 'transparent';\n ctx.lineWidth = 1;\n ctx.strokeStyle = 'rgba(20,24,34,0.9)';\n ctx.stroke();\n } else {\n // Arrow pointer path (24px design grid, hotspot at 0,0)\n ctx.beginPath();\n ctx.moveTo(0, 0);\n ctx.lineTo(0, 17.5);\n ctx.lineTo(4.2, 13.6);\n ctx.lineTo(7.4, 20.6);\n ctx.lineTo(10.3, 19.2);\n ctx.lineTo(7.2, 12.4);\n ctx.lineTo(12.8, 12.2);\n ctx.closePath();\n ctx.fillStyle = '#ffffff';\n ctx.fill();\n ctx.shadowColor = 'transparent';\n ctx.lineWidth = 1.4;\n ctx.strokeStyle = 'rgba(20,24,34,0.9)';\n ctx.stroke();\n }\n ctx.restore();\n}\n\nfunction easeOut(u: number): number {\n return 1 - (1 - u) * (1 - u);\n}\n","import type { SKRSContext2D } from '@napi-rs/canvas';\nimport type { CaptionOverlay, OutputProfile, OverlayEntry, TitleCardOverlay } from '../types.js';\nimport type { ResolvedTheme } from '../../theme/index.js';\nimport { roundRect, measureText } from './text.js';\nimport { clamp } from '../../shared/geometry.js';\n\nconst FADE_MS = 200;\nconst SCRIM_H = 210;\n\nexport function drawOverlays(\n ctx: SKRSContext2D,\n overlays: OverlayEntry[],\n tOut: number,\n theme: ResolvedTheme,\n profile: OutputProfile,\n): void {\n // Bottom gradient scrim behind the caption band, drawn ONCE at the strongest active caption's\n // alpha (overlapping cross-fading captions must not double-darken it). Keeps caption text off\n // raw UI pixels regardless of what the app renders down there.\n const bottomCaptions = overlays.filter(\n (o): o is CaptionOverlay =>\n o.kind === 'caption' && tOut >= o.tStart && tOut <= o.tEnd && o.box.y > profile.height / 2,\n );\n if (bottomCaptions.length > 0) {\n const a = Math.max(...bottomCaptions.map((o) => captionAlpha(o, tOut)));\n if (a > 0) {\n const g = ctx.createLinearGradient(0, profile.height - SCRIM_H, 0, profile.height);\n g.addColorStop(0, 'rgba(8,10,16,0)');\n g.addColorStop(1, `rgba(8,10,16,${(0.55 * a).toFixed(3)})`);\n ctx.fillStyle = g;\n ctx.fillRect(0, profile.height - SCRIM_H, profile.width, SCRIM_H);\n }\n }\n\n for (const o of overlays) {\n if (tOut < o.tStart || tOut > o.tEnd) continue;\n switch (o.kind) {\n case 'caption':\n drawCaption(ctx, o, tOut, theme);\n break;\n case 'dip': {\n // 'in': fade from theme bg into footage (post-title). 'out': fade footage into the bg\n // (pre-end-card), so the closing card doesn't hard-cut in.\n const u = (tOut - o.tStart) / Math.max(1, o.tEnd - o.tStart);\n ctx.save();\n ctx.globalAlpha = o.direction === 'out' ? u : 1 - u;\n ctx.fillStyle = theme.bg;\n ctx.fillRect(0, 0, profile.width, profile.height);\n ctx.restore();\n break;\n }\n case 'elapsedClock':\n drawElapsedClock(ctx, o.zeroAtMs, tOut, theme, profile);\n break;\n case 'chapterLabel':\n drawChapterLabel(ctx, o, tOut, theme, profile);\n break;\n case 'titleCard':\n case 'failureCard':\n // Painted by the renderer as a full-frame card (not an overlay on footage).\n break;\n }\n }\n}\n\nfunction drawElapsedClock(\n ctx: SKRSContext2D,\n zeroAtMs: number,\n tOut: number,\n theme: ResolvedTheme,\n profile: OutputProfile,\n): void {\n const ms = Math.max(0, tOut - zeroAtMs);\n const s = Math.floor(ms / 1000);\n const label = `${String(Math.floor(s / 60)).padStart(2, '0')}:${String(s % 60).padStart(2, '0')}.${String(Math.floor((ms % 1000) / 100))}`;\n const font = '600 26px Inter SemiBold';\n ctx.save();\n ctx.font = font;\n const textW = ctx.measureText(label).width;\n const padX = 16;\n const w = textW + padX * 2 + 30;\n const h = 44;\n const x = profile.width - profile.safeArea.right - w;\n const y = profile.safeArea.top;\n ctx.fillStyle = 'rgba(18,22,31,0.82)';\n roundRect(ctx, x, y, w, h, 10);\n ctx.fill();\n // A small \"recording\" dot.\n ctx.fillStyle = '#ef4444';\n ctx.beginPath();\n ctx.arc(x + padX + 6, y + h / 2, 6, 0, Math.PI * 2);\n ctx.fill();\n ctx.fillStyle = '#ffffff';\n ctx.textAlign = 'left';\n ctx.textBaseline = 'middle';\n ctx.font = font;\n ctx.fillText(label, x + padX + 24, y + h / 2 + 1);\n ctx.restore();\n}\n\nfunction drawChapterLabel(\n ctx: SKRSContext2D,\n o: { title: string; ordinal: number; tStart: number; tEnd: number },\n tOut: number,\n theme: ResolvedTheme,\n profile: OutputProfile,\n): void {\n const alpha = clamp(Math.min((tOut - o.tStart) / 260, (o.tEnd - tOut) / 320), 0, 1);\n if (alpha <= 0) return;\n ctx.save();\n ctx.globalAlpha = alpha;\n const font = '700 30px Inter Bold';\n ctx.font = font;\n const textW = ctx.measureText(o.title).width;\n const barW = textW + 96;\n const barH = 56;\n const x = (profile.width - barW) / 2;\n // Below the stage's chrome bar (never over the URL pill); safe-area top otherwise.\n const y = profile.stage ? profile.stage.content.y + 14 : profile.safeArea.top + 8;\n ctx.fillStyle = theme.accent;\n roundRect(ctx, x, y, barW, barH, 12);\n ctx.fill();\n ctx.fillStyle = '#ffffff';\n ctx.font = '600 16px Inter SemiBold';\n ctx.textAlign = 'left';\n ctx.textBaseline = 'middle';\n ctx.fillText(String(o.ordinal), x + 22, y + barH / 2 + 1);\n ctx.font = font;\n ctx.fillText(o.title, x + 48, y + barH / 2 + 1);\n ctx.restore();\n}\n\nfunction captionAlpha(o: CaptionOverlay, tOut: number): number {\n return clamp(Math.min((tOut - o.tStart) / FADE_MS, (o.tEnd - tOut) / FADE_MS), 0, 1);\n}\n\nfunction drawCaption(ctx: SKRSContext2D, o: CaptionOverlay, tOut: number, theme: ResolvedTheme): void {\n const alpha = captionAlpha(o, tOut);\n if (alpha <= 0) return;\n ctx.save();\n ctx.globalAlpha = alpha;\n\n // Card\n ctx.shadowColor = 'rgba(0,0,0,0.30)';\n ctx.shadowBlur = 18;\n ctx.shadowOffsetY = 4;\n ctx.fillStyle = theme.surface;\n roundRect(ctx, o.box.x, o.box.y, o.box.w, o.box.h, theme.radius);\n ctx.fill();\n ctx.shadowColor = 'transparent';\n\n // Step badge chip (omitted for styles that don't number captions)\n let badgeW = 0;\n const bx = o.box.x + 26;\n if (o.showBadge) {\n const badgeText = `${o.ordinal}/${o.totalSteps}`;\n const badgeFont = `600 15px Inter SemiBold`;\n badgeW = Math.ceil(measureText(badgeText, badgeFont)) + 20;\n const badgeH = 26;\n const by = o.box.y + o.box.h / 2 - badgeH / 2;\n ctx.fillStyle = theme.accent;\n roundRect(ctx, bx, by, badgeW, badgeH, 13);\n ctx.fill();\n ctx.fillStyle = '#ffffff';\n ctx.font = badgeFont;\n ctx.textBaseline = 'middle';\n ctx.textAlign = 'center';\n ctx.fillText(badgeText, bx + badgeW / 2, by + badgeH / 2 + 1);\n }\n\n // Caption text\n const lineH = Math.round(o.fontPx * 1.35);\n const textX = o.showBadge ? bx + badgeW + 14 : bx;\n const textTop = o.box.y + (o.box.h - o.lines.length * lineH) / 2;\n ctx.fillStyle = theme.onSurface;\n ctx.font = `${o.fontPx}px Inter Medium`;\n ctx.textAlign = 'left';\n ctx.textBaseline = 'middle';\n o.lines.forEach((line, i) => {\n ctx.fillText(line, textX, textTop + i * lineH + lineH / 2 + 1);\n });\n ctx.restore();\n}\n\n/** The failure clip's closing card: what step broke and why, in evidence red. */\nexport function drawFailureCard(\n ctx: SKRSContext2D,\n card: { stepRef: string; message: string; tStart: number },\n tOut: number,\n theme: ResolvedTheme,\n profile: OutputProfile,\n): void {\n const { width, height } = profile;\n const g = ctx.createLinearGradient(0, 0, 0, height);\n g.addColorStop(0, '#1c1114');\n g.addColorStop(1, '#12090b');\n ctx.fillStyle = g;\n ctx.fillRect(0, 0, width, height);\n\n const t = tOut - card.tStart;\n const a = clamp(t / 300, 0, 1);\n ctx.save();\n ctx.globalAlpha = a;\n\n ctx.fillStyle = '#ef4444';\n roundRect(ctx, width / 2 - 32, height / 2 - 150, 64, 8, 4);\n ctx.fill();\n\n ctx.fillStyle = '#ffffff';\n ctx.font = `52px Inter Bold`;\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n ctx.fillText('Flow failed', width / 2, height / 2 - 70);\n\n ctx.fillStyle = '#fca5a5';\n ctx.font = `600 30px Inter SemiBold`;\n ctx.fillText(`at step ${card.stepRef}`, width / 2, height / 2 - 12);\n\n // Error message, wrapped to a readable measure.\n ctx.fillStyle = 'rgba(255,255,255,0.75)';\n ctx.font = `24px Inter`;\n const maxW = Math.min(1200, width - 200);\n const words = card.message.replace(/\\s+/g, ' ').split(' ');\n const lines: string[] = [];\n let line = '';\n for (const w of words) {\n const probe = line ? `${line} ${w}` : w;\n if (ctx.measureText(probe).width > maxW && line) {\n lines.push(line);\n line = w;\n if (lines.length >= 3) break;\n } else line = probe;\n }\n if (lines.length < 3 && line) lines.push(line);\n else if (line && lines.length >= 3) lines[2] = `${lines[2]!.slice(0, -1)}…`;\n lines.forEach((l, i) => ctx.fillText(l, width / 2, height / 2 + 48 + i * 36));\n ctx.restore();\n}\n\nexport function drawTitleCard(\n ctx: SKRSContext2D,\n card: TitleCardOverlay,\n tOut: number,\n theme: ResolvedTheme,\n profile: OutputProfile,\n): void {\n const { width, height } = profile;\n // Ground with the same gradient the stage uses, so the dip into footage feels continuous.\n const g = ctx.createLinearGradient(0, 0, 0, height);\n g.addColorStop(0, theme.bgSubtle);\n g.addColorStop(1, theme.bg);\n ctx.fillStyle = g;\n ctx.fillRect(0, 0, width, height);\n\n // Staggered entrance: bar → title → subtitle, each rising 16px as it fades in. A group fade\n // with zero motion reads as a slide; a 200ms stagger reads as designed.\n const t = tOut - card.tStart;\n const enter = (delay: number) => {\n const u = clamp((t - delay) / 380, 0, 1);\n const e = 1 - (1 - u) * (1 - u) * (1 - u); // easeOutCubic\n return { alpha: u, rise: 16 * (1 - e) };\n };\n const bar = enter(0);\n const title = enter(130);\n const sub = enter(240);\n\n ctx.save();\n ctx.globalAlpha = bar.alpha;\n ctx.fillStyle = theme.accent;\n roundRect(ctx, width / 2 - 32, height / 2 - 110 + bar.rise, 64, 8, 4);\n ctx.fill();\n\n ctx.globalAlpha = title.alpha;\n ctx.fillStyle = '#ffffff';\n ctx.font = `56px Inter Bold`;\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n ctx.fillText(card.title, width / 2, height / 2 - 20 + title.rise);\n\n if (card.subtitle) {\n ctx.globalAlpha = sub.alpha;\n ctx.fillStyle = theme.onSurfaceDim;\n ctx.font = `26px Inter`;\n ctx.fillText(card.subtitle, width / 2, height / 2 + 44 + sub.rise);\n }\n ctx.restore();\n}\n","import sharp from 'sharp';\nimport { createCanvas, ImageData, type Canvas } from '@napi-rs/canvas';\nimport type { BundleData } from '../../bundle/types.js';\nimport { frameIndexForTime, framePath } from '../../bundle/reader.js';\n\nconst LRU_SIZE = 6;\n\n/**\n * Timestamp-indexed source-frame store with an LRU of decoded frames and one-ahead\n * prefetch. Access during a render is monotonic in time, so a small cache wins.\n */\nexport class FrameStore {\n private cache = new Map<number, Promise<Canvas>>();\n\n constructor(private readonly bundle: BundleData) {}\n\n /** Decoded canvas for the frame that should be on screen at capture-relative tMs. */\n async frameForTime(tMs: number): Promise<Canvas> {\n const idx = frameIndexForTime(this.bundle.frames, tMs);\n const canvas = await this.get(idx);\n // Prefetch the next distinct frame while this one is being drawn.\n if (idx + 1 < this.bundle.frames.length) void this.get(idx + 1);\n return canvas;\n }\n\n /**\n * The frame at tMs plus its successor with a blend factor: the capture is ~20fps but output\n * is 30fps, so nearest-frame playback holds each source frame in a 2-1-2-1 judder pattern.\n * Blending adjacent frames during real motion smooths it without optical flow.\n */\n async framePairForTime(tMs: number): Promise<{ a: Canvas; b: Canvas | null; mix: number; gapMs: number }> {\n const idx = frameIndexForTime(this.bundle.frames, tMs);\n const a = await this.get(idx);\n if (idx + 1 >= this.bundle.frames.length) return { a, b: null, mix: 0, gapMs: Infinity };\n const t0 = this.bundle.frames[idx]!.t;\n const t1 = this.bundle.frames[idx + 1]!.t;\n const gapMs = t1 - t0;\n const mix = gapMs > 0 ? Math.min(1, Math.max(0, (tMs - t0) / gapMs)) : 0;\n const b = await this.get(idx + 1);\n return { a, b, mix, gapMs };\n }\n\n private get(idx: number): Promise<Canvas> {\n const hit = this.cache.get(idx);\n if (hit) {\n // refresh recency\n this.cache.delete(idx);\n this.cache.set(idx, hit);\n return hit;\n }\n const promise = this.decode(idx);\n this.cache.set(idx, promise);\n while (this.cache.size > LRU_SIZE) {\n const oldest = this.cache.keys().next().value as number;\n this.cache.delete(oldest);\n }\n return promise;\n }\n\n private async decode(idx: number): Promise<Canvas> {\n const { data, info } = await sharp(framePath(this.bundle, idx))\n .ensureAlpha()\n .raw()\n .toBuffer({ resolveWithObject: true });\n const canvas = createCanvas(info.width, info.height);\n const ctx = canvas.getContext('2d');\n ctx.putImageData(new ImageData(new Uint8ClampedArray(data.buffer, data.byteOffset, data.byteLength), info.width, info.height), 0, 0);\n return canvas;\n }\n}\n","import { spawn } from 'node:child_process';\nimport { createRequire } from 'node:module';\n\nconst require = createRequire(import.meta.url);\n\n/** Resolve the ffmpeg binary: $PLAYHEAD_FFMPEG override, else the bundled ffmpeg-static build. */\nexport function ffmpegPath(): string {\n if (process.env.PLAYHEAD_FFMPEG) return process.env.PLAYHEAD_FFMPEG;\n const p = require('ffmpeg-static') as string | null;\n if (!p) throw new Error('ffmpeg-static did not provide a binary; set PLAYHEAD_FFMPEG');\n return p;\n}\n\nexport function ffprobePath(): string {\n if (process.env.PLAYHEAD_FFPROBE) return process.env.PLAYHEAD_FFPROBE;\n const mod = require('ffprobe-static') as { path: string };\n return mod.path;\n}\n\nexport interface RunResult {\n code: number;\n stdout: string;\n stderr: string;\n}\n\n/** Run ffmpeg/ffprobe to completion, capturing output. For the streaming encoder see compose/render/encoder.ts. */\nexport function runBinary(bin: string, args: string[], stdin?: Buffer): Promise<RunResult> {\n return new Promise((resolve, reject) => {\n const child = spawn(bin, args, { stdio: ['pipe', 'pipe', 'pipe'] });\n const out: Buffer[] = [];\n const err: Buffer[] = [];\n child.stdout.on('data', (d) => out.push(d));\n child.stderr.on('data', (d) => err.push(d));\n child.on('error', reject);\n child.on('close', (code) => {\n resolve({\n code: code ?? -1,\n stdout: Buffer.concat(out).toString('utf8'),\n stderr: Buffer.concat(err).toString('utf8'),\n });\n });\n if (stdin) child.stdin.end(stdin);\n else child.stdin.end();\n });\n}\n\n/** Losslessly concatenate H.264 MP4s (same codec/params) into one file via the concat demuxer. */\nexport async function concatVideos(inputs: string[], outPath: string): Promise<void> {\n const { writeFile, mkdtemp, rm } = await import('node:fs/promises');\n const { join } = await import('node:path');\n const { tmpdir } = await import('node:os');\n const dir = await mkdtemp(join(tmpdir(), 'playhead-concat-'));\n const listPath = join(dir, 'list.txt');\n await writeFile(listPath, inputs.map((p) => `file '${p.replace(/'/g, \"'\\\\''\")}'`).join('\\n'));\n try {\n const res = await runBinary(ffmpegPath(), [\n '-hide_banner', '-loglevel', 'error',\n '-f', 'concat', '-safe', '0',\n '-i', listPath,\n '-c', 'copy',\n '-movflags', '+faststart',\n '-y', outPath,\n ]);\n if (res.code !== 0) throw new Error(`concat failed: ${res.stderr}`);\n } finally {\n await rm(dir, { recursive: true, force: true }).catch(() => {});\n }\n}\n\n/** Run ffmpeg, returning raw stdout bytes (for image2pipe extraction). */\nexport function runBinaryRaw(bin: string, args: string[]): Promise<{ code: number; stdout: Buffer; stderr: string }> {\n return new Promise((resolve, reject) => {\n const child = spawn(bin, args, { stdio: ['ignore', 'pipe', 'pipe'] });\n const out: Buffer[] = [];\n const err: Buffer[] = [];\n child.stdout.on('data', (d) => out.push(d));\n child.stderr.on('data', (d) => err.push(d));\n child.on('error', reject);\n child.on('close', (code) => {\n resolve({ code: code ?? -1, stdout: Buffer.concat(out), stderr: Buffer.concat(err).toString('utf8') });\n });\n });\n}\n","import { spawn, type ChildProcess } from 'node:child_process';\nimport { once } from 'node:events';\nimport { ffmpegPath } from '../../shared/ffmpeg.js';\n\n/**\n * Streaming H.264 encoder: raw RGBA frames in on stdin, MP4 out. Backpressure is\n * respected — write() resolves only when the pipe can take more.\n */\nexport class Encoder {\n private child: ChildProcess;\n private stderrTail: string[] = [];\n private exit: Promise<number>;\n\n constructor(outPath: string, width: number, height: number, fps: number) {\n this.child = spawn(\n ffmpegPath(),\n [\n '-hide_banner',\n '-loglevel', 'error',\n '-f', 'rawvideo',\n '-pix_fmt', 'rgba',\n '-s', `${width}x${height}`,\n '-r', String(fps),\n '-i', 'pipe:0',\n // A silent AAC track: some players/galleries refuse an audio-less MP4.\n '-f', 'lavfi',\n '-i', 'anullsrc=channel_layout=stereo:sample_rate=44100',\n '-c:v', 'libx264',\n '-preset', 'medium',\n '-crf', '18',\n '-pix_fmt', 'yuv420p',\n '-profile:v', 'high',\n '-c:a', 'aac',\n '-b:a', '96k',\n '-shortest',\n '-movflags', '+faststart',\n '-y',\n outPath,\n ],\n { stdio: ['pipe', 'ignore', 'pipe'] },\n );\n this.child.stderr!.on('data', (d: Buffer) => {\n this.stderrTail.push(d.toString('utf8'));\n if (this.stderrTail.length > 40) this.stderrTail.shift();\n });\n this.exit = new Promise((resolve, reject) => {\n this.child.on('error', reject);\n this.child.on('close', (code) => resolve(code ?? -1));\n });\n }\n\n async write(rgba: Buffer): Promise<void> {\n const stdin = this.child.stdin!;\n if (!stdin.writable) throw new Error(`ffmpeg closed early: ${this.stderrTail.join('')}`);\n if (!stdin.write(rgba)) {\n await once(stdin, 'drain');\n }\n }\n\n async finish(): Promise<void> {\n this.child.stdin!.end();\n const code = await this.exit;\n if (code !== 0) {\n throw new Error(`ffmpeg exited with code ${code}: ${this.stderrTail.join('')}`);\n }\n }\n}\n","import { createCanvas, type Canvas, type SKRSContext2D } from '@napi-rs/canvas';\nimport type { BundleData } from '../../bundle/types.js';\nimport type { ComposeManifest, TitleCardOverlay, StepMapEntry } from '../types.js';\nimport { stageContent } from '../types.js';\nimport { sampleSource } from '../timeline/pacing.js';\nimport { sampleCamera } from '../camera/interpolate.js';\nimport { sampleCursor, type CursorPlan } from '../cursor/path.js';\nimport { drawCursor, type CursorGlyph } from '../cursor/render.js';\nimport { drawOverlays, drawTitleCard, drawFailureCard } from '../overlays/draw.js';\nimport { roundRect } from '../overlays/text.js';\nimport { visibleRect, projectPoint, projectRect, clamp, type CameraPlane, type Rect } from '../../shared/geometry.js';\nimport { FrameStore } from './frameStore.js';\nimport { Encoder } from './encoder.js';\nimport { registerFonts } from '../../theme/index.js';\nimport { log } from '../../shared/log.js';\n\nconst SPOTLIGHT_KINDS = new Set(['click', 'dblclick', 'select']);\nconst SPOTLIGHT_LEAD_MS = 200;\nconst SPOTLIGHT_TAIL_MS = 650;\nconst SPOTLIGHT_MAX_DIM = 0.34;\n\n/** Render the full output from a bundle + compose manifest. Pure playback of the plan. */\nexport async function renderVideo(\n bundle: BundleData,\n manifest: ComposeManifest,\n outPath: string,\n): Promise<void> {\n registerFonts();\n const { profile, theme } = manifest;\n const { width, height, fps } = profile;\n // All camera math runs in stage-content space (the same space the planner and verifier use);\n // the renderer's only extra job is translating that space onto the frame at `content.x/y`.\n const content = stageContent(profile);\n const plane: CameraPlane = {\n vpW: manifest.viewport.w,\n vpH: manifest.viewport.h,\n outW: content.w,\n outH: content.h,\n };\n const frameScale = bundle.manifest.frameW / manifest.viewport.w;\n\n const store = new FrameStore(bundle);\n const encoder = new Encoder(outPath, width, height, fps);\n const canvas = createCanvas(width, height);\n const ctx = canvas.getContext('2d');\n ctx.imageSmoothingEnabled = true;\n ctx.imageSmoothingQuality = 'high';\n // Offscreen scratch for the spotlight (dim layer with a feathered punch-out).\n const spotCanvas = createCanvas(content.w, content.h);\n const spotCtx = spotCanvas.getContext('2d');\n\n const cursorPlan: CursorPlan = {\n segments: manifest.cursor,\n ripples: manifest.ripples,\n restStart:\n manifest.cursor.length > 0\n ? manifest.cursor[0]!.path[0]!\n : { x: manifest.viewport.w / 2, y: manifest.viewport.h * 0.6 },\n };\n const cards = new Map(\n manifest.overlays\n .filter((o): o is TitleCardOverlay => o.kind === 'titleCard')\n .map((c) => [c.cardId, c]),\n );\n const transitions = manifest.transitions ?? [];\n const spotlightSteps = manifest.steps.filter(\n (s) => SPOTLIGHT_KINDS.has(s.kind) && (s.focusRectVp ?? s.targetRectVp),\n );\n\n const start = Date.now();\n for (let i = 0; i < manifest.totalFrames; i++) {\n const tOut = (i * 1000) / fps;\n const { srcAt, segment } = sampleSource(manifest.segments, tOut);\n\n if (srcAt === null) {\n const failCard =\n segment.kind === 'card' && segment.cardId === 'failure'\n ? manifest.overlays.find((o) => o.kind === 'failureCard')\n : undefined;\n const card = segment.kind === 'card' ? cards.get(segment.cardId) : undefined;\n if (failCard && failCard.kind === 'failureCard') drawFailureCard(ctx, failCard, tOut, theme, profile);\n else if (card) drawTitleCard(ctx, card, tOut, theme, profile);\n else {\n ctx.fillStyle = theme.bg;\n ctx.fillRect(0, 0, width, height);\n }\n } else {\n const cam = sampleCamera(manifest.camera, tOut);\n const vis = visibleRect(cam, plane);\n\n // ---- the stage: matte background + card (chrome bar + footage) ----\n paintStageBackdrop(ctx, profile, theme);\n ctx.save();\n if (profile.stage) {\n paintStageCard(ctx, profile, theme, bundle.manifest.appUrl);\n roundRect(ctx, content.x, content.y, content.w, content.h, 0); // content area (card carries the radius)\n ctx.clip();\n }\n\n // ---- footage: frame blending kills 20→30fps judder during real motion ----\n const drawSrc = (img: Canvas, alpha: number) => {\n ctx.globalAlpha = alpha;\n ctx.drawImage(\n img,\n vis.x * frameScale, vis.y * frameScale, vis.w * frameScale, vis.h * frameScale,\n content.x, content.y, content.w, content.h,\n );\n ctx.globalAlpha = 1;\n };\n const pair = await store.framePairForTime(srcAt);\n // Blend only inside `source` segments (real motion): blending across a freeze would ghost\n // the NEXT action into a deliberate hold.\n if (segment.kind === 'source' && pair.b && pair.mix > 0.12 && pair.gapMs < 400) {\n drawSrc(pair.a, 1);\n drawSrc(pair.b, pair.mix);\n } else {\n drawSrc(pair.a, 1);\n }\n\n // ---- scene-boundary cross-dissolve: old footage fades into the new scene ----\n const tr = transitions.find((w) => tOut >= w.tStart && tOut <= w.tEnd);\n if (tr) {\n const u = clamp((tOut - tr.tStart) / Math.max(1, tr.tEnd - tr.tStart), 0, 1);\n if (u < 1) {\n const from = await store.frameForTime(tr.srcFrom);\n drawSrc(from, 1 - u);\n }\n }\n\n // ---- click spotlight: dim the surroundings, feather-punch the target ----\n const spot = activeSpotlight(spotlightSteps, tOut);\n if (spot) {\n const rect = spot.step.focusRectVp ?? spot.step.targetRectVp!;\n const proj = projectRect(rect, cam, plane);\n drawSpotlight(spotCtx, content, proj, spot.alpha);\n ctx.drawImage(spotCanvas, content.x, content.y);\n }\n\n // Cursor + ripples live on the source plane; project through the camera, then translate\n // into frame space by the stage origin.\n const cursorVp = sampleCursor(cursorPlan, tOut);\n const cursorOut = projectPoint(cursorVp, cam, plane);\n const rippleCenters = manifest.ripples.map((r) => {\n const p = projectPoint({ x: r.x, y: r.y }, cam, plane);\n return { x: p.x + content.x, y: p.y + content.y };\n });\n const glyph = cursorGlyphAt(manifest.steps, tOut);\n drawCursor(\n ctx,\n { x: cursorOut.x + content.x, y: cursorOut.y + content.y },\n cam.zoom,\n tOut,\n manifest.ripples,\n rippleCenters,\n theme,\n plane.outW / plane.vpW,\n glyph,\n );\n ctx.restore();\n }\n\n drawOverlays(ctx, manifest.overlays, tOut, theme, profile);\n await encoder.write(Buffer.from(ctx.getImageData(0, 0, width, height).data.buffer));\n\n if (i > 0 && i % 300 === 0) {\n const fpsNow = i / ((Date.now() - start) / 1000);\n log.debug(`rendered ${i}/${manifest.totalFrames} frames (${fpsNow.toFixed(0)} fps)`);\n }\n }\n await encoder.finish();\n const elapsed = (Date.now() - start) / 1000;\n log.ok(\n `rendered ${manifest.totalFrames} frames in ${elapsed.toFixed(1)}s (${(manifest.totalFrames / elapsed).toFixed(0)} fps) → ${outPath}`,\n );\n}\n\n/** Soft vertical gradient behind the stage, derived from the theme. */\nfunction paintStageBackdrop(ctx: SKRSContext2D, profile: { width: number; height: number }, theme: { bg: string; bgSubtle: string }): void {\n const g = ctx.createLinearGradient(0, 0, 0, profile.height);\n g.addColorStop(0, theme.bgSubtle);\n g.addColorStop(1, theme.bg);\n ctx.fillStyle = g;\n ctx.fillRect(0, 0, profile.width, profile.height);\n}\n\n/** The card: shadow, rounded body, browser-chrome bar (traffic dots + URL pill). */\nfunction paintStageCard(\n ctx: SKRSContext2D,\n profile: { stage?: { content: Rect; chromeH: number; radius: number }; width: number },\n theme: { surface: string; onSurfaceDim: string },\n appUrl: string,\n): void {\n const s = profile.stage!;\n const c = s.content;\n const cardX = c.x;\n const cardY = c.y - s.chromeH;\n const cardW = c.w;\n const cardH = c.h + s.chromeH;\n\n ctx.save();\n ctx.shadowColor = 'rgba(0,0,0,0.45)';\n ctx.shadowBlur = 42;\n ctx.shadowOffsetY = 14;\n ctx.fillStyle = '#20242e';\n roundRect(ctx, cardX, cardY, cardW, cardH, s.radius);\n ctx.fill();\n ctx.restore();\n\n if (s.chromeH > 0) {\n // Traffic dots\n const dotY = cardY + s.chromeH / 2;\n const dotR = Math.max(5, Math.round(s.chromeH * 0.14));\n const colors = ['#ff5f57', '#febc2e', '#28c840'];\n colors.forEach((col, i) => {\n ctx.fillStyle = col;\n ctx.beginPath();\n ctx.arc(cardX + 24 + i * (dotR * 2 + 9), dotY, dotR, 0, Math.PI * 2);\n ctx.fill();\n });\n // URL pill\n const url = displayUrl(appUrl);\n const pillH = Math.round(s.chromeH * 0.62);\n ctx.font = `500 ${Math.round(pillH * 0.52)}px Inter Medium`;\n const textW = ctx.measureText(url).width;\n const pillW = Math.min(cardW * 0.5, textW + 36);\n const pillX = cardX + (cardW - pillW) / 2;\n const pillY = cardY + (s.chromeH - pillH) / 2;\n ctx.fillStyle = 'rgba(255,255,255,0.08)';\n roundRect(ctx, pillX, pillY, pillW, pillH, pillH / 2);\n ctx.fill();\n ctx.fillStyle = 'rgba(255,255,255,0.55)';\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n ctx.fillText(url, pillX + pillW / 2, pillY + pillH / 2 + 1, pillW - 24);\n }\n}\n\nfunction displayUrl(appUrl: string): string {\n try {\n const u = new URL(appUrl);\n return u.host + (u.pathname !== '/' ? u.pathname : '');\n } catch {\n return appUrl;\n }\n}\n\n/** Which spotlight (if any) is active at tOut, with its ramped alpha. */\nfunction activeSpotlight(\n steps: StepMapEntry[],\n tOut: number,\n): { step: StepMapEntry; alpha: number } | null {\n for (const step of steps) {\n const from = step.outBeat - SPOTLIGHT_LEAD_MS;\n const to = step.outBeat + SPOTLIGHT_TAIL_MS;\n if (tOut < from || tOut > to) continue;\n const rampIn = clamp((tOut - from) / 180, 0, 1);\n const rampOut = clamp((to - tOut) / 250, 0, 1);\n return { step, alpha: SPOTLIGHT_MAX_DIM * Math.min(rampIn, rampOut) };\n }\n return null;\n}\n\n/** Dim layer with a feathered punch-out around the target, built on the scratch canvas. */\nfunction drawSpotlight(sctx: SKRSContext2D, content: Rect, proj: Rect, alpha: number): void {\n sctx.clearRect(0, 0, content.w, content.h);\n sctx.fillStyle = `rgba(6,8,14,${alpha.toFixed(3)})`;\n sctx.fillRect(0, 0, content.w, content.h);\n const pad = 14;\n sctx.save();\n sctx.globalCompositeOperation = 'destination-out';\n sctx.shadowColor = '#ffffff';\n sctx.shadowBlur = 30;\n sctx.fillStyle = '#ffffff';\n roundRect(sctx, proj.x - pad, proj.y - pad, proj.w + pad * 2, proj.h + pad * 2, 10);\n sctx.fill();\n sctx.restore();\n}\n\n/** Glyph for the active step: I-beam while typing, arrow otherwise. */\nfunction cursorGlyphAt(steps: StepMapEntry[], tOut: number): CursorGlyph {\n for (const s of steps) {\n if (s.kind === 'type' && tOut >= s.outStart && tOut <= s.outEnd) return 'ibeam';\n }\n return 'arrow';\n}\n","import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { createHash } from 'node:crypto';\nimport { createRequire } from 'node:module';\n\nconst require = createRequire(import.meta.url);\nconst ffprobePath: string = require('ffprobe-static').path;\nconst exec = promisify(execFile);\n\nexport interface NarrationOptions {\n /** Only 'say' (macOS local TTS) is implemented today; the seam is here for cloud providers. */\n provider: 'say';\n voice?: string;\n /** Words per minute (say-specific). */\n rate?: number;\n}\n\nexport interface NarrationLine {\n stepRef: string;\n text: string;\n}\n\nexport interface NarrationClip {\n stepRef: string;\n file: string;\n durationMs: number;\n}\n\n/** A text-to-speech backend: text → an audio file on disk. */\ninterface TtsProvider {\n readonly name: string;\n synth(text: string, outFile: string): Promise<void>;\n}\n\nclass SayProvider implements TtsProvider {\n readonly name = 'say';\n constructor(private voice: string, private rate: number) {}\n async synth(text: string, outFile: string): Promise<void> {\n // Pass the text via a file so em-dashes / quotes / apostrophes survive shell escaping.\n const txt = `${outFile}.txt`;\n await writeFile(txt, text);\n await exec('say', ['-v', this.voice, '-r', String(this.rate), '-f', txt, '-o', outFile]);\n }\n}\n\nfunction providerFor(opts: NarrationOptions): { provider: TtsProvider; voice: string; rate: number } {\n const voice = opts.voice ?? 'Samantha';\n const rate = opts.rate ?? 178;\n switch (opts.provider) {\n case 'say':\n return { provider: new SayProvider(voice, rate), voice, rate };\n default:\n throw new Error(`unknown TTS provider: ${opts.provider}`);\n }\n}\n\nasync function probeDurationMs(file: string): Promise<number> {\n const { stdout } = await exec(ffprobePath, [\n '-v', 'error', '-show_entries', 'format=duration', '-of', 'csv=p=0', file,\n ]);\n return Math.round(parseFloat(stdout.trim()) * 1000);\n}\n\n/**\n * Synthesize one clip per line. Clips are cached by a content hash of\n * (provider, voice, rate, text) so re-renders reuse them — keeping compose offline\n * and deterministic (same text+voice → same audio → same timing).\n */\nexport async function synthesizeNarration(\n lines: NarrationLine[],\n opts: NarrationOptions,\n cacheDir: string,\n): Promise<Map<string, NarrationClip>> {\n await mkdir(cacheDir, { recursive: true });\n const { provider, voice, rate } = providerFor(opts);\n const out = new Map<string, NarrationClip>();\n for (const { stepRef, text } of lines) {\n const key = createHash('sha256').update(`${provider.name}|${voice}|${rate}|${text}`).digest('hex').slice(0, 16);\n const file = join(cacheDir, `${key}.aiff`);\n if (!existsSync(file)) await provider.synth(text, file);\n out.set(stepRef, { stepRef, file, durationMs: await probeDurationMs(file) });\n }\n return out;\n}\n","import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { rename, mkdir } from 'node:fs/promises';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { createRequire } from 'node:module';\nimport type { StepMapEntry, ClickRipple } from '../compose/types.js';\nimport type { NarrationClip } from './tts.js';\nimport { AUDIO_LEAD_MS } from './timing.js';\n\nconst require = createRequire(import.meta.url);\nconst ffmpegPath: string = require('ffmpeg-static');\nconst exec = promisify(execFile);\n\nexport interface PlacedClip {\n stepRef: string;\n /** Output-clock ms the clip starts playing. */\n tStart: number;\n durMs: number;\n}\n\nexport interface AudioBedOptions {\n /** Narration clips per stepRef (absent = no narration). */\n narration?: Map<string, NarrationClip>;\n /** Click-beat times (output clock) that get a soft synthesized tick. */\n sfxBeats?: ClickRipple[];\n /** User-supplied music bed (no asset is bundled). */\n music?: { file: string; gainDb: number };\n /** Directory for the synthesized click sample (cached). */\n cacheDir: string;\n}\n\n/**\n * Build the full audio track — narration clips at their step starts, click ticks at ripple\n * beats, an optional music bed ducked under narration — normalize loudness (EBU R128, I=-16),\n * and mux it onto the rendered MP4. Returns where each narration clip landed so verification\n * can reason about voice windows.\n */\nexport async function mixAudio(\n videoPath: string,\n steps: StepMapEntry[],\n durationMs: number,\n opts: AudioBedOptions,\n): Promise<PlacedClip[]> {\n const placed = (opts.narration ? steps : [])\n .map((s) => ({ start: Math.round(s.outStart + AUDIO_LEAD_MS), clip: opts.narration!.get(s.stepRef) }))\n .filter((p): p is { start: number; clip: NarrationClip } => p.clip !== undefined);\n const beats = opts.sfxBeats ?? [];\n const hasMusic = !!opts.music;\n if (placed.length === 0 && beats.length === 0 && !hasMusic) return [];\n\n const durSec = (durationMs / 1000).toFixed(3);\n const args = ['-y', '-loglevel', 'error', '-i', videoPath];\n const inputs: string[] = []; // filter labels for the final mix\n const filters: string[] = [];\n let inputIdx = 1;\n\n // Silent full-length base keeps the mix spanning the whole video.\n args.push('-f', 'lavfi', '-t', durSec, '-i', 'anullsrc=r=44100:cl=stereo');\n const baseIdx = inputIdx++;\n inputs.push(`[${baseIdx}]`);\n\n // Narration clips, delayed to their step starts, pre-mixed into one voice bus.\n let voiceBus: string | null = null;\n if (placed.length > 0) {\n const labels: string[] = [];\n placed.forEach((p, i) => {\n args.push('-i', p.clip.file);\n const idx = inputIdx++;\n filters.push(\n `[${idx}]aformat=sample_rates=44100:channel_layouts=stereo,adelay=${p.start}|${p.start}[v${i}]`,\n );\n labels.push(`[v${i}]`);\n });\n filters.push(`${labels.join('')}amix=inputs=${labels.length}:normalize=0:duration=longest[voice]`);\n voiceBus = '[voice]';\n }\n\n // Click SFX: one synthesized sample, split and delayed to each beat.\n if (beats.length > 0) {\n const click = await ensureClickSample(opts.cacheDir);\n args.push('-i', click);\n const idx = inputIdx++;\n const splits = beats.map((_, i) => `[c${i}]`).join('');\n filters.push(`[${idx}]aformat=sample_rates=44100:channel_layouts=stereo,asplit=${beats.length}${splits}`);\n const labels: string[] = [];\n beats.forEach((b, i) => {\n const at = Math.max(0, Math.round(b.tOut));\n filters.push(`[c${i}]adelay=${at}|${at}[ck${i}]`);\n labels.push(`[ck${i}]`);\n });\n filters.push(`${labels.join('')}amix=inputs=${labels.length}:normalize=0:duration=longest[sfx]`);\n inputs.push('[sfx]');\n }\n\n // Music bed: looped to length, faded out, gained down — and DUCKED under narration.\n if (opts.music) {\n args.push('-stream_loop', '-1', '-i', opts.music.file);\n const idx = inputIdx++;\n const fadeStart = Math.max(0, durationMs / 1000 - 1.8).toFixed(2);\n filters.push(\n `[${idx}]aformat=sample_rates=44100:channel_layouts=stereo,atrim=0:${durSec},` +\n `volume=${opts.music.gainDb}dB,afade=t=out:st=${fadeStart}:d=1.8[mraw]`,\n );\n if (voiceBus) {\n // Duplicate the voice bus: one copy keys the compressor, one goes to the mix.\n filters.push(`${voiceBus}asplit=2[vmain][vkey]`);\n filters.push(`[mraw][vkey]sidechaincompress=threshold=0.02:ratio=8:attack=40:release=400[mduck]`);\n inputs.push('[mduck]', '[vmain]');\n voiceBus = null;\n } else {\n inputs.push('[mraw]');\n }\n }\n if (voiceBus) inputs.push(voiceBus);\n\n filters.push(\n `${inputs.join('')}amix=inputs=${inputs.length}:normalize=0:duration=longest,` +\n `loudnorm=I=-16:TP=-1.5:LRA=11[mix]`,\n );\n\n const tmp = videoPath.replace(/\\.mp4$/, '.audio.tmp.mp4');\n args.push(\n '-filter_complex', filters.join(';'),\n '-map', '0:v:0', '-map', '[mix]',\n '-c:v', 'copy', '-c:a', 'aac', '-b:a', '160k',\n '-shortest', '-movflags', '+faststart',\n tmp,\n );\n await exec(ffmpegPath, args, { maxBuffer: 1 << 24 });\n await rename(tmp, videoPath);\n return placed.map((p) => ({ stepRef: p.clip.stepRef, tStart: p.start, durMs: p.clip.durationMs }));\n}\n\n/** Synthesize the click sample once: a soft 2-tone tick with a fast decay (no bundled assets). */\nasync function ensureClickSample(cacheDir: string): Promise<string> {\n await mkdir(cacheDir, { recursive: true });\n const file = join(cacheDir, 'click.wav');\n if (existsSync(file)) return file;\n await exec(ffmpegPath, [\n '-y', '-loglevel', 'error',\n '-f', 'lavfi', '-i', 'sine=frequency=1250:duration=0.05',\n '-f', 'lavfi', '-i', 'sine=frequency=2500:duration=0.03',\n '-filter_complex',\n '[0]volume=0.5[a];[1]volume=0.22[b];[a][b]amix=inputs=2:normalize=0,afade=t=in:d=0.004,afade=t=out:st=0.014:d=0.036,aformat=sample_rates=44100:channel_layouts=stereo',\n file,\n ]);\n return file;\n}\n","import { join } from 'node:path';\nimport { writeFile } from 'node:fs/promises';\nimport type { BundleData } from '../bundle/types.js';\nimport type { Spec } from '../spec/schema.js';\nimport { resolveResolution } from '../spec/schema.js';\nimport { resolveTheme, type ResolvedTheme } from '../theme/index.js';\nimport type { ComposeDiagnostics, ComposeManifest, OutputProfile } from './types.js';\nimport { profileForAspect, withStage } from './types.js';\nimport { kindProfile } from './kinds.js';\nimport { buildTimeline, pacingConfig } from './timeline/pacing.js';\nimport { planCamera } from './camera/planner.js';\nimport { planCursor } from './cursor/path.js';\nimport { buildOverlays } from './overlays/build.js';\nimport { renderVideo } from './render/renderer.js';\nimport { registerFonts } from '../theme/index.js';\nimport { sha256File } from '../bundle/hash.js';\nimport { log } from '../shared/log.js';\nimport { actionEvents } from '../capture/events.js';\nimport { writeCaption, writeNarration, type StepTexts } from './captions.js';\nimport { flattenSteps } from '../spec/schema.js';\nimport { synthesizeNarration, type NarrationClip } from '../audio/tts.js';\nimport { mixAudio } from '../audio/mux.js';\n\nexport interface ComposeResult {\n videoPath: string;\n manifestPath: string;\n manifest: ComposeManifest;\n}\n\n/** Pure planning: bundle + spec + theme → compose manifest. No rendering. */\n/** Per-step caption/narration text from the LIVE spec, keyed by stepRef — so text edits are a\n * re-compose, never a re-capture. */\nexport function specStepTexts(spec: Spec): Map<string, StepTexts> {\n const map = new Map<string, StepTexts>();\n for (const a of flattenSteps(spec)) {\n const s = a.step;\n if (s.caption || s.narration) {\n map.set(`${a.sceneId}/${a.stepIndex}`, {\n ...(s.caption ? { caption: s.caption } : {}),\n ...(s.narration ? { narration: s.narration } : {}),\n });\n }\n }\n return map;\n}\n\nexport function plan(\n bundle: BundleData,\n spec: Spec,\n theme?: ResolvedTheme,\n profile?: OutputProfile,\n audioMs?: Map<string, number>,\n): ComposeManifest {\n registerFonts();\n const resolvedTheme = theme ?? resolveTheme(spec);\n const kind = kindProfile(spec.output.kind);\n let prof: OutputProfile =\n profile ?? profileForAspect(spec.output.aspect, resolveResolution(spec), spec.output.fps);\n // The stage (matte + card + browser chrome) is the produced look; bug-repro stays literal.\n if (kind.stage && !prof.stage) prof = withStage(prof, true);\n const diagnostics: ComposeDiagnostics = { overflows: [], cameraFallbacks: [], clockWarnings: [] };\n const cfg = pacingConfig(spec.output.pacing ?? kind.pacing, kind);\n // Long-form teaching dwell: stretch the min-step, per-action holds, and outro so\n // each screen lingers. Idle-gap trimming and title card stay fixed (they're not dwell).\n const dwell = spec.output.dwellScale;\n if (dwell && dwell !== 1) {\n cfg.minStepMs *= dwell;\n cfg.outroMs *= dwell;\n for (const k of Object.keys(cfg.holds) as (keyof typeof cfg.holds)[]) cfg.holds[k] *= dwell;\n }\n const timeline = buildTimeline(bundle.events, cfg, audioMs);\n\n // Closing card: a title-card-styled segment appended after the outro.\n const END_CARD_MS = 2400;\n if (spec.output.endCard) {\n const endStart = timeline.durationMs;\n timeline.segments.push({ kind: 'card', outStart: endStart, outEnd: endStart + END_CARD_MS, cardId: 'end' });\n timeline.durationMs += END_CARD_MS;\n }\n // FAILURE CLIP: a partial bundle (capture died mid-run) composes into a diagnosis — the\n // captured footage plays through, then holds on a red card naming the step and the error.\n // This is the artifact a red CI run hands the developer: watch what happened, not a stack line.\n const FAILURE_CARD_MS = 3200;\n if (bundle.manifest.partial && bundle.manifest.failure) {\n const failStart = timeline.durationMs;\n timeline.segments.push({ kind: 'card', outStart: failStart, outEnd: failStart + FAILURE_CARD_MS, cardId: 'failure' });\n timeline.durationMs += FAILURE_CARD_MS;\n }\n\n // Clock sanity: warn when the action beat has no frame within 150ms after it.\n for (const step of timeline.steps) {\n const hasFrame = bundle.frames.some((f) => f.t >= step.srcAction && f.t <= step.srcAction + 150);\n if (!hasFrame && step.kind !== 'wait' && step.kind !== 'expect') {\n diagnostics.clockWarnings.push(`${step.stepRef}: no source frame within 150ms after the action`);\n }\n }\n\n const camera = planCamera(timeline.steps, bundle.events, prof, timeline.durationMs, {\n emphasis: kind.cameraEmphasis,\n });\n diagnostics.cameraFallbacks.push(...camera.fallbacks);\n const cursor = planCursor(timeline.steps, bundle.events);\n\n // Cross-dissolve at scene boundaries: the old footage (held at its last frame) fades into the\n // new scene instead of a hard cut.\n const transitions: { tStart: number; tEnd: number; srcFrom: number }[] = [];\n for (let i = 1; i < timeline.steps.length; i++) {\n const prev = timeline.steps[i - 1]!;\n const cur = timeline.steps[i]!;\n if (cur.sceneId !== prev.sceneId) {\n const tStart = cur.outStart;\n transitions.push({ tStart, tEnd: tStart + 280, srcFrom: Math.max(0, prev.srcSettled - 1) });\n }\n }\n\n const subtitle = spec.subtitle ?? safeHost(bundle.manifest.appUrl);\n const sceneTitles = new Map(\n spec.scenes.filter((s) => s.title).map((s) => [s.id, s.title as string]),\n );\n const overlays = buildOverlays(\n timeline.steps,\n bundle.events,\n resolvedTheme,\n prof,\n spec.title,\n subtitle,\n cfg.titleCardMs,\n diagnostics,\n kind,\n sceneTitles,\n camera.keyframes,\n specStepTexts(spec),\n );\n if (spec.output.endCard && !bundle.manifest.partial) {\n const endStart = timeline.durationMs - END_CARD_MS;\n overlays.push({ kind: 'dip', tStart: endStart - 350, tEnd: endStart, direction: 'out' });\n overlays.push({\n kind: 'titleCard',\n cardId: 'end',\n title: spec.output.endCard.title,\n ...(spec.output.endCard.subtitle ? { subtitle: spec.output.endCard.subtitle } : {}),\n tStart: endStart,\n tEnd: timeline.durationMs,\n });\n }\n if (bundle.manifest.partial && bundle.manifest.failure) {\n const failStart = timeline.durationMs - FAILURE_CARD_MS;\n overlays.push({ kind: 'dip', tStart: failStart - 300, tEnd: failStart, direction: 'out' });\n overlays.push({\n kind: 'failureCard',\n stepRef: bundle.manifest.failure.stepRef,\n message: bundle.manifest.failure.message,\n tStart: failStart,\n tEnd: timeline.durationMs,\n });\n }\n\n const totalFrames = Math.ceil((timeline.durationMs / 1000) * prof.fps);\n return {\n schema: 'playhead/compose@1',\n profile: prof,\n viewport: bundle.manifest.viewport,\n durationMs: timeline.durationMs,\n totalFrames,\n segments: timeline.segments,\n camera: camera.keyframes,\n cursor: cursor.segments,\n ripples: cursor.ripples,\n overlays,\n ...(transitions.length > 0 ? { transitions } : {}),\n steps: timeline.steps,\n theme: resolvedTheme,\n diagnostics,\n bundleHashes: bundle.manifest.hashes,\n };\n}\n\nexport interface ComposeOptions {\n outDir: string;\n fileName?: string;\n theme?: ResolvedTheme;\n profile?: OutputProfile;\n}\n\n/** Full composition: plan + render + write manifest. Never touches the live app. */\nexport async function compose(bundle: BundleData, spec: Spec, opts: ComposeOptions): Promise<ComposeResult> {\n // Voice narration (optional): synthesize each step's spoken line first, so pacing\n // can grow every step to fit it. TTS is local (macOS `say`) and cached in the bundle.\n const audioCfg = spec.output.audio;\n let narration: Map<string, NarrationClip> | undefined;\n let audioMs: Map<string, number> | undefined;\n if (audioCfg && audioCfg.narration === 'tts') {\n const texts = specStepTexts(spec);\n const lines = actionEvents(bundle.events)\n .map((e) => {\n const ref = `${e.sceneId}/${e.stepIndex}`;\n return { stepRef: ref, text: writeNarration(e, texts.get(ref)) };\n })\n .filter((l): l is { stepRef: string; text: string } => typeof l.text === 'string' && l.text.length > 0);\n log.info(`synthesizing narration: ${lines.length} lines (${audioCfg.provider}, voice ${audioCfg.voice ?? 'Samantha'})`);\n try {\n narration = await synthesizeNarration(lines, audioCfg, join(opts.outDir, 'narration'));\n audioMs = new Map([...narration].map(([k, v]) => [k, v.durationMs]));\n } catch (e) {\n // A host without the TTS binary (e.g. Linux CI with provider `say`) must not kill the\n // render — degrade to a silent video LOUDLY. `playhead doctor --ci` reports this upfront.\n log.warn(`narration unavailable on this host (${(e as Error).message.split('\\n')[0]}) — rendering WITHOUT voice`);\n narration = undefined;\n audioMs = undefined;\n }\n }\n\n const manifest = plan(bundle, spec, opts.theme, opts.profile, audioMs);\n for (const w of manifest.diagnostics.clockWarnings) log.warn(w);\n for (const f of manifest.diagnostics.cameraFallbacks) log.warn(f);\n\n const videoPath = join(opts.outDir, opts.fileName ?? 'out.mp4');\n log.info(\n `composing ${(manifest.durationMs / 1000).toFixed(1)}s (${manifest.totalFrames} frames @ ${manifest.profile.fps}fps, ${manifest.profile.width}x${manifest.profile.height})`,\n );\n await renderVideo(bundle, manifest, videoPath);\n\n // Audio bed: narration + click SFX + (user-supplied) music, ducked and loudness-normalized.\n if (audioCfg && (narration || audioCfg.sfx || audioCfg.music)) {\n const clips = await mixAudio(videoPath, manifest.steps, manifest.durationMs, {\n ...(narration ? { narration } : {}),\n ...(audioCfg.sfx ? { sfxBeats: manifest.ripples } : {}),\n ...(audioCfg.music ? { music: audioCfg.music } : {}),\n cacheDir: join(opts.outDir, 'narration'),\n });\n if (narration) {\n manifest.audio = {\n narrated: true,\n provider: audioCfg.provider,\n voice: audioCfg.voice ?? 'Samantha',\n lines: clips.length,\n clips,\n };\n }\n log.info(\n `✓ audio: ${clips.length} narration line(s)` +\n `${audioCfg.sfx ? `, ${manifest.ripples.length} click(s)` : ''}` +\n `${audioCfg.music ? ', music bed' : ''} → ${videoPath}`,\n );\n }\n\n manifest.videoSha256 = await sha256File(videoPath);\n const manifestPath = join(opts.outDir, 'compose-manifest.json');\n await writeFile(manifestPath, JSON.stringify(manifest, null, 2));\n return { videoPath, manifestPath, manifest };\n}\n\nexport async function renderFromManifest(bundle: BundleData, manifest: ComposeManifest, videoPath: string): Promise<void> {\n await renderVideo(bundle, manifest, videoPath);\n}\n\nfunction safeHost(url: string): string {\n try {\n return new URL(url).host;\n } catch {\n return url;\n }\n}\n","import sharp from 'sharp';\nimport { ffmpegPath, ffprobePath, runBinaryRaw, runBinary } from '../shared/ffmpeg.js';\nimport type { BundleData } from '../bundle/types.js';\nimport { frameIndexForTime, framePath } from '../bundle/reader.js';\n\n/** Extract grayscale frames from the output video at a fixed rate. */\nexport async function extractGrayFrames(\n videoPath: string,\n fps: number,\n w: number,\n h: number,\n): Promise<{ frames: Buffer[]; intervalMs: number }> {\n const res = await runBinaryRaw(ffmpegPath(), [\n '-hide_banner', '-loglevel', 'error',\n '-i', videoPath,\n '-vf', `fps=${fps},scale=${w}:${h}`,\n '-f', 'rawvideo',\n '-pix_fmt', 'gray',\n 'pipe:1',\n ]);\n if (res.code !== 0) throw new Error(`frame extraction failed: ${res.stderr}`);\n const frameSize = w * h;\n const frames: Buffer[] = [];\n for (let off = 0; off + frameSize <= res.stdout.length; off += frameSize) {\n frames.push(res.stdout.subarray(off, off + frameSize));\n }\n return { frames, intervalMs: 1000 / fps };\n}\n\n/** Extract one PNG frame from the output video at a timestamp (ms). */\nexport async function extractFrameAt(videoPath: string, tMs: number): Promise<Buffer> {\n const res = await runBinaryRaw(ffmpegPath(), [\n '-hide_banner', '-loglevel', 'error',\n '-ss', (Math.max(0, tMs) / 1000).toFixed(3),\n '-i', videoPath,\n '-frames:v', '1',\n '-f', 'image2pipe',\n '-vcodec', 'png',\n 'pipe:1',\n ]);\n if (res.code !== 0 || res.stdout.length === 0) {\n throw new Error(`could not extract frame at ${tMs}ms: ${res.stderr}`);\n }\n return res.stdout;\n}\n\nexport interface ProbeInfo {\n codec: string;\n width: number;\n height: number;\n durationSec: number;\n fps: number;\n}\n\nexport async function probeVideo(videoPath: string): Promise<ProbeInfo> {\n const res = await runBinary(ffprobePath(), [\n '-v', 'error',\n '-print_format', 'json',\n '-show_format',\n '-show_streams',\n videoPath,\n ]);\n if (res.code !== 0) throw new Error(`ffprobe failed: ${res.stderr}`);\n const json = JSON.parse(res.stdout) as {\n streams?: { codec_type: string; codec_name: string; width: number; height: number; avg_frame_rate: string }[];\n format?: { duration?: string };\n };\n const v = json.streams?.find((s) => s.codec_type === 'video');\n if (!v) throw new Error('no video stream found');\n const [num, den] = v.avg_frame_rate.split('/').map(Number);\n return {\n codec: v.codec_name,\n width: v.width,\n height: v.height,\n durationSec: Number(json.format?.duration ?? 0),\n fps: den ? num! / den : 0,\n };\n}\n\nexport function meanAbsDiff(a: Buffer, b: Buffer): number {\n const n = Math.min(a.length, b.length);\n let sum = 0;\n for (let i = 0; i < n; i++) sum += Math.abs(a[i]! - b[i]!);\n return sum / n;\n}\n\nexport function variance(a: Buffer): number {\n let sum = 0;\n for (let i = 0; i < a.length; i++) sum += a[i]!;\n const mean = sum / a.length;\n let v = 0;\n for (let i = 0; i < a.length; i++) v += (a[i]! - mean) ** 2;\n return v / a.length;\n}\n\n/** Decode a capture-bundle source frame to grayscale at reduced width. */\nexport async function sourceFrameGray(\n bundle: BundleData,\n tMs: number,\n width: number,\n): Promise<{ data: Buffer; w: number; h: number; frameT: number }> {\n const idx = frameIndexForTime(bundle.frames, tMs);\n const { data, info } = await sharp(framePath(bundle, idx))\n .resize({ width })\n .grayscale()\n .raw()\n .toBuffer({ resolveWithObject: true });\n return { data, w: info.width, h: info.height, frameT: bundle.frames[idx]!.t };\n}\n\n/** Decode a region of a source frame (frame px) to grayscale raw. */\nexport async function sourceRegionGray(\n bundle: BundleData,\n tMs: number,\n region: { x: number; y: number; w: number; h: number },\n preferAfter = false,\n color = false,\n): Promise<Buffer | null> {\n let idx = frameIndexForTime(bundle.frames, tMs);\n if (preferAfter && idx + 1 < bundle.frames.length && bundle.frames[idx]!.t < tMs) idx += 1;\n const meta = await sharp(framePath(bundle, idx)).metadata();\n const fw = meta.width ?? 0;\n const fh = meta.height ?? 0;\n const x = Math.max(0, Math.round(region.x));\n const y = Math.max(0, Math.round(region.y));\n const w = Math.min(Math.round(region.w), fw - x);\n const h = Math.min(Math.round(region.h), fh - y);\n if (w < 4 || h < 4) return null;\n // Grayscale by default (cheap); color on request — a pastel hue swap (blue→red badge) is\n // nearly luminance-neutral and INVISIBLE to a grayscale diff.\n let img = sharp(framePath(bundle, idx)).extract({ left: x, top: y, width: w, height: h });\n if (!color) img = img.grayscale();\n const { data } = await img.raw().toBuffer({ resolveWithObject: true });\n return data;\n}\n\n/** Crop a region from PNG bytes (or an image file), grayscale, resize to 48x48 raw. */\nexport async function regionGray48(input: Buffer | string, rect: { x: number; y: number; w: number; h: number }): Promise<Buffer | null> {\n try {\n const img = sharp(input);\n const meta = await img.metadata();\n const W = meta.width ?? 0;\n const H = meta.height ?? 0;\n const left = Math.max(0, Math.round(rect.x));\n const top = Math.max(0, Math.round(rect.y));\n const width = Math.min(W - left, Math.round(rect.w));\n const height = Math.min(H - top, Math.round(rect.h));\n if (width < 8 || height < 8) return null;\n return await sharp(input).extract({ left, top, width, height }).grayscale().resize(48, 48, { fit: 'fill' }).raw().toBuffer();\n } catch {\n return null;\n }\n}\n\n/** Normalized cross-correlation of two equal-length gray buffers, in [-1, 1]. */\nexport function normalizedCorrelation(a: Buffer, b: Buffer): number {\n const n = Math.min(a.length, b.length);\n let ma = 0;\n let mb = 0;\n for (let i = 0; i < n; i++) {\n ma += a[i]!;\n mb += b[i]!;\n }\n ma /= n;\n mb /= n;\n let num = 0;\n let da = 0;\n let db = 0;\n for (let i = 0; i < n; i++) {\n const xa = a[i]! - ma;\n const xb = b[i]! - mb;\n num += xa * xb;\n da += xa * xa;\n db += xb * xb;\n }\n // Two flat regions (zero variance) are \"the same\" for our purposes.\n if (da < 1e-6 || db < 1e-6) return da < 1e-6 && db < 1e-6 ? 1 : 0;\n return num / Math.sqrt(da * db);\n}\n","import type { VerifyContext, CheckResult, CheckEvidence } from './types.js';\nimport { stageContent, actReactWindows } from '../compose/types.js';\nimport { sampleCamera } from '../compose/camera/interpolate.js';\nimport { sampleCursor, type CursorPlan } from '../compose/cursor/path.js';\nimport { segmentAt, sampleSource } from '../compose/timeline/pacing.js';\nimport { actionEvents } from '../capture/events.js';\nimport { projectRect, rectContains, type CameraPlane, type Rect } from '../shared/geometry.js';\nimport {\n extractFrameAt,\n extractGrayFrames,\n meanAbsDiff,\n normalizedCorrelation,\n probeVideo,\n regionGray48,\n sourceFrameGray,\n sourceRegionGray,\n variance,\n} from './media.js';\nimport { framePath, frameIndexForTime } from '../bundle/reader.js';\nimport { ffmpegPath, ffprobePath, runBinary } from '../shared/ffmpeg.js';\n\nconst EFFECT_KINDS = new Set(['click', 'dblclick', 'type', 'select', 'goto']);\nconst CLICK_KINDS = new Set(['click', 'dblclick', 'select']);\n\n/** The camera projects into STAGE-CONTENT space (same space the planner and renderer use). */\nfunction plane(ctx: VerifyContext): CameraPlane {\n const content = stageContent(ctx.manifest.profile);\n return {\n vpW: ctx.manifest.viewport.w,\n vpH: ctx.manifest.viewport.h,\n outW: content.w,\n outH: content.h,\n };\n}\n\n/** 1. Every target legibly in frame around its action beat. */\nexport async function checkTargetInFrame(ctx: VerifyContext): Promise<CheckResult> {\n const p = plane(ctx);\n const frame: Rect = { x: 0, y: 0, w: p.outW, h: p.outH };\n const evidence: CheckEvidence[] = [];\n let checked = 0;\n let minHeight = Infinity;\n\n // Captions that are visible during a step's hold — the target must not hide behind them.\n const captions = ctx.manifest.overlays.filter((o) => o.kind === 'caption');\n for (const step of ctx.manifest.steps) {\n // The framing promise mirrors the planner exactly (same shared helper): an act→react step\n // promises the action target around the beat and the focused payoff during the settled\n // hold; otherwise the focused rect (or target) across the whole hold. The camera's travel\n // between act and react windows is unchecked by design.\n const handoff = actReactWindows(step);\n const rect = step.focusRectVp ?? step.targetRectVp;\n const windows = handoff\n ? [handoff.act, handoff.react]\n : rect\n ? [{ rect, from: Math.max(step.outStart, step.outBeat - 60), to: step.outEnd }]\n : [];\n if (windows.length === 0) continue;\n checked += 1;\n for (const w of windows)\n for (let t = w.from; t <= w.to; t += 100) {\n const rect = w.rect;\n const cam = sampleCamera(ctx.manifest.camera, t);\n const proj = projectRect(rect, cam, p);\n minHeight = Math.min(minHeight, proj.h);\n if (!rectContains(frame, proj, 2)) {\n evidence.push({ stepRef: step.stepRef, t, note: `target cropped by frame edge (projected ${fmtRect(proj)})` });\n break;\n }\n // A scroll's anchor element is just where we scrolled to — the viewer watches the list\n // move, not that element, so it need only be in frame, not meet the legibility floor.\n // Same for an explicit `focus: wide`: the author chose context over close-up, so the\n // target must be visible but is exempt from the close-up legibility floor.\n if (step.kind !== 'scroll' && step.focus !== 'wide' && proj.h < 28) {\n evidence.push({ stepRef: step.stepRef, t, note: `target renders too small (${proj.h.toFixed(0)}px high)` });\n break;\n }\n // Captions live in FRAME space; the projection is in stage-content space — translate\n // before comparing (the stage origin is (0,0) when no stage is set).\n const content = stageContent(ctx.manifest.profile);\n const projFrame: Rect = { x: proj.x + content.x, y: proj.y + content.y, w: proj.w, h: proj.h };\n const cap = captions.find((c) => t >= c.tStart + 150 && t <= c.tEnd - 150 && rectsOverlap(c.box, projFrame));\n if (cap) {\n evidence.push({ stepRef: step.stepRef, t, note: `caption \"${cap.text}\" overlaps the target` });\n break;\n }\n }\n }\n if (checked === 0) return { id: 'target-in-frame', status: 'skip', details: 'no steps with targets' };\n return evidence.length > 0\n ? { id: 'target-in-frame', status: 'fail', details: `${evidence.length}/${checked} targets violate framing`, evidence }\n : {\n id: 'target-in-frame',\n status: 'pass',\n details: `${checked}/${checked} targets fully framed, min rendered height ${minHeight === Infinity ? '—' : minHeight.toFixed(0) + 'px'}`,\n };\n}\n\n/** 2. Rendered cursor sits on the target at each click beat. */\nexport async function checkCursorOnTarget(ctx: VerifyContext): Promise<CheckResult> {\n const cursorPlan: CursorPlan = {\n segments: ctx.manifest.cursor,\n ripples: ctx.manifest.ripples,\n restStart: { x: ctx.manifest.viewport.w / 2, y: ctx.manifest.viewport.h * 0.6 },\n };\n const evidence: CheckEvidence[] = [];\n let checked = 0;\n for (const step of ctx.manifest.steps) {\n if (!CLICK_KINDS.has(step.kind) || !step.targetRectVp) continue;\n checked += 1;\n const pos = sampleCursor(cursorPlan, step.outBeat);\n const r = step.targetRectVp;\n const pad = 4;\n const inside =\n pos.x >= r.x - pad && pos.x <= r.x + r.w + pad && pos.y >= r.y - pad && pos.y <= r.y + r.h + pad;\n if (!inside) {\n evidence.push({\n stepRef: step.stepRef,\n t: step.outBeat,\n note: `cursor at (${pos.x.toFixed(0)},${pos.y.toFixed(0)}) missed target ${fmtRect(r)}`,\n });\n }\n }\n if (checked === 0) return { id: 'cursor-on-target', status: 'skip', details: 'no click steps' };\n return evidence.length > 0\n ? { id: 'cursor-on-target', status: 'fail', details: `${evidence.length}/${checked} clicks miss their target`, evidence }\n : { id: 'cursor-on-target', status: 'pass', details: `${checked}/${checked} clicks land on target` };\n}\n\n/** 3. Every action visibly changed the UI (dead-click detection). */\nexport async function checkActionEffect(ctx: VerifyContext): Promise<CheckResult> {\n const evidence: CheckEvidence[] = [];\n const inconclusive: CheckEvidence[] = [];\n let checked = 0;\n const frameScale = ctx.bundle.manifest.frameW / ctx.manifest.viewport.w;\n\n const lastFrameT = ctx.bundle.frames[ctx.bundle.frames.length - 1]!.t;\n const steps = ctx.manifest.steps;\n let skippedMasked = 0;\n for (let i = 0; i < steps.length; i++) {\n const step = steps[i]!;\n if (!EFFECT_KINDS.has(step.kind)) continue;\n // A masked field intentionally hides its own change — its effect is unverifiable by design.\n if (step.masked) {\n skippedMasked += 1;\n continue;\n }\n checked += 1;\n // Sample the \"after\" state at this step's settled hold, just before the next action — for an\n // instant hash-route navigation the settle timestamp itself can precede the first post-nav\n // frame, so compare against the fully-settled view instead.\n const nextAction = i + 1 < steps.length ? steps[i + 1]!.srcAction : lastFrameT;\n const afterT = Math.max(step.srcSettled, nextAction - 60);\n const before = await sourceFrameGray(ctx.bundle, step.srcAction - 40, 320);\n const after = await sourceFrameGray(ctx.bundle, afterT, 320);\n if (after.frameT <= before.frameT) {\n // No distinct post-action frame was captured (a capture-loop gap, e.g. under CPU load).\n // Absence of frames can't prove absence of effect, so this is inconclusive, not a failure.\n inconclusive.push({ stepRef: step.stepRef, note: 'no post-action frame captured to compare' });\n continue;\n }\n if (before.frameT >= step.srcAction) {\n // The \"before\" sample clamped to a frame AT/AFTER the action (no pre-action footage —\n // e.g. the first grabs stalled during initial load). Comparing post to post proves\n // nothing either way.\n inconclusive.push({ stepRef: step.stepRef, note: 'no pre-action frame captured to compare' });\n continue;\n }\n const overall = meanAbsDiff(before.data, after.data);\n let regionDiff = 0;\n // Measure where the effect is EXPECTED: the action target, and — for act→react steps —\n // the focused payoff (changing a select recolors the badge ELSEWHERE; the payoff region\n // is where the change actually lands). Take the strongest signal.\n const regions = [step.targetRectVp, step.focusRectVp].filter((r): r is Rect => !!r);\n for (const r of regions) {\n const region = scaleRect(r, frameScale);\n const [ra, rb] = await Promise.all([\n sourceRegionGray(ctx.bundle, step.srcAction - 40, region, false, true),\n sourceRegionGray(ctx.bundle, afterT, region, true, true),\n ]);\n if (ra && rb && ra.length === rb.length) regionDiff = Math.max(regionDiff, meanAbsDiff(ra, rb));\n }\n // Typing changes only a few pixels page-wide, so the local target region is the real signal.\n if (overall < 0.5 && regionDiff < 2) {\n evidence.push({\n stepRef: step.stepRef,\n t: step.outBeat,\n note: `no visible effect (frame diff ${overall.toFixed(2)}, target diff ${regionDiff.toFixed(2)})`,\n });\n }\n }\n if (checked === 0) {\n return {\n id: 'action-effect',\n status: 'skip',\n details: skippedMasked > 0 ? `no verifiable actions (${skippedMasked} masked)` : 'no effectful actions',\n };\n }\n const maskedNote = skippedMasked > 0 ? ` (${skippedMasked} masked skipped)` : '';\n const inconcNote = inconclusive.length > 0 ? `, ${inconclusive.length} inconclusive (capture gap)` : '';\n if (evidence.length > 0) {\n return {\n id: 'action-effect',\n status: 'fail',\n details: `${evidence.length}/${checked} actions show no visible effect${maskedNote}${inconcNote}`,\n evidence: [...evidence, ...inconclusive],\n };\n }\n if (inconclusive.length > 0) {\n return {\n id: 'action-effect',\n status: 'warn',\n details: `${checked - inconclusive.length}/${checked} actions visibly effective; ${inconclusive.length} unverified (capture gap)${maskedNote}`,\n evidence: inconclusive,\n };\n }\n return { id: 'action-effect', status: 'pass', details: `${checked}/${checked} actions visibly effective${maskedNote}` };\n}\n\n/** 4. No unplanned frozen footage, no blank frames, in the delivered video. */\nexport async function checkFrozenBlank(ctx: VerifyContext): Promise<CheckResult> {\n const { frames, intervalMs } = await extractGrayFrames(ctx.videoPath, 2, 320, 180);\n if (frames.length < 2) return { id: 'frozen-blank', status: 'fail', details: 'could not decode output frames' };\n const evidence: CheckEvidence[] = [];\n\n // Intentional near-uniform frames: title cards, and the dip-to-background fades around them\n // (which momentarily paint mostly theme background). These are design, not dead footage.\n const dips = ctx.manifest.overlays.filter((o) => o.kind === 'dip');\n const inTransition = (t: number) =>\n segmentAt(ctx.manifest.segments, t).kind === 'card' || dips.some((d) => t >= d.tStart - 60 && t <= d.tEnd + 60);\n\n // Blank frames.\n for (let i = 0; i < frames.length; i++) {\n const t = i * intervalMs;\n if (inTransition(t)) continue;\n if (variance(frames[i]!) < 2) {\n evidence.push({ t, note: `blank frame at ${(t / 1000).toFixed(1)}s` });\n }\n }\n\n // Frozen runs: identical stretches that cross more than one step beat, or absurdly long.\n // A masked step is intentionally static on screen (the overlay hides the typing), so its\n // window is legitimately \"frozen\" — exclude it, as action-effect does.\n const maskedWindows = ctx.manifest.steps\n .filter((s) => s.masked)\n .map((s) => ({ start: s.outStart, end: s.outEnd }));\n const inMaskedWindow = (t0: number, t1: number) =>\n maskedWindows.some((w) => t1 >= w.start - 200 && t0 <= w.end + 200);\n\n // The final section (last action through the outro) is an intended hold on the result — a\n // walkthrough often ends held on its final state — so static footage there is not a stall.\n const lastBeat = ctx.manifest.steps.reduce((m, s) => Math.max(m, s.outBeat), 0);\n\n // A narrated video legitimately holds on a static screen WHILE ITS SPOKEN LINE PLAYS — the\n // voice carries it. But that must never blanket-disable stall detection: a frozen run is only\n // exempt when a narration clip actually covers it. (Manifests from before clip windows were\n // recorded fall back to the blanket exemption rather than mis-failing old renders.)\n const narrated = !!ctx.manifest.audio?.narrated;\n const clipWindows = (ctx.manifest.audio?.clips ?? []).map((c) => ({\n start: c.tStart - 300,\n end: c.tStart + c.durMs + 1200, // clip + the tail-and-extend hold pacing grants it\n }));\n const voiceCovers = (t0: number, t1: number) =>\n clipWindows.length === 0\n ? narrated // legacy manifests: no window data — keep the old blanket behavior\n : clipWindows.some((w) => t0 >= w.start && t1 <= w.end);\n\n let runStart = 0;\n for (let i = 1; i <= frames.length; i++) {\n const identical = i < frames.length && meanAbsDiff(frames[i]!, frames[i - 1]!) < 0.15;\n if (!identical) {\n const runMs = (i - 1 - runStart) * intervalMs;\n const t0 = runStart * intervalMs;\n const t1 = (i - 1) * intervalMs;\n const inFinalHold = t0 >= lastBeat - 800;\n if (runMs > 2000 && !inMaskedWindow(t0, t1) && !inFinalHold && !(narrated && voiceCovers(t0, t1))) {\n const beatsInside = ctx.manifest.steps.filter((s) => s.outBeat > t0 + 200 && s.outBeat < t1 - 200);\n if (beatsInside.length >= 1 && runMs > 2500) {\n evidence.push({\n t: t0,\n note: `frozen footage ${(runMs / 1000).toFixed(1)}s spanning ${beatsInside.length} action beat(s)`,\n });\n } else if (runMs > 8000) {\n evidence.push({ t: t0, note: `frozen footage for ${(runMs / 1000).toFixed(1)}s` });\n }\n }\n runStart = i;\n }\n }\n return evidence.length > 0\n ? { id: 'frozen-blank', status: 'fail', details: `${evidence.length} frozen/blank issue(s)`, evidence }\n : { id: 'frozen-blank', status: 'pass', details: `${frames.length} sampled output frames live and non-blank` };\n}\n\n/** 5. Captions legible: no truncation, font floor respected, inside safe bounds. */\nexport async function checkCaptions(ctx: VerifyContext): Promise<CheckResult> {\n const evidence: CheckEvidence[] = [];\n let warned = 0;\n let count = 0;\n const out: Rect = { x: 0, y: 0, w: ctx.manifest.profile.width, h: ctx.manifest.profile.height };\n for (const o of ctx.manifest.overlays) {\n if (o.kind !== 'caption') continue;\n count += 1;\n if (o.truncated) evidence.push({ stepRef: o.stepRef, note: `caption truncated: \"${o.text}\"` });\n if (o.fontPx < ctx.manifest.theme.captionMinFontPx)\n evidence.push({ stepRef: o.stepRef, note: `caption font ${o.fontPx}px below minimum` });\n if (!rectContains(out, o.box, 24)) evidence.push({ stepRef: o.stepRef, note: 'caption box outside safe bounds' });\n if (o.shrunk && !o.truncated) warned += 1;\n }\n if (count === 0) return { id: 'captions', status: 'skip', details: 'no captions' };\n if (evidence.length > 0)\n return { id: 'captions', status: 'fail', details: `${evidence.length} caption problem(s)`, evidence };\n return warned > 0\n ? { id: 'captions', status: 'warn', details: `${count} captions ok, ${warned} auto-shrunk to fit` }\n : { id: 'captions', status: 'pass', details: `${count} captions fit at full size` };\n}\n\n/** 6. Pacing sanity: steps get readable screen time; total duration sane. */\nexport async function checkPacing(ctx: VerifyContext): Promise<CheckResult> {\n const evidence: CheckEvidence[] = [];\n for (const step of ctx.manifest.steps) {\n const dur = step.outEnd - step.outStart;\n if (step.kind !== 'wait' && dur < 1200) {\n evidence.push({ stepRef: step.stepRef, note: `step on screen only ${(dur / 1000).toFixed(1)}s` });\n }\n }\n const total = ctx.manifest.durationMs;\n if (total < 3000) evidence.push({ note: `video too short (${(total / 1000).toFixed(1)}s)` });\n if (total > 15 * 60_000) evidence.push({ note: `video too long (${(total / 60000).toFixed(1)}min)` });\n return evidence.length > 0\n ? { id: 'pacing', status: 'fail', details: `${evidence.length} pacing violation(s)`, evidence }\n : { id: 'pacing', status: 'pass', details: `${ctx.manifest.steps.length} steps paced ≥1.2s, total ${(total / 1000).toFixed(1)}s` };\n}\n\n/** 7. The MP4 itself is intact and matches the manifest. */\n/** 9. Narration audio: when the video was narrated, the track must exist, be audible, and span the video. */\nexport async function checkAudio(ctx: VerifyContext): Promise<CheckResult> {\n if (!ctx.manifest.audio?.narrated) return { id: 'audio', status: 'skip', details: 'no narration' };\n const evidence: CheckEvidence[] = [];\n\n const probe = await runBinary(ffprobePath(), [\n '-v', 'error', '-select_streams', 'a', '-show_entries', 'stream=codec_name,duration', '-of', 'json', ctx.videoPath,\n ]);\n const stream = (JSON.parse(probe.stdout) as { streams?: { codec_name: string; duration?: string }[] }).streams?.[0];\n if (!stream) return { id: 'audio', status: 'fail', details: 'narration requested but the output has no audio stream' };\n\n // Non-silent? volumedetect reports mean/peak levels on stderr.\n const vd = await runBinary(ffmpegPath(), ['-hide_banner', '-nostats', '-i', ctx.videoPath, '-af', 'volumedetect', '-f', 'null', '-']);\n const mean = Number(/mean_volume:\\s*(-?[\\d.]+) dB/.exec(vd.stderr)?.[1] ?? '0');\n if (mean <= -70) evidence.push({ note: `narration track is effectively silent (mean ${mean} dB)` });\n\n const expectSec = ctx.manifest.durationMs / 1000;\n const aDur = Number(stream.duration ?? 0);\n if (aDur > 0 && Math.abs(aDur - expectSec) > Math.max(0.5, expectSec * 0.05))\n evidence.push({ note: `audio ${aDur.toFixed(1)}s vs video ${expectSec.toFixed(1)}s` });\n\n // A/V SYNC: every narration clip must be AUDIBLE inside its own window. Pacing predicts and\n // mux places independently — a drift bug would otherwise ship a voice describing the\n // previous screen with a passing verdict.\n const clips = ctx.manifest.audio.clips ?? [];\n let loudness: number | null = null;\n if (clips.length > 0) {\n const det = await runBinary(ffmpegPath(), [\n '-hide_banner', '-nostats',\n '-i', ctx.videoPath,\n '-af', 'silencedetect=noise=-40dB:d=0.35,ebur128',\n '-f', 'null', '-',\n ]);\n const silences: { start: number; end: number }[] = [];\n let open: number | null = null;\n for (const m of det.stderr.matchAll(/silence_(start|end): ([\\d.]+)/g)) {\n if (m[1] === 'start') open = parseFloat(m[2]!) * 1000;\n else if (open !== null) {\n silences.push({ start: open, end: parseFloat(m[2]!) * 1000 });\n open = null;\n }\n }\n if (open !== null) silences.push({ start: open, end: ctx.manifest.durationMs });\n for (const clip of clips) {\n const w0 = clip.tStart;\n const w1 = clip.tStart + clip.durMs;\n let silent = 0;\n for (const s of silences) {\n silent += Math.max(0, Math.min(w1, s.end) - Math.max(w0, s.start));\n }\n const voiced = (w1 - w0 - silent) / Math.max(1, w1 - w0);\n if (voiced < 0.45) {\n evidence.push({\n stepRef: clip.stepRef,\n t: clip.tStart,\n note: `narration line is mostly silent in its own window (${(voiced * 100).toFixed(0)}% voiced) — audio/video drift`,\n });\n }\n }\n // Loudness: the mix normalizes to I=-16 LUFS; a big miss means the loudnorm stage broke.\n // ebur128 prints PERIODIC \"I:\" readouts (starting at -70 before audio plays) and a final\n // summary — the integrated value is the LAST match, never the first.\n const lus = [...det.stderr.matchAll(/I:\\s+(-?[\\d.]+)\\s+LUFS/g)];\n const lu = lus[lus.length - 1];\n if (lu) {\n loudness = parseFloat(lu[1]!);\n if (loudness < -20 || loudness > -12) {\n evidence.push({ note: `integrated loudness ${loudness.toFixed(1)} LUFS is outside the -16±4 target` });\n }\n }\n }\n\n return evidence.length\n ? { id: 'audio', status: 'fail', details: `${evidence.length} narration problem(s)`, evidence }\n : {\n id: 'audio',\n status: 'pass',\n details: `${ctx.manifest.audio.lines} lines audible in their windows, ${stream.codec_name}${loudness !== null ? `, ${loudness.toFixed(1)} LUFS` : `, mean ${mean.toFixed(0)} dB`}`,\n };\n}\n\nexport async function checkEncode(ctx: VerifyContext): Promise<CheckResult> {\n let info;\n try {\n info = await probeVideo(ctx.videoPath);\n } catch (e) {\n return { id: 'encode', status: 'fail', details: `unreadable video: ${(e as Error).message}` };\n }\n const problems: string[] = [];\n if (info.codec !== 'h264') problems.push(`codec ${info.codec}`);\n if (info.width !== ctx.manifest.profile.width || info.height !== ctx.manifest.profile.height)\n problems.push(`resolution ${info.width}x${info.height}`);\n const expectSec = ctx.manifest.durationMs / 1000;\n if (Math.abs(info.durationSec - expectSec) > Math.max(0.5, expectSec * 0.03))\n problems.push(`duration ${info.durationSec.toFixed(1)}s vs planned ${expectSec.toFixed(1)}s`);\n if (Math.abs(info.fps - ctx.manifest.profile.fps) > 0.5) problems.push(`fps ${info.fps.toFixed(2)}`);\n return problems.length > 0\n ? { id: 'encode', status: 'fail', details: problems.join('; ') }\n : {\n id: 'encode',\n status: 'pass',\n details: `h264 ${info.width}x${info.height} @ ${info.fps.toFixed(0)}fps, ${info.durationSec.toFixed(1)}s`,\n };\n}\n\n/** 8. Masking held: masked regions are covered in footage, secrets absent from the log. */\nexport async function checkMasks(ctx: VerifyContext): Promise<CheckResult> {\n const evidence: CheckEvidence[] = [];\n const frameScale = ctx.bundle.manifest.frameW / ctx.manifest.viewport.w;\n\n // A mask region can be legitimately occluded by later UI (a dialog opening over a banner),\n // which raises its variance without exposing the sensitive pixels. So group samples by\n // position and require that each masked element reads as covered in its BEST sample —\n // if masking failed entirely, no sample of that element would ever be uniform.\n const buckets = new Map<string, { rect: { x: number; y: number; w: number; h: number }; minSd: number; t: number }>();\n const blurKeys = new Set<string>();\n for (const sample of ctx.bundle.maskSamples) {\n for (const rect of sample.rects) {\n const posKey = `${Math.round(rect.x / 24)}:${Math.round(rect.y / 24)}:${Math.round(rect.w / 24)}:${Math.round(rect.h / 24)}`;\n if (rect.style === 'blur') {\n blurKeys.add(posKey);\n continue; // a blurred region has no reference to compare against; leave it to --vision\n }\n const inset = scaleRect(shrinkRect(rect, Math.min(6, rect.w / 8, rect.h / 8)), frameScale);\n const region = await sourceRegionGray(ctx.bundle, sample.t + 60, inset, true);\n if (!region) continue;\n const sd = Math.sqrt(variance(region));\n const key = posKey;\n const prev = buckets.get(key);\n if (!prev || sd < prev.minSd) buckets.set(key, { rect, minSd: sd, t: sample.t });\n }\n }\n for (const b of buckets.values()) {\n if (b.minSd > 16) {\n evidence.push({ t: b.t, note: `solid mask at ${fmtRect(b.rect)} never verified opaque (best σ=${b.minSd.toFixed(1)})` });\n }\n }\n\n for (const e of actionEvents(ctx.bundle.events)) {\n if (e.masked && e.typedText && /[^•]/.test(e.typedText)) {\n evidence.push({ stepRef: `${e.sceneId}/${e.stepIndex}`, note: 'masked step leaked typed text into the event log' });\n }\n }\n\n if (ctx.bundle.maskSamples.length === 0) {\n return { id: 'masks', status: 'skip', details: 'no masking rules' };\n }\n if (evidence.length > 0) {\n return { id: 'masks', status: 'fail', details: `${evidence.length} mask violation(s)`, evidence };\n }\n const parts: string[] = [];\n if (buckets.size > 0) parts.push(`${buckets.size} solid region(s) verified opaque`);\n if (blurKeys.size > 0) parts.push(`${blurKeys.size} blurred region(s) applied`);\n return { id: 'masks', status: 'pass', details: `${parts.join(', ')}; log clean` };\n}\n\nfunction scaleRect(r: Rect, s: number): Rect {\n return { x: r.x * s, y: r.y * s, w: r.w * s, h: r.h * s };\n}\n\nfunction rectsOverlap(a: Rect, b: Rect): boolean {\n return a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y;\n}\n\nfunction shrinkRect(r: { x: number; y: number; w: number; h: number }, by: number): Rect {\n return { x: r.x + by, y: r.y + by, w: Math.max(1, r.w - 2 * by), h: Math.max(1, r.h - 2 * by) };\n}\n\nfunction fmtRect(r: Rect): string {\n return `[${r.x.toFixed(0)},${r.y.toFixed(0)} ${r.w.toFixed(0)}x${r.h.toFixed(0)}]`;\n}\n\n/**\n * 10. The DELIVERED pixels match the plan: for sampled steps, the region of the output MP4\n * where the subject should be must correlate with the same region of the source bundle frame.\n * Every geometry check above re-runs the planner's math — this one closes the plan-vs-pixels\n * hole: a renderer drawing the wrong frame or the wrong crop fails HERE.\n */\nexport async function checkOutputPixels(ctx: VerifyContext): Promise<CheckResult> {\n const p = plane(ctx);\n const content = stageContent(ctx.manifest.profile);\n const frameScale = ctx.bundle.manifest.frameW / ctx.manifest.viewport.w;\n const captions = ctx.manifest.overlays.filter((o) => o.kind === 'caption');\n\n const candidates = ctx.manifest.steps.filter((s) => !s.masked && (s.focusRectVp ?? s.targetRectVp));\n // Sample evenly, capped for speed — this decodes output frames.\n const stride = Math.max(1, Math.floor(candidates.length / 6));\n const sampled = candidates.filter((_, i) => i % stride === 0).slice(0, 6);\n if (sampled.length === 0) return { id: 'output-pixels', status: 'skip', details: 'no steps with targets' };\n\n const evidence: CheckEvidence[] = [];\n let checked = 0;\n for (const step of sampled) {\n const rect = step.focusRectVp ?? step.targetRectVp!;\n const tOut = Math.max(step.outBeat + 100, step.outEnd - 250);\n const cam = sampleCamera(ctx.manifest.camera, tOut);\n const proj = projectRect(rect, cam, p);\n const projFrame: Rect = { x: proj.x + content.x, y: proj.y + content.y, w: proj.w, h: proj.h };\n // A caption overlapping the region would pollute the comparison — skip those samples.\n if (captions.some((c) => tOut >= c.tStart && tOut <= c.tEnd && rectsOverlap(c.box, projFrame))) continue;\n const { srcAt } = sampleSource(ctx.manifest.segments, tOut);\n if (srcAt === null) continue;\n\n const outPng = await extractFrameAt(ctx.videoPath, tOut).catch(() => null);\n if (!outPng) continue;\n const outRegion = await regionGray48(outPng, projFrame);\n const srcFile = framePath(ctx.bundle, frameIndexForTime(ctx.bundle.frames, srcAt));\n const srcRegion = await regionGray48(srcFile, {\n x: rect.x * frameScale,\n y: rect.y * frameScale,\n w: rect.w * frameScale,\n h: rect.h * frameScale,\n });\n if (!outRegion || !srcRegion) continue;\n // A flat (zero-variance) region proves nothing: it can be a legitimately blank area, a mask\n // overlay, or a transition frame — and correlation against flatness is undefined. Only a\n // TEXTURED-vs-TEXTURED mismatch demonstrates a wrong frame or wrong crop.\n if (variance(outRegion) < 4 || variance(srcRegion) < 4) continue;\n checked += 1;\n const corr = normalizedCorrelation(outRegion, srcRegion);\n // Loose threshold: JPEG, rescaling, frame blending, and the spotlight all perturb pixels;\n // a WRONG frame or crop scores near zero, a right-but-processed one scores high.\n if (corr < 0.5) {\n evidence.push({\n stepRef: step.stepRef,\n t: tOut,\n note: `output region does not match the planned source region (correlation ${corr.toFixed(2)})`,\n });\n }\n }\n if (checked === 0) return { id: 'output-pixels', status: 'skip', details: 'no comparable samples (captions overlapped or frames unavailable)' };\n return evidence.length > 0\n ? { id: 'output-pixels', status: 'fail', details: `${evidence.length}/${checked} sampled regions diverge from the plan`, evidence }\n : { id: 'output-pixels', status: 'pass', details: `${checked} sampled output regions match their planned source` };\n}\n","import { writeFile } from 'node:fs/promises';\nimport { createCanvas, loadImage } from '@napi-rs/canvas';\nimport type { ComposeManifest } from '../compose/types.js';\nimport { extractFrameAt } from './media.js';\nimport { registerFonts } from '../theme/index.js';\nimport { roundRect } from '../compose/overlays/text.js';\n\nconst TILE_W = 480;\nconst LABEL_H = 42;\nconst GUTTER = 16;\nconst COLS = 3;\n\n/**\n * Contact sheet: one tile per step at its action beat (decoded from the OUTPUT video —\n * what viewers actually see) plus first and last frames, annotated with captions.\n */\nexport async function renderContactSheet(\n manifest: ComposeManifest,\n videoPath: string,\n outPath: string,\n): Promise<string> {\n registerFonts();\n const tileH = Math.round((TILE_W * manifest.profile.height) / manifest.profile.width);\n const captionsByStep = new Map(\n manifest.overlays.filter((o) => o.kind === 'caption').map((o) => [o.stepRef, o]),\n );\n\n const moments: { t: number; label: string }[] = [\n { t: manifest.overlays.find((o) => o.kind === 'titleCard')!.tEnd / 2, label: 'Title' },\n ];\n for (const step of manifest.steps) {\n const caption = captionsByStep.get(step.stepRef);\n // Sample the SETTLED hold, not the beat: at the beat (+150ms) a slow effect — a navigation,\n // a fetch, a modal — hasn't painted yet, so the tile labelled \"Click Save\" would show the\n // screen from *before* Save was clicked. Sampling near the end of the step's hold shows the\n // effect the caption claims. (Clamped to stay after the beat for very short steps.)\n const label = caption ? `${caption.ordinal}. ${caption.text}` : `${step.kind} (${step.stepRef})`;\n const settled = Math.max(step.outBeat + 150, step.outEnd - 400);\n moments.push({ t: Math.min(settled, step.outEnd - 50), label });\n }\n moments.push({ t: manifest.durationMs - 200, label: 'Final state' });\n\n const rows = Math.ceil(moments.length / COLS);\n const width = GUTTER + COLS * (TILE_W + GUTTER);\n const height = GUTTER + rows * (tileH + LABEL_H + GUTTER);\n const canvas = createCanvas(width, height);\n const ctx = canvas.getContext('2d');\n ctx.fillStyle = '#14161d';\n ctx.fillRect(0, 0, width, height);\n\n for (let i = 0; i < moments.length; i++) {\n const m = moments[i]!;\n const col = i % COLS;\n const row = Math.floor(i / COLS);\n const x = GUTTER + col * (TILE_W + GUTTER);\n const y = GUTTER + row * (tileH + LABEL_H + GUTTER);\n try {\n const png = await extractFrameAt(videoPath, m.t);\n const img = await loadImage(png);\n ctx.drawImage(img, x, y, TILE_W, tileH);\n } catch {\n ctx.fillStyle = '#3a2030';\n ctx.fillRect(x, y, TILE_W, tileH);\n ctx.fillStyle = '#ffffff';\n ctx.font = '16px Inter Medium';\n ctx.textAlign = 'center';\n ctx.fillText('frame unavailable', x + TILE_W / 2, y + tileH / 2);\n }\n // Label bar\n ctx.fillStyle = '#1e222c';\n roundRect(ctx, x, y + tileH + 4, TILE_W, LABEL_H - 8, 6);\n ctx.fill();\n ctx.fillStyle = 'rgba(255,255,255,0.92)';\n ctx.font = '15px Inter Medium';\n ctx.textAlign = 'left';\n ctx.textBaseline = 'middle';\n ctx.fillText(truncate(m.label, 58), x + 12, y + tileH + 4 + (LABEL_H - 8) / 2 + 1);\n ctx.fillStyle = 'rgba(255,255,255,0.45)';\n ctx.font = '13px Inter';\n ctx.textAlign = 'right';\n ctx.fillText(`${(m.t / 1000).toFixed(1)}s`, x + TILE_W - 12, y + tileH + 4 + (LABEL_H - 8) / 2 + 1);\n }\n\n await writeFile(outPath, await canvas.encode('png'));\n return outPath;\n}\n\nfunction truncate(s: string, n: number): string {\n return s.length <= n ? s : s.slice(0, n - 1) + '…';\n}\n","import { readFile } from 'node:fs/promises';\nimport type { CheckResult } from './types.js';\nimport type { ComposeManifest } from '../compose/types.js';\nimport { log } from '../shared/log.js';\n\nconst DEFAULT_MODEL = process.env.PLAYHEAD_VISION_MODEL ?? 'claude-opus-5';\n\nexport interface VisionReview {\n model: string;\n findings: { severity: string; note: string }[];\n}\n\n/**\n * Optional AI review: sends the contact sheet to Claude for a judgment call the\n * deterministic checks can't make (\"does this read as a coherent, professional\n * walkthrough?\"). Advisory only — findings become warn-level check entries.\n */\nexport async function visionReview(\n contactSheetPath: string,\n manifest: ComposeManifest,\n): Promise<{ check: CheckResult; review: VisionReview | null }> {\n if (!process.env.ANTHROPIC_API_KEY) {\n return {\n check: { id: 'vision-review', status: 'skip', details: 'ANTHROPIC_API_KEY not set' },\n review: null,\n };\n }\n try {\n const { default: Anthropic } = await import('@anthropic-ai/sdk');\n const client = new Anthropic();\n const png = await readFile(contactSheetPath);\n const captions = manifest.overlays\n .filter((o) => o.kind === 'caption')\n .map((o) => `${o.ordinal}. ${o.text}`)\n .join('\\n');\n\n const response = await client.messages.create({\n model: DEFAULT_MODEL,\n max_tokens: 1200,\n messages: [\n {\n role: 'user',\n content: [\n {\n type: 'image',\n source: { type: 'base64', media_type: 'image/png', data: png.toString('base64') },\n },\n {\n type: 'text',\n text: [\n 'This is a contact sheet of key moments from an automatically produced product walkthrough video.',\n 'Each tile shows the output frame at one step, labeled with its instruction caption. The steps are:',\n captions,\n '',\n 'Review it as a demanding video editor. Report only real problems a viewer would notice:',\n 'illegible or clipped UI, captions that do not match what is on screen, awkward framing,',\n 'visual glitches, or anything unprofessional. Ignore the tile borders and labels themselves.',\n 'Respond with strict JSON: {\"findings\": [{\"severity\": \"warn\", \"note\": \"...\"}]} —',\n 'an empty findings array if the video looks publishable.',\n ].join('\\n'),\n },\n ],\n },\n ],\n });\n const text = response.content\n .map((b) => (b.type === 'text' ? b.text : ''))\n .join('');\n const parsed = extractJson(text);\n const findings = Array.isArray(parsed?.findings)\n ? parsed.findings\n .filter((f): f is { severity?: string; note?: string } => !!f && typeof f === 'object')\n .map((f) => ({ severity: String(f.severity ?? 'warn'), note: String(f.note ?? '') }))\n : [];\n const review: VisionReview = { model: DEFAULT_MODEL, findings };\n return {\n check: {\n id: 'vision-review',\n status: findings.length > 0 ? 'warn' : 'pass',\n details:\n findings.length > 0\n ? `${findings.length} advisory finding(s) from ${DEFAULT_MODEL}`\n : `no issues flagged by ${DEFAULT_MODEL}`,\n ...(findings.length > 0 ? { evidence: findings.map((f) => ({ note: f.note })) } : {}),\n },\n review,\n };\n } catch (e) {\n log.warn(`vision review failed: ${(e as Error).message}`);\n return {\n check: { id: 'vision-review', status: 'skip', details: `vision review errored: ${(e as Error).message}` },\n review: null,\n };\n }\n}\n\nfunction extractJson(text: string): { findings?: unknown[] } | null {\n const start = text.indexOf('{');\n const end = text.lastIndexOf('}');\n if (start === -1 || end <= start) return null;\n try {\n return JSON.parse(text.slice(start, end + 1)) as { findings?: unknown[] };\n } catch {\n return null;\n }\n}\n","import { createHmac } from 'node:crypto';\nimport type { Verdict } from './types.js';\n\n/**\n * The canonical signable payload: everything that makes the verdict a CLAIM (result, artifact\n * hashes, provenance, per-check outcomes), in a fixed key order. Paths are excluded — moving\n * files doesn't change what was proven.\n */\nexport function signablePayload(v: Omit<Verdict, 'signature'>): string {\n return JSON.stringify({\n schema: v.schema,\n verdict: v.verdict,\n videoSha256: v.video.sha256,\n bundleHashes: { events: v.bundleHashes.events, framesIndex: v.bundleHashes.framesIndex },\n provenance: {\n playheadVersion: v.provenance.playheadVersion,\n specHash: v.provenance.specHash,\n appUrl: v.provenance.appUrl,\n capturedAt: v.provenance.capturedAt,\n verifiedAt: v.provenance.verifiedAt,\n checkSuiteVersion: v.provenance.checkSuiteVersion,\n host: v.provenance.host,\n partial: v.provenance.partial ?? false,\n },\n checks: v.checks.map((c) => ({ id: c.id, status: c.status })),\n });\n}\n\n/** HMAC-SHA256 signature over the canonical payload; null when no key is configured. */\nexport function signVerdict(v: Omit<Verdict, 'signature'>, key = process.env.PLAYHEAD_SIGNING_KEY): string | null {\n if (!key) return null;\n return createHmac('sha256', key).update(signablePayload(v)).digest('hex');\n}\n\n/** JUnit XML: one testsuite per verdict, one testcase per check — the shape every CI ingests. */\nexport function toJUnit(v: Verdict, suiteName = 'playhead'): string {\n const failures = v.checks.filter((c) => c.status === 'fail').length;\n const skipped = v.checks.filter((c) => c.status === 'skip').length;\n const esc = (s: string) =>\n s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"');\n const cases = v.checks\n .map((c) => {\n const body =\n c.status === 'fail'\n ? `\\n <failure message=\"${esc(c.details)}\">${esc(\n (c.evidence ?? []).map((e) => `${e.stepRef ?? ''}${e.t !== undefined ? ` @${(e.t / 1000).toFixed(1)}s` : ''} — ${e.note}`).join('\\n'),\n )}</failure>\\n `\n : c.status === 'skip'\n ? `\\n <skipped message=\"${esc(c.details)}\"/>\\n `\n : '';\n return ` <testcase classname=\"${esc(suiteName)}\" name=\"${esc(c.id)}\">${body}</testcase>`;\n })\n .join('\\n');\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<testsuite name=\"${esc(suiteName)}\" tests=\"${v.checks.length}\" failures=\"${failures}\" skipped=\"${skipped}\">\n${cases}\n</testsuite>\n`;\n}\n","import { join } from 'node:path';\nimport { mkdir, writeFile, readFile } from 'node:fs/promises';\nimport type { BundleData } from '../bundle/types.js';\nimport type { ComposeManifest } from '../compose/types.js';\nimport type { CheckResult, Verdict, VerifyContext } from './types.js';\nimport {\n checkActionEffect,\n checkAudio,\n checkCaptions,\n checkCursorOnTarget,\n checkEncode,\n checkFrozenBlank,\n checkMasks,\n checkOutputPixels,\n checkPacing,\n checkTargetInFrame,\n} from './checks.js';\nimport { renderContactSheet } from './contact-sheet.js';\nimport { visionReview } from './vision.js';\nimport { sha256File } from '../bundle/hash.js';\nimport { signVerdict } from './report.js';\nimport { PLAYHEAD_VERSION } from '../shared/version.js';\nimport { log } from '../shared/log.js';\nimport { platform, arch } from 'node:os';\nimport pc from 'picocolors';\n\n/** Bumped whenever a check is added or its semantics change — part of provenance. */\nexport const CHECK_SUITE_VERSION = 'playhead/checks@2';\n\nexport interface VerifyOptions {\n outDir: string;\n vision?: boolean;\n}\n\nexport async function verify(\n bundle: BundleData,\n manifest: ComposeManifest,\n videoPath: string,\n opts: VerifyOptions,\n): Promise<Verdict> {\n const verifyDir = join(opts.outDir, 'verify');\n await mkdir(verifyDir, { recursive: true });\n const ctx: VerifyContext = { bundle, manifest, videoPath, outDir: verifyDir };\n\n log.info('verifying output');\n const checks: CheckResult[] = [];\n const suite = [\n checkEncode, // fail fast on a broken file before decoding frames from it\n checkTargetInFrame,\n checkCursorOnTarget,\n checkActionEffect,\n checkOutputPixels, // the delivered MP4, not the plan\n checkFrozenBlank,\n checkCaptions,\n checkPacing,\n checkMasks,\n checkAudio,\n ];\n for (const check of suite) {\n const result = await check(ctx);\n checks.push(result);\n report(result);\n }\n\n const contactSheet = join(verifyDir, 'contact-sheet.png');\n await renderContactSheet(manifest, videoPath, contactSheet);\n log.ok(`contact sheet → ${contactSheet}`);\n\n let vision: Verdict['vision'] = null;\n if (opts.vision) {\n const { check, review } = await visionReview(contactSheet, manifest);\n checks.push(check);\n report(check);\n vision = review;\n }\n\n const failed = checks.some((c) => c.status === 'fail');\n const unsigned: Omit<Verdict, 'signature'> = {\n schema: 'playhead/verdict@2',\n verdict: failed ? 'not-publishable' : 'publishable',\n video: { path: videoPath, sha256: manifest.videoSha256 ?? (await sha256File(videoPath)) },\n bundleHashes: manifest.bundleHashes,\n provenance: {\n playheadVersion: PLAYHEAD_VERSION,\n specHash: bundle.manifest.specHash,\n appUrl: bundle.manifest.appUrl,\n capturedAt: bundle.manifest.createdAtIso,\n verifiedAt: new Date().toISOString(),\n checkSuiteVersion: CHECK_SUITE_VERSION,\n host: `${platform()}-${arch()}`,\n ...(bundle.manifest.partial ? { partial: true } : {}),\n ...(bundle.manifest.failure ? { failure: bundle.manifest.failure } : {}),\n },\n checks,\n contactSheet,\n vision,\n };\n const verdict: Verdict = { ...unsigned, signature: signVerdict(unsigned) };\n if (!verdict.signature) log.debug('verdict unsigned — set PLAYHEAD_SIGNING_KEY to sign');\n await writeFile(join(verifyDir, 'verdict.json'), JSON.stringify(verdict, null, 2));\n\n if (failed) log.error(`verdict: NOT PUBLISHABLE`);\n else log.ok(`verdict: publishable`);\n return verdict;\n}\n\n/** Re-load a compose manifest from disk (for `playhead verify <bundle> <mp4>`). */\nexport async function loadComposeManifest(path: string): Promise<ComposeManifest> {\n const manifest = JSON.parse(await readFile(path, 'utf8')) as ComposeManifest;\n if (manifest.schema !== 'playhead/compose@1') {\n throw new Error(`Unsupported compose manifest schema in ${path}`);\n }\n return manifest;\n}\n\nfunction report(c: CheckResult): void {\n const label =\n c.status === 'pass'\n ? pc.green('pass')\n : c.status === 'fail'\n ? pc.red('FAIL')\n : c.status === 'warn'\n ? pc.yellow('warn')\n : pc.dim('skip');\n console.error(` ${label} ${c.id}: ${c.details}`);\n for (const e of c.evidence ?? []) {\n console.error(pc.dim(` ${e.stepRef ?? ''}${e.t !== undefined ? ` @${(e.t / 1000).toFixed(1)}s` : ''} — ${e.note}`));\n }\n}\n","import { join } from 'node:path';\nimport { mkdir } from 'node:fs/promises';\nimport type { Spec } from './spec/schema.js';\nimport { capture } from './capture/executor.js';\nimport { openBundle } from './bundle/reader.js';\nimport { compose } from './compose/index.js';\nimport { verify } from './verify/runner.js';\nimport type { Verdict } from './verify/types.js';\nimport { concatVideos } from './shared/ffmpeg.js';\nimport { log } from './shared/log.js';\n\nexport interface BeforeAfterResult {\n videoPath: string;\n before: { videoPath: string; verdict: Verdict };\n after: { videoPath: string; verdict: Verdict };\n verdict: 'publishable' | 'not-publishable';\n}\n\n/**\n * Render a before/after comparison: run the SAME spec against two versions of the app\n * (app.compareUrl = before, app.url = after), compose each with the full pipeline, verify both,\n * and stitch them into one titled clip. Publishable only if both halves are.\n */\nexport async function renderBeforeAfter(\n spec: Spec,\n opts: { outDir: string; headless?: boolean; vision?: boolean },\n): Promise<BeforeAfterResult> {\n if (!spec.app.compareUrl) {\n throw new Error('before-after needs app.compareUrl (the \"before\" version) alongside app.url (the \"after\")');\n }\n const side = async (label: string, url: string): Promise<{ videoPath: string; verdict: Verdict }> => {\n const dir = join(opts.outDir, label);\n await mkdir(dir, { recursive: true });\n const sideSpec: Spec = {\n ...spec,\n title: `${spec.title} — ${cap(label)}`,\n app: { ...spec.app, url },\n };\n log.info(`before/after: capturing \"${label}\" (${url})`);\n const { bundleDir } = await capture(sideSpec, { outDir: dir, headless: opts.headless ?? true });\n const bundle = await openBundle(bundleDir);\n const composed = await compose(bundle, sideSpec, { outDir: dir });\n const verdict = await verify(bundle, composed.manifest, composed.videoPath, { outDir: dir, vision: opts.vision ?? false });\n return { videoPath: composed.videoPath, verdict };\n };\n\n // \"Before\" plays first, then \"After\".\n const before = await side('before', spec.app.compareUrl);\n const after = await side('after', spec.app.url);\n\n const videoPath = join(opts.outDir, 'before-after.mp4');\n await concatVideos([before.videoPath, after.videoPath], videoPath);\n\n const publishable = before.verdict.verdict === 'publishable' && after.verdict.verdict === 'publishable';\n log.info(`before/after → ${videoPath}`);\n if (publishable) log.ok('verdict: publishable (both halves)');\n else log.error('verdict: NOT PUBLISHABLE (a half failed)');\n\n return { videoPath, before, after, verdict: publishable ? 'publishable' : 'not-publishable' };\n}\n\nfunction cap(s: string): string {\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n","import { readFile, stat } from 'node:fs/promises';\nimport { join, basename } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport type { Verdict } from '../verify/types.js';\nimport { log } from '../shared/log.js';\nimport { InfraError } from '../shared/exit.js';\n\n/**\n * Jira integration: attach a render's evidence to an EXISTING issue and post a verdict comment.\n * v1 deliberately never creates issues — \"attach proof to the ticket a human opened\" is the\n * tester workflow; auto-filing is ticket noise.\n *\n * Auth is an API token in env vars — Playhead never handles a password:\n * JIRA_BASE_URL e.g. https://yourorg.atlassian.net\n * JIRA_EMAIL the token owner's email\n * JIRA_API_TOKEN from id.atlassian.com/manage-profile/security/api-tokens\n */\n\nexport interface JiraConfig {\n baseUrl: string;\n email: string;\n token: string;\n}\n\nexport function jiraConfigFromEnv(): JiraConfig {\n const baseUrl = process.env.JIRA_BASE_URL;\n const email = process.env.JIRA_EMAIL;\n const token = process.env.JIRA_API_TOKEN;\n if (!baseUrl || !email || !token) {\n throw new InfraError(\n 'Jira is not configured — set JIRA_BASE_URL (https://yourorg.atlassian.net), JIRA_EMAIL, and JIRA_API_TOKEN (create one at id.atlassian.com → Security → API tokens)',\n );\n }\n return { baseUrl: baseUrl.replace(/\\/+$/, ''), email, token };\n}\n\nfunction authHeader(cfg: JiraConfig): string {\n return `Basic ${Buffer.from(`${cfg.email}:${cfg.token}`).toString('base64')}`;\n}\n\nasync function jiraFetch(cfg: JiraConfig, path: string, init?: RequestInit): Promise<Response> {\n const res = await fetch(`${cfg.baseUrl}${path}`, {\n ...init,\n headers: {\n Authorization: authHeader(cfg),\n Accept: 'application/json',\n ...(init?.headers ?? {}),\n },\n });\n return res;\n}\n\n/** Fail fast with a readable message when the issue doesn't exist or auth is wrong. */\nexport async function assertIssue(cfg: JiraConfig, issueKey: string): Promise<{ key: string; summary: string }> {\n const res = await jiraFetch(cfg, `/rest/api/3/issue/${encodeURIComponent(issueKey)}?fields=summary`);\n if (res.status === 404) throw new InfraError(`Jira issue ${issueKey} not found on ${cfg.baseUrl}`);\n if (res.status === 401 || res.status === 403) {\n throw new InfraError(`Jira rejected the credentials for ${cfg.email} (HTTP ${res.status}) — check JIRA_API_TOKEN`);\n }\n if (!res.ok) throw new InfraError(`Jira issue lookup failed: HTTP ${res.status}`);\n const body = (await res.json()) as { key: string; fields?: { summary?: string } };\n return { key: body.key, summary: body.fields?.summary ?? '' };\n}\n\n/** Attach one file. Jira requires multipart/form-data with the XSRF check disabled. */\nexport async function attachFile(cfg: JiraConfig, issueKey: string, filePath: string): Promise<string> {\n const data = await readFile(filePath);\n const form = new FormData();\n form.append('file', new Blob([new Uint8Array(data)]), basename(filePath));\n const res = await jiraFetch(cfg, `/rest/api/3/issue/${encodeURIComponent(issueKey)}/attachments`, {\n method: 'POST',\n headers: { 'X-Atlassian-Token': 'no-check' },\n body: form,\n });\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw new InfraError(`attaching ${basename(filePath)} failed: HTTP ${res.status} ${text.slice(0, 200)}`);\n }\n return basename(filePath);\n}\n\n/** Post an ADF comment. */\nexport async function addComment(cfg: JiraConfig, issueKey: string, adfBody: unknown): Promise<void> {\n const res = await jiraFetch(cfg, `/rest/api/3/issue/${encodeURIComponent(issueKey)}/comment`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ body: adfBody }),\n });\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw new InfraError(`posting the comment failed: HTTP ${res.status} ${text.slice(0, 200)}`);\n }\n}\n\n// ---------- evidence discovery + comment building ----------\n\nexport interface RenderEvidence {\n /** 'publishable' | 'not-publishable' | 'flow-failed' */\n outcome: string;\n verdict?: Verdict;\n failure?: { stepRef: string; message: string; url?: string };\n files: string[];\n}\n\n/** Find whatever evidence a render (successful or failed) left in an out dir. */\nexport async function collectEvidence(outDir: string): Promise<RenderEvidence> {\n const candidates = [\n join(outDir, 'out.mp4'),\n join(outDir, 'failure.mp4'),\n join(outDir, 'verify', 'verdict.json'),\n join(outDir, 'verify', 'contact-sheet.png'),\n join(outDir, 'junit.xml'),\n join(outDir, 'capture', 'failure.json'),\n join(outDir, 'capture', 'console.json'),\n ];\n const files: string[] = [];\n for (const f of candidates) {\n if (!existsSync(f)) continue;\n const s = await stat(f);\n if (s.size > 95 * 1024 * 1024) {\n log.warn(`skipping ${basename(f)} (${(s.size / 1e6).toFixed(0)}MB — larger than Jira's usual attachment ceiling)`);\n continue;\n }\n files.push(f);\n }\n if (files.length === 0) {\n throw new InfraError(`no Playhead artifacts found under ${outDir} — expected out.mp4/failure.mp4, verify/verdict.json, …`);\n }\n\n let verdict: Verdict | undefined;\n const verdictPath = join(outDir, 'verify', 'verdict.json');\n if (existsSync(verdictPath)) verdict = JSON.parse(await readFile(verdictPath, 'utf8')) as Verdict;\n\n let failure: RenderEvidence['failure'];\n const failurePath = join(outDir, 'capture', 'failure.json');\n if (existsSync(failurePath)) failure = JSON.parse(await readFile(failurePath, 'utf8')) as RenderEvidence['failure'];\n\n const outcome = failure ? 'flow-failed' : (verdict?.verdict ?? 'unknown');\n return { outcome, ...(verdict ? { verdict } : {}), ...(failure ? { failure } : {}), files };\n}\n\n/** The verdict comment, as an Atlassian Document Format doc. Kept to simple, universal nodes. */\nexport function buildComment(ev: RenderEvidence, attached: string[]): unknown {\n const text = (t: string, strong = false) => ({\n type: 'text',\n text: t,\n ...(strong ? { marks: [{ type: 'strong' }] } : {}),\n });\n const para = (...content: unknown[]) => ({ type: 'paragraph', content });\n const bullet = (items: string[]) => ({\n type: 'bulletList',\n content: items.map((i) => ({ type: 'listItem', content: [para(text(i))] })),\n });\n\n const content: unknown[] = [];\n if (ev.outcome === 'flow-failed' && ev.failure) {\n content.push(para(text('Playhead: flow FAILED', true), text(` at step ${ev.failure.stepRef}`)));\n content.push(para(text(ev.failure.message.split('\\n')[0] ?? '')));\n if (ev.failure.url) content.push(para(text(`Page at failure: ${ev.failure.url}`)));\n content.push(para(text('The failure clip shows the flow up to the break — watch failure.mp4.')));\n } else if (ev.verdict) {\n const v = ev.verdict;\n content.push(\n para(text(`Playhead verdict: ${v.verdict === 'publishable' ? 'PUBLISHABLE ✅' : 'NOT PUBLISHABLE ❌'}`, true)),\n );\n content.push(\n bullet(\n v.checks.map((c) => `${c.status === 'pass' ? '✓' : c.status === 'fail' ? '✗' : '·'} ${c.id}: ${c.details}`),\n ),\n );\n content.push(\n para(\n text(\n `Provenance: playhead ${v.provenance.playheadVersion} · spec ${v.provenance.specHash.slice(0, 12)}… · captured ${v.provenance.capturedAt} · ${v.provenance.host}${v.signature ? ' · signed' : ' · unsigned'}`,\n ),\n ),\n );\n } else {\n content.push(para(text('Playhead render evidence attached.', true)));\n }\n content.push(para(text(`Attached: ${attached.join(', ')}`)));\n return { type: 'doc', version: 1, content };\n}\n\n/** The whole flow: validate the issue, attach every artifact, post the verdict comment. */\nexport async function reportToJira(issueKey: string, outDir: string, cfg = jiraConfigFromEnv()): Promise<void> {\n const issue = await assertIssue(cfg, issueKey);\n log.info(`reporting to ${issue.key} (“${issue.summary}”) on ${cfg.baseUrl}`);\n const ev = await collectEvidence(outDir);\n const attached: string[] = [];\n for (const f of ev.files) {\n attached.push(await attachFile(cfg, issueKey, f));\n log.ok(`attached ${basename(f)}`);\n }\n await addComment(cfg, issueKey, buildComment(ev, attached));\n log.ok(`verdict comment posted to ${issue.key}`);\n}\n","import type { RawInteractable } from '../capture/driver-api.js';\n\nexport type CatalogKind = 'button' | 'link' | 'input' | 'select' | 'toggle' | 'heading' | 'other';\n\nexport interface CatalogEntry {\n kind: CatalogKind;\n role: string | null;\n name: string | null;\n /** The chosen, validated Playhead locator string. */\n locator: string;\n /** Whether `locator` resolves to exactly one element. */\n unique: boolean;\n /** How likely the locator survives app changes: testid/role+name high, label medium, text low. */\n stability: 'high' | 'medium' | 'low';\n /** Landmark region: nav | header | sidebar | main | dialog | footer | page. */\n region: string;\n bbox: { x: number; y: number; w: number; h: number };\n visible: boolean;\n options?: string[];\n}\n\n/** Stability of a locator string by its engine — a maintenance signal for authors. */\nexport function stabilityOf(locatorRaw: string): 'high' | 'medium' | 'low' {\n const locator = locatorRaw.replace(/^(frame=[^>]+>>\\s*)+/, '').trim();\n if (locator.startsWith('testid=')) return 'high';\n if (locator.startsWith('role=')) return 'high';\n if (locator.startsWith('label=') || locator.startsWith('placeholder=')) return 'medium';\n return 'low'; // text=, css=\n}\n\nconst NAMED_ROLES = new Set(['button', 'link', 'tab', 'switch', 'menuitem', 'heading', 'checkbox', 'radio', 'option']);\nconst FIELD_ROLES = new Set(['textbox', 'searchbox', 'combobox', 'spinbutton']);\n\n/** Ordered locator candidates for an element, best (most resilient/readable) first. */\nexport function candidateLocators(el: RawInteractable): string[] {\n const out: string[] = [];\n const push = (s: string) => {\n if (s && !out.includes(s)) out.push(s);\n };\n const name = el.accessibleName;\n\n if (el.testId) push(`testid=${el.testId}`);\n // Form fields read best by their label.\n if ((FIELD_ROLES.has(el.role ?? '') || el.inputType === 'select') && el.label) push(`label=${quote(el.label)}`);\n if (el.role && name && NAMED_ROLES.has(el.role)) push(`role=${el.role}[name=${quote(name)}]`);\n if (el.label) push(`label=${quote(el.label)}`);\n if (el.placeholder) push(`placeholder=${quote(el.placeholder)}`);\n if (el.role && name && !NAMED_ROLES.has(el.role)) push(`role=${el.role}[name=${quote(name)}]`);\n if (name) push(`text=${quote(name)}`);\n // Elements inside an iframe are only addressable through it.\n if (el.framePrefix) return out.map((l) => `${el.framePrefix} >> ${l}`);\n return out;\n}\n\nexport function kindOf(el: RawInteractable): CatalogKind {\n if (el.inputType === 'select') return 'select';\n if (el.role === 'switch' || el.role === 'checkbox' || el.role === 'radio') return 'toggle';\n if (FIELD_ROLES.has(el.role ?? '')) return 'input';\n if (el.role === 'button') return 'button';\n if (el.role === 'link') return 'link';\n if (el.role === 'heading') return 'heading';\n return 'other';\n}\n\n/** Quote for an EXACT locator match; fall back to a regex when the text has awkward characters. */\nexport function quote(s: string): string {\n const clean = s.replace(/\\s+/g, ' ').trim();\n if (clean.includes('\"')) {\n return `/${escapeRegex(clean).replace(/\\//g, '\\\\/')}/`;\n }\n return `\"${clean}\"`;\n}\n\nfunction escapeRegex(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n","import type { Driver } from '../capture/driver-api.js';\nimport { PlaywrightDriver } from '../capture/playwright-driver.js';\nimport { parseLocator } from '../spec/locators.js';\nimport { candidateLocators, kindOf, stabilityOf, type CatalogEntry } from './catalog.js';\n\nexport interface PageSnapshot {\n url: string;\n title: string;\n aria: string;\n catalog: CatalogEntry[];\n}\n\n/**\n * Explore the app in its current state: read every interactable, choose the first locator\n * candidate that resolves uniquely against the live DOM, and return a grounded catalog.\n * This is what makes authored specs correct by construction — locators are validated here,\n * not discovered to be wrong at render time.\n */\nexport async function snapshotPage(driver: Driver): Promise<PageSnapshot> {\n const [raw, aria, title] = await Promise.all([\n driver.collectInteractables(),\n driver.ariaSnapshot(),\n driver.currentTitle(),\n ]);\n\n const catalog: CatalogEntry[] = [];\n for (const el of raw) {\n if (!el.visible) continue;\n if (el.bbox.w < 2 || el.bbox.h < 2) continue;\n const candidates = candidateLocators(el);\n if (candidates.length === 0) continue;\n\n let chosen: string | null = null;\n let unique = false;\n let ambiguous: string | null = null;\n for (const cand of candidates) {\n const count = await driver.countMatches(parseLocator(cand)).catch(() => 0);\n if (count === 1) {\n chosen = cand;\n unique = true;\n break;\n }\n // Candidates are ordered BEST-first, so the fallback must keep the FIRST ambiguous\n // match, not overwrite with each worse one.\n if (count > 1 && ambiguous === null) ambiguous = cand;\n }\n chosen = chosen ?? ambiguous ?? candidates[0]!;\n catalog.push({\n kind: kindOf(el),\n role: el.role,\n name: el.accessibleName,\n locator: chosen,\n unique,\n stability: stabilityOf(chosen),\n region: el.region ?? 'page',\n bbox: el.bbox,\n visible: el.visible,\n ...(el.options ? { options: el.options } : {}),\n });\n }\n // De-duplicate by locator, keeping the first (top-most) occurrence.\n const byLocator = new Map<string, CatalogEntry>();\n for (const e of catalog) if (!byLocator.has(e.locator)) byLocator.set(e.locator, e);\n\n return { url: driver.currentUrl(), title, aria, catalog: [...byLocator.values()] };\n}\n\n/** One-shot exploration: launch, navigate, snapshot, close. Used by `playhead explore`. */\nexport async function exploreUrl(\n url: string,\n opts?: {\n viewport?: { w: number; h: number };\n headless?: boolean;\n driver?: Driver;\n /** storageState JSON (from `playhead login`) so authed screens are exploreable. */\n storageStatePath?: string;\n },\n): Promise<PageSnapshot> {\n const driver = opts?.driver ?? new PlaywrightDriver();\n const owned = !opts?.driver;\n if (owned) {\n await driver.launch({\n viewport: opts?.viewport ?? { w: 1280, h: 720 },\n dpr: 2,\n headless: opts?.headless ?? true,\n ...(opts?.storageStatePath ? { storageStatePath: opts.storageStatePath } : {}),\n });\n }\n try {\n await driver.goto(url);\n await driver.settle({ idleMs: 300, capMs: 5000 });\n return await snapshotPage(driver);\n } finally {\n if (owned) await driver.close();\n }\n}\n\n/** Render a catalog as a compact, human/agent-readable table: grouped by page REGION (where\n * the element lives), then by kind, with a stability signal per locator. */\nexport function formatCatalog(snap: PageSnapshot): string {\n const lines: string[] = [];\n lines.push(`# ${snap.title || '(untitled)'} — ${snap.url}`);\n lines.push(`# ${snap.catalog.length} interactable elements (stability: ● high · ◐ medium · ○ low)\\n`);\n const regions: Record<string, CatalogEntry[]> = {};\n for (const e of snap.catalog) (regions[e.region] ??= []).push(e);\n const stabMark = { high: '●', medium: '◐', low: '○' } as const;\n for (const region of ['dialog', 'main', 'nav', 'sidebar', 'header', 'footer', 'page']) {\n const items = regions[region];\n if (!items || items.length === 0) continue;\n lines.push(`## ${region}`);\n const groups: Record<string, CatalogEntry[]> = {};\n for (const e of items) (groups[e.kind] ??= []).push(e);\n for (const kind of ['heading', 'link', 'button', 'input', 'select', 'toggle', 'other']) {\n const kindItems = groups[kind];\n if (!kindItems || kindItems.length === 0) continue;\n for (const e of kindItems) {\n const flag = e.unique ? '' : ' ⚠ ambiguous';\n const opts = e.options ? ` options: [${e.options.join(', ')}]` : '';\n lines.push(` ${stabMark[e.stability]} [${kind}] ${e.locator}${flag}${opts}`);\n }\n }\n lines.push('');\n }\n return lines.join('\\n');\n}\n","import type { Spec } from '../spec/schema.js';\nimport { flattenSteps, resolveViewport } from '../spec/schema.js';\nimport { parseLocator } from '../spec/locators.js';\nimport type { Driver } from '../capture/driver-api.js';\nimport { PlaywrightDriver } from '../capture/playwright-driver.js';\nimport { editDistance } from '../spec/schema.js';\nimport { snapshotPage } from './explore.js';\nimport { rectCenter } from '../shared/geometry.js';\n\nexport interface ValidateIssue {\n stepRef: string;\n step: string;\n locator: string;\n severity: 'error' | 'warn';\n message: string;\n suggestions: string[];\n}\n\nexport interface ValidateResult {\n ok: boolean;\n checked: number;\n issues: ValidateIssue[];\n}\n\n/**\n * Live preflight: walk the spec against the running app in ONE browser pass, checking every\n * locator (the action target, the focus hint, waits, expects) *before* any frame is ever\n * captured — and report ALL problems at once with nearest-candidate suggestions from the\n * current screen. Steps are executed fast (no cursor choreography, no filming) so later\n * locators are checked against the state they'll actually meet.\n *\n * This collapses \"one bad locator = one full capture run\" into a single cheap pass.\n */\nexport async function validateLive(\n spec: Spec,\n opts?: { headless?: boolean; driver?: Driver },\n): Promise<ValidateResult> {\n const driver = opts?.driver ?? new PlaywrightDriver();\n const owned = !opts?.driver;\n const issues: ValidateIssue[] = [];\n let checked = 0;\n let stateDiverged = false;\n\n if (owned) {\n await driver.launch({\n viewport: resolveViewport(spec),\n dpr: 1,\n headless: opts?.headless ?? true,\n ...(spec.app.storageState ? { storageStatePath: spec.app.storageState } : {}),\n });\n }\n try {\n await driver.goto(spec.app.url);\n await driver.settle({ idleMs: 300, capMs: 5000 });\n\n for (const a of flattenSteps(spec)) {\n const stepRef = `${a.sceneId}/${a.stepIndex}`;\n const step = a.step;\n const push = async (locator: string, severity: 'error' | 'warn', message: string) => {\n issues.push({\n stepRef,\n step: step.action,\n locator,\n severity,\n message: stateDiverged ? `${message} (after an earlier failure — state may have diverged)` : message,\n suggestions: severity === 'error' ? await suggestFor(driver, locator) : [],\n });\n };\n\n // 1) Check every locator the step names.\n const locators: { value: string; kind: 'target' | 'focus' | 'wait' }[] = [];\n if ('target' in step && step.target) locators.push({ value: step.target, kind: 'target' });\n if (step.action === 'wait' && step.for) locators.push({ value: step.for, kind: 'wait' });\n if (step.focus && step.focus !== 'target' && step.focus !== 'wide') {\n locators.push({ value: step.focus, kind: 'focus' });\n }\n for (const l of locators) {\n checked += 1;\n const count = await driver.countMatches(parseLocator(l.value)).catch(() => 0);\n if (count === 0 && l.kind === 'target') {\n await push(l.value, 'error', 'no matching element on the current screen');\n } else if (count === 0 && l.kind !== 'target') {\n // Focus/wait locators often name a PAYOFF that only exists after the action — not\n // an error before the action runs, but worth confirming after.\n await push(l.value, 'warn', `${l.kind} locator matches nothing yet (may appear after the action)`);\n } else if (count > 1 && !l.value.includes('>> nth=')) {\n await push(l.value, 'warn', `ambiguous: ${count} matches — add '>> nth=N' to pick one`);\n }\n }\n\n // 2) Execute the step fast so downstream locators meet real state.\n try {\n await fastExecute(driver, step);\n } catch (e) {\n if ('target' in step && step.target) {\n const already = issues.some((i) => i.stepRef === stepRef && i.severity === 'error');\n if (!already) await push(step.target ?? '(none)', 'error', `step failed to execute: ${firstLine((e as Error).message)}`);\n }\n stateDiverged = true;\n }\n\n // 3) Post-action: a focus locator that matched nothing must exist NOW.\n const focus = step.focus;\n if (focus && focus !== 'target' && focus !== 'wide') {\n const loc = parseLocator(focus);\n let n = 0;\n for (let i = 0; i < 8 && n === 0; i++) {\n n = await driver.countMatches(loc).catch(() => 0);\n if (n === 0) await sleep(250);\n }\n if (n === 0) await push(focus, 'error', 'focus locator never appeared after the action');\n // Drop the provisional pre-action warn once the payoff shows up.\n if (n > 0) {\n const idx = issues.findIndex((i) => i.stepRef === stepRef && i.locator === focus && i.severity === 'warn');\n if (idx >= 0) issues.splice(idx, 1);\n }\n }\n }\n } finally {\n if (owned) await driver.close();\n }\n return { ok: !issues.some((i) => i.severity === 'error'), checked, issues };\n}\n\n/** Execute a step with no filming, no cursor choreography, minimal waits. */\nasync function fastExecute(driver: Driver, step: import('../spec/schema.js').Step): Promise<void> {\n const FAST_TIMEOUT = step.timeout ?? 8000;\n switch (step.action) {\n case 'goto':\n await driver.goto(step.url);\n break;\n case 'click':\n case 'dblclick': {\n const t = await driver.resolveTarget(parseLocator(step.target), FAST_TIMEOUT);\n await driver.clickAt(rectCenter(t.bbox), { double: step.action === 'dblclick' });\n break;\n }\n case 'hover': {\n const t = await driver.resolveTarget(parseLocator(step.target), FAST_TIMEOUT);\n await driver.moveCursor(rectCenter(t.bbox), 40);\n break;\n }\n case 'type': {\n const t = await driver.resolveTarget(parseLocator(step.target), FAST_TIMEOUT);\n await driver.clickAt(rectCenter(t.bbox));\n await driver.typeText(step.text, 0);\n break;\n }\n case 'press':\n await driver.press(step.keys);\n break;\n case 'select':\n await driver.selectOption(parseLocator(step.target), step.value);\n break;\n case 'scroll':\n if (step.target) await driver.scrollIntoView(parseLocator(step.target));\n else if (step.by) await driver.scrollBy(step.by);\n await driver.waitForScrollSettle(1500);\n break;\n case 'expect':\n await driver.expectState(\n parseLocator(step.target),\n {\n ...(step.visible !== undefined ? { visible: step.visible } : {}),\n ...(step.text !== undefined ? { text: step.text } : {}),\n ...(step.count !== undefined ? { count: step.count } : {}),\n },\n FAST_TIMEOUT,\n );\n break;\n case 'wait':\n if (step.for) {\n await driver.expectState(parseLocator(step.for), { visible: step.state !== 'hidden' }, step.timeout ?? 8000);\n }\n // blind `ms` sleeps are skipped in fast mode\n break;\n }\n await driver.settle({ idleMs: 200, capMs: 2500 });\n}\n\n/** Nearest catalog candidates on the CURRENT screen, by name distance to the broken locator. */\nasync function suggestFor(driver: Driver, locator: string): Promise<string[]> {\n try {\n const snap = await snapshotPage(driver);\n const wanted = displayText(locator).toLowerCase();\n return snap.catalog\n .map((e) => ({ e, d: editDistance(wanted, (e.name ?? displayText(e.locator)).toLowerCase().slice(0, 40)) }))\n .sort((a, b) => a.d - b.d)\n .slice(0, 3)\n .map(({ e }) => `${e.locator}${e.unique ? '' : ' (ambiguous)'}`);\n } catch {\n return [];\n }\n}\n\nfunction displayText(locator: string): string {\n const m = /name=[\"']?([^\\]\"']+)/.exec(locator) ?? /=[\"']?([^\\]\"']+)/.exec(locator);\n return (m?.[1] ?? locator).slice(0, 40);\n}\n\nfunction firstLine(s: string): string {\n return (s.split('\\n')[0] ?? '').slice(0, 160);\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n\n/** Human-readable report for the CLI. */\nexport function formatValidateResult(res: ValidateResult): string {\n const lines: string[] = [];\n for (const i of res.issues) {\n const mark = i.severity === 'error' ? '✗' : '⚠';\n lines.push(`${mark} ${i.stepRef} ${i.step} ${i.locator}`);\n lines.push(` ${i.message}`);\n for (const s of i.suggestions) lines.push(` did you mean: ${s}`);\n }\n const errors = res.issues.filter((i) => i.severity === 'error').length;\n const warns = res.issues.length - errors;\n lines.push('');\n lines.push(\n res.ok\n ? `✓ ${res.checked} locator(s) validated against the live app${warns ? ` (${warns} warning(s))` : ''}`\n : `✗ ${errors} error(s), ${warns} warning(s) across ${res.checked} locator check(s)`,\n );\n return lines.join('\\n');\n}\n","import { stringify } from 'yaml';\n\n/** An action the author loop decided on and (usually) executed to advance the app. */\nexport interface AuthoredStep {\n action: 'goto' | 'click' | 'dblclick' | 'hover' | 'type' | 'press' | 'select' | 'scroll' | 'expect';\n scene: string;\n locator?: string;\n text?: string;\n value?: string;\n keys?: string;\n url?: string;\n visible?: boolean;\n caption?: string;\n mask?: boolean;\n}\n\nexport interface AuthoredSpec {\n title: string;\n url: string;\n viewport: { w: number; h: number };\n kind: string;\n steps: AuthoredStep[];\n}\n\n/** Turn one authored step into the spec's shorthand YAML form. */\nfunction toYamlStep(s: AuthoredStep): Record<string, unknown> {\n const extra: Record<string, unknown> = {};\n if (s.caption) extra.caption = s.caption;\n switch (s.action) {\n case 'goto':\n return { goto: s.url, ...extra };\n case 'press':\n return { press: s.keys, ...extra };\n case 'click':\n case 'dblclick':\n case 'hover':\n return { [s.action]: s.locator, ...extra };\n case 'type':\n return { type: { target: s.locator, text: s.text, ...(s.mask ? { mask: true } : {}) }, ...extra };\n case 'select':\n return { select: { target: s.locator, value: s.value }, ...extra };\n case 'scroll':\n return { scroll: s.locator, ...extra };\n case 'expect':\n return { expect: { target: s.locator, ...(s.visible !== false ? { visible: true } : {}) }, ...extra };\n }\n}\n\nconst kebab = (s: string) =>\n s.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 40) || 'scene';\n\n/** Serialize an authored spec into clean, human-editable Playhead YAML, grouped into scenes. */\nexport function serializeSpec(spec: AuthoredSpec): string {\n const scenes: { id: string; title: string; steps: Record<string, unknown>[] }[] = [];\n const seenIds = new Set<string>();\n for (const step of spec.steps) {\n let scene = scenes[scenes.length - 1];\n if (!scene || scene.title !== step.scene) {\n let id = kebab(step.scene);\n let n = 2;\n while (seenIds.has(id)) id = `${kebab(step.scene)}-${n++}`;\n seenIds.add(id);\n scene = { id, title: step.scene, steps: [] };\n scenes.push(scene);\n }\n scene.steps.push(toYamlStep(step));\n }\n\n const doc = {\n playhead: 1,\n title: spec.title,\n app: { url: spec.url, viewport: `${spec.viewport.w}x${spec.viewport.h}` },\n output: { kind: spec.kind, pacing: 'normal' },\n scenes: scenes.map((s) => ({ id: s.id, title: s.title, steps: s.steps })),\n };\n return (\n '# Authored by `playhead author` — grounded in the live app, every locator validated.\\n' +\n '# Edit freely, then: playhead render this-file.yaml\\n\\n' +\n stringify(doc, { lineWidth: 0 })\n );\n}\n","import { writeFile } from 'node:fs/promises';\nimport { PlaywrightDriver } from '../capture/playwright-driver.js';\nimport type { Driver } from '../capture/driver-api.js';\nimport { parseLocator } from '../spec/locators.js';\nimport { rectCenter } from '../shared/geometry.js';\nimport { snapshotPage, type PageSnapshot } from './explore.js';\nimport { serializeSpec, type AuthoredSpec, type AuthoredStep } from './serialize.js';\nimport { log } from '../shared/log.js';\n\nexport interface StepDecision {\n done: boolean;\n reason?: string;\n scene: string;\n action?: AuthoredStep['action'];\n locator?: string;\n text?: string;\n value?: string;\n keys?: string;\n caption?: string;\n mask?: boolean;\n}\n\n/** Chooses the next step from the current screen. Default is Claude; injectable for tests/policies. */\nexport type Decider = (goal: string, snap: PageSnapshot, soFar: AuthoredStep[]) => Promise<StepDecision>;\n\nexport interface AuthorOptions {\n url: string;\n goal: string;\n outPath: string;\n title?: string;\n viewport: { w: number; h: number };\n maxSteps: number;\n headless: boolean;\n driver?: Driver;\n /** Override the step decider (defaults to the Claude-backed one). */\n decide?: Decider;\n}\n\nconst SETTLE = { idleMs: 300, capMs: 5000 };\n\nconst STEP_TOOL = {\n name: 'emit_step',\n description: 'Emit the single next step of the demo, or finish when the goal is fully shown.',\n input_schema: {\n type: 'object',\n properties: {\n done: { type: 'boolean', description: 'true when the goal has been fully demonstrated' },\n reason: { type: 'string', description: 'one short sentence explaining this choice' },\n scene: { type: 'string', description: 'short human title for the current section, e.g. \"Create a deal\"' },\n action: { type: 'string', enum: ['click', 'dblclick', 'hover', 'type', 'select', 'press', 'scroll', 'expect'] },\n locator: { type: 'string', description: 'a locator copied EXACTLY from the catalog' },\n text: { type: 'string', description: 'text to type (for action=type)' },\n value: { type: 'string', description: 'option to choose (for action=select)' },\n keys: { type: 'string', description: 'key to press, e.g. Enter (for action=press)' },\n caption: { type: 'string', description: 'optional custom caption; omit to auto-write from the label' },\n mask: { type: 'boolean', description: 'true if typing a secret that must be hidden' },\n },\n required: ['done', 'scene'],\n },\n} as const;\n\nconst SYSTEM = `You author Playhead demo specs by walking a REAL running web app toward a goal.\nEach turn you are shown the current screen's catalog of addressable elements — each line is a\nvalidated locator you may use VERBATIM. Rules:\n- Choose the SINGLE next step that best advances the goal, like a person performing the flow once.\n- Use ONLY locators that appear in the current catalog; never invent one. If what you need is not\n visible yet, pick the step that navigates toward it (a nav link, a button that opens a dialog).\n- After you act, the app changes and you will see the next screen's catalog.\n- Prefer role/label locators. Use 'expect' to assert an important result appeared (e.g. a success\n toast or a new row) — it produces no click, just proof.\n- Group steps into scenes with a short 'scene' title; keep the same title across related steps.\n- Set done=true only when the goal is fully shown, then stop.\nKeep the demo tight and legible — a good walkthrough is 6-20 meaningful steps.`;\n\n/** Agent-author a grounded, validated spec by walking the app toward the goal. Needs ANTHROPIC_API_KEY. */\nexport async function authorSpec(opts: AuthorOptions): Promise<{ specPath: string; steps: AuthoredStep[] }> {\n const decide = opts.decide ?? claudeDecider();\n\n const driver = opts.driver ?? new PlaywrightDriver();\n const owned = !opts.driver;\n const steps: AuthoredStep[] = [];\n\n log.info(`authoring \"${opts.goal}\" against ${opts.url}`);\n if (owned) await driver.launch({ viewport: opts.viewport, dpr: 2, headless: opts.headless });\n try {\n await driver.goto(opts.url);\n await driver.settle(SETTLE);\n\n for (let i = 0; i < opts.maxSteps; i++) {\n const snap = await snapshotPage(driver);\n const decision = await decide(opts.goal, snap, steps);\n if (decision.done || !decision.action) {\n log.ok(`agent finished: ${decision.reason ?? 'goal shown'}`);\n break;\n }\n const step = toAuthoredStep(decision);\n log.step(`${steps.length + 1}. ${describe(step)}${decision.reason ? ` — ${decision.reason}` : ''}`);\n try {\n await perform(driver, step);\n await driver.settle(SETTLE);\n steps.push(step);\n } catch (e) {\n log.warn(`step failed (${(e as Error).message}); asking the agent to adjust`);\n // Leave it out of the spec; the next turn re-snapshots the unchanged screen and retries.\n }\n }\n\n if (steps.length === 0) throw new Error('authoring produced no steps — the goal may not be reachable from this URL');\n\n const spec: AuthoredSpec = {\n title: opts.title ?? capitalize(opts.goal),\n url: opts.url,\n viewport: opts.viewport,\n kind: 'walkthrough',\n steps,\n };\n await writeFile(opts.outPath, serializeSpec(spec));\n log.ok(`wrote ${steps.length}-step spec → ${opts.outPath}`);\n log.info(`next: playhead render ${opts.outPath}`);\n return { specPath: opts.outPath, steps };\n } finally {\n if (owned) await driver.close();\n }\n}\n\n/** The default decider: ask Claude for the next step, forcing a structured tool call. */\nexport function claudeDecider(): Decider {\n if (!process.env.ANTHROPIC_API_KEY) {\n throw new Error('playhead author needs ANTHROPIC_API_KEY (the agent that drafts the spec). Set it and retry.');\n }\n const model = process.env.PLAYHEAD_AUTHOR_MODEL ?? 'claude-opus-5';\n let clientPromise: Promise<import('@anthropic-ai/sdk').default> | null = null;\n const getClient = async () => {\n if (!clientPromise) clientPromise = import('@anthropic-ai/sdk').then((m) => new m.default());\n return clientPromise;\n };\n\n return async (goal, snap, soFar) => {\n const client = await getClient();\n const catalog = snap.catalog\n .map((e) => ` ${e.locator}${e.options ? ` (options: ${e.options.join(' | ')})` : ''}${e.unique ? '' : ' [ambiguous]'}`)\n .join('\\n');\n const history = soFar.length ? soFar.map((s, i) => ` ${i + 1}. ${describe(s)}`).join('\\n') : ' (none yet)';\n const userMsg = [\n `GOAL: ${goal}`,\n ``,\n `CURRENT SCREEN: ${snap.title} — ${snap.url}`,\n `ADDRESSABLE ELEMENTS (use these locators verbatim):`,\n catalog || ' (no interactable elements found)',\n ``,\n `STEPS SO FAR:`,\n history,\n ``,\n `Emit the next step (or done=true if the goal is fully shown).`,\n ].join('\\n');\n\n const res = await client.messages.create({\n model,\n max_tokens: 700,\n system: SYSTEM,\n tools: [STEP_TOOL as never],\n tool_choice: { type: 'tool', name: 'emit_step' },\n messages: [{ role: 'user', content: userMsg }],\n });\n const block = res.content.find((b) => b.type === 'tool_use');\n if (!block || block.type !== 'tool_use') return { done: true, scene: 'end', reason: 'no step returned' };\n return block.input as StepDecision;\n };\n}\n\nfunction toAuthoredStep(d: StepDecision): AuthoredStep {\n const s: AuthoredStep = { action: d.action!, scene: d.scene || 'Walkthrough' };\n if (d.locator) s.locator = d.locator;\n if (d.text !== undefined) s.text = d.text;\n if (d.value !== undefined) s.value = d.value;\n if (d.keys !== undefined) s.keys = d.keys;\n if (d.caption) s.caption = d.caption;\n if (d.mask) s.mask = true;\n if (d.action === 'expect') s.visible = true;\n return s;\n}\n\n/** Execute an authored step to advance the live app (no capture; just drives the flow forward). */\nasync function perform(driver: Driver, step: AuthoredStep): Promise<void> {\n const timeout = 10_000;\n switch (step.action) {\n case 'expect':\n // An assertion only — confirm it resolves so the authored spec won't fail at render time.\n if (step.locator) await driver.resolveTarget(parseLocator(step.locator), timeout);\n return;\n case 'press':\n if (step.keys) await driver.press(step.keys);\n return;\n case 'scroll':\n if (step.locator) {\n await driver.scrollIntoView(parseLocator(step.locator));\n await driver.waitForScrollSettle(2500);\n }\n return;\n case 'select':\n if (step.locator && step.value) await driver.selectOption(parseLocator(step.locator), step.value);\n return;\n }\n if (!step.locator) return;\n const loc = parseLocator(step.locator);\n const target = await driver.resolveTarget(loc, timeout);\n const center = rectCenter(target.bbox);\n if (step.action === 'hover') {\n await driver.moveCursor(center, 400);\n return;\n }\n await driver.moveCursor(center, 400);\n await driver.clickAt(center, step.action === 'dblclick' ? { double: true } : undefined);\n if (step.action === 'type' && step.text) {\n await driver.typeText(step.text, 40);\n }\n}\n\nfunction describe(s: AuthoredStep): string {\n switch (s.action) {\n case 'type':\n return `type \"${s.mask ? '••••' : s.text}\" into ${s.locator}`;\n case 'select':\n return `select \"${s.value}\" in ${s.locator}`;\n case 'press':\n return `press ${s.keys}`;\n case 'expect':\n return `expect ${s.locator}`;\n default:\n return `${s.action} ${s.locator}`;\n }\n}\n\nfunction capitalize(s: string): string {\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n","import { mkdtemp, writeFile, mkdir, readFile } from 'node:fs/promises';\nimport { PLAYHEAD_VERSION } from '../shared/version.js';\nimport { tmpdir } from 'node:os';\nimport { join, resolve, isAbsolute } from 'node:path';\nimport { z } from 'zod';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { exploreUrl, formatCatalog } from '../authoring/explore.js';\nimport { authorSpec } from '../authoring/author.js';\nimport { parseSpec, loadSpec } from '../spec/parse.js';\nimport { capture } from '../capture/executor.js';\nimport { openBundle } from '../bundle/reader.js';\nimport { compose } from '../compose/index.js';\nimport { verify } from '../verify/runner.js';\nimport type { Verdict } from '../verify/types.js';\n\n/**\n * Playhead as a set of tools any coding agent can call. The agent grounds its spec with\n * `playhead_explore`, renders with `playhead_render`, and iterates on the returned verdict —\n * the whole author → verify → fix loop, inside the agent's own workspace.\n */\nexport function buildServer(): McpServer {\n const server = new McpServer(\n { name: 'playhead', version: PLAYHEAD_VERSION },\n {\n instructions:\n 'Playhead turns a spec + a live web app into a verified walkthrough video. ' +\n 'To make a demo: (1) call playhead_explore on the running app to get validated locators, ' +\n '(2) write a spec (or call playhead_author), (3) call playhead_render and read the verdict — ' +\n 'fix the spec if it is not publishable. Every locator you use MUST come from an explore catalog. ' +\n 'To attach the result to a ticket, call playhead_jira with the same outDir after rendering.',\n },\n );\n\n const dims = z.string().regex(/^\\d+x\\d+$/).default('1280x720');\n const parseDims = (s: string) => {\n const [w, h] = s.split('x').map(Number);\n return { w: w!, h: h! };\n };\n\n server.registerTool(\n 'playhead_explore',\n {\n title: 'Explore a live app',\n description:\n 'Launch the running web app and return a grounded catalog of addressable elements — each ' +\n 'line is a Playhead locator validated to resolve uniquely against the real DOM. Use these ' +\n 'locators verbatim when writing a spec. Only shows the CURRENT screen; call again after a ' +\n 'navigation to see later screens.',\n inputSchema: {\n url: z.string().describe('the running app URL, e.g. http://localhost:3000'),\n viewport: dims.describe('viewport WxH'),\n },\n },\n async ({ url, viewport }) => {\n const snap = await exploreUrl(url, { viewport: parseDims(viewport), headless: true });\n return { content: [{ type: 'text', text: formatCatalog(snap) }] };\n },\n );\n\n server.registerTool(\n 'playhead_author',\n {\n title: 'Auto-author a spec',\n description:\n 'Walk the app toward a natural-language goal and write a grounded, validated spec file. ' +\n 'Needs ANTHROPIC_API_KEY. Returns the spec path and its YAML. Prefer this for a quick draft; ' +\n 'use explore + your own spec-writing for fine control.',\n inputSchema: {\n url: z.string(),\n goal: z.string().describe('what flow to demo, e.g. \"create a new deal for Globex\"'),\n outPath: z.string().default('playhead.yaml').describe('where to write the spec'),\n viewport: dims,\n },\n },\n async ({ url, goal, outPath, viewport }) => {\n const path = isAbsolute(outPath) ? outPath : resolve(outPath);\n const { steps } = await authorSpec({\n url,\n goal,\n outPath: path,\n viewport: parseDims(viewport),\n maxSteps: 40,\n headless: true,\n });\n const yaml = await readFile(path, 'utf8');\n return { content: [{ type: 'text', text: `Wrote ${steps.length}-step spec to ${path}\\n\\n${yaml}` }] };\n },\n );\n\n server.registerTool(\n 'playhead_validate_spec',\n {\n title: 'Validate a spec',\n description:\n 'Parse a spec (path or inline YAML) and report schema errors. With live: true, ALSO walk ' +\n 'the spec against the running app in one fast browser pass — every locator is checked in ' +\n 'order with nearest-candidate suggestions, before any frame is captured. Run this before ' +\n 'playhead_render: it turns N capture-time failures into one cheap preflight.',\n inputSchema: {\n specPath: z.string().optional().describe('path to a spec file'),\n spec: z.string().optional().describe('inline spec YAML (use instead of specPath)'),\n live: z.boolean().default(false).describe('dry-run every locator against the live app'),\n },\n },\n async ({ specPath, spec, live }) => {\n try {\n const yaml = spec ?? (await readFile(resolve(specPath!), 'utf8'));\n const parsed = parseSpec(yaml);\n const steps = parsed.scenes.reduce((n, s) => n + s.steps.length, 0);\n const header = `✓ Valid spec \"${parsed.title}\" — ${parsed.scenes.length} scenes, ${steps} steps.`;\n if (!live) return { content: [{ type: 'text', text: header }] };\n const { validateLive, formatValidateResult } = await import('../authoring/validate.js');\n const res = await validateLive(parsed);\n return {\n content: [{ type: 'text', text: `${header}\\n\\n${formatValidateResult(res)}` }],\n ...(res.ok ? {} : { isError: true }),\n };\n } catch (e) {\n return { content: [{ type: 'text', text: `✗ ${(e as Error).message}` }], isError: true };\n }\n },\n );\n\n server.registerTool(\n 'playhead_render',\n {\n title: 'Render a verified video',\n description:\n 'Capture the live app per the spec, compose the walkthrough video, and verify it. Returns the ' +\n 'publishable/not-publishable verdict with per-check reasons, plus paths to the MP4, the ' +\n 'compose manifest, and the contact sheet. If not publishable, fix the spec and render again.',\n inputSchema: {\n specPath: z.string().optional(),\n spec: z.string().optional().describe('inline spec YAML (use instead of specPath)'),\n outDir: z.string().default('playhead-out').describe('where to write artifacts'),\n vision: z.boolean().default(false).describe('also run the Claude vision review (needs ANTHROPIC_API_KEY)'),\n },\n },\n async ({ specPath, spec, outDir, vision }) => {\n const out = resolve(outDir);\n await mkdir(out, { recursive: true });\n let parsedSpec;\n if (spec) {\n const tmp = await mkdtemp(join(tmpdir(), 'playhead-spec-'));\n const p = join(tmp, 'spec.yaml');\n await writeFile(p, spec);\n parsedSpec = parseSpec(spec);\n } else {\n parsedSpec = await loadSpec(resolve(specPath!));\n }\n const { bundleDir } = await capture(parsedSpec, { outDir: out, headless: true });\n const bundle = await openBundle(bundleDir);\n const composed = await compose(bundle, parsedSpec, { outDir: out });\n const verdict = await verify(bundle, composed.manifest, composed.videoPath, { outDir: out, vision });\n return {\n content: [{ type: 'text', text: renderVerdictReport(verdict, composed.videoPath, composed.manifestPath) }],\n isError: verdict.verdict !== 'publishable',\n };\n },\n );\n\n server.registerTool(\n 'playhead_jira',\n {\n title: 'Post render evidence to Jira',\n description:\n 'Attach a render\\'s evidence to an EXISTING Jira issue and post a verdict comment — the ' +\n 'video (or failure clip), verdict.json, contact sheet, JUnit, and console log, plus a ' +\n 'comment carrying the per-check table (or the failing step + error for a flow failure). ' +\n 'Run this AFTER playhead_render, pointing outDir at the same directory. Reports to ' +\n 'existing issues only (never creates them). Requires JIRA_BASE_URL, JIRA_EMAIL, and ' +\n 'JIRA_API_TOKEN in the environment — Playhead never handles a password.',\n inputSchema: {\n issueKey: z.string().describe('the existing Jira issue key, e.g. PROJ-123'),\n outDir: z.string().default('playhead-out').describe('the render output directory (same one passed to playhead_render)'),\n },\n },\n async ({ issueKey, outDir }) => {\n try {\n const { reportToJira, collectEvidence } = await import('../integrations/jira.js');\n const out = resolve(outDir);\n await reportToJira(issueKey, out);\n const ev = await collectEvidence(out);\n return {\n content: [\n {\n type: 'text',\n text: `Posted to ${issueKey}: attached ${ev.files.length} artifact(s) [${ev.files\n .map((f) => f.split('/').pop())\n .join(', ')}] and a ${ev.outcome} verdict comment.`,\n },\n ],\n };\n } catch (e) {\n return { content: [{ type: 'text', text: `✗ Jira report failed: ${(e as Error).message}` }], isError: true };\n }\n },\n );\n\n return server;\n}\n\nfunction renderVerdictReport(verdict: Verdict, videoPath: string, manifestPath: string): string {\n const lines: string[] = [];\n lines.push(`VERDICT: ${verdict.verdict.toUpperCase()}`);\n lines.push('');\n for (const c of verdict.checks) {\n const mark = c.status === 'pass' ? '✓' : c.status === 'fail' ? '✗' : c.status === 'warn' ? '⚠' : '·';\n lines.push(`${mark} ${c.id}: ${c.details}`);\n for (const e of c.evidence ?? []) {\n lines.push(` ${e.stepRef ?? ''}${e.t !== undefined ? ` @${(e.t / 1000).toFixed(1)}s` : ''} — ${e.note}`);\n }\n }\n lines.push('');\n lines.push(`video: ${videoPath}`);\n lines.push(`manifest: ${manifestPath}`);\n lines.push(`contact sheet:${verdict.contactSheet}`);\n if (verdict.verdict !== 'publishable') lines.push('\\nFix the flagged steps in the spec and render again.');\n return lines.join('\\n');\n}\n\n/** Start the stdio MCP server (called by `playhead mcp`). */\nexport async function startMcpServer(): Promise<void> {\n const server = buildServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n","#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { mkdir, writeFile, access } from 'node:fs/promises';\nimport { join, resolve } from 'node:path';\nimport pc from 'picocolors';\nimport { loadSpec } from '../spec/parse.js';\nimport { capture } from '../capture/executor.js';\nimport { openBundle } from '../bundle/reader.js';\nimport { compose } from '../compose/index.js';\nimport { verify, loadComposeManifest } from '../verify/runner.js';\nimport { resolveTheme } from '../theme/index.js';\nimport { ffmpegPath, ffprobePath, runBinary } from '../shared/ffmpeg.js';\nimport { log, setVerbose } from '../shared/log.js';\nimport { sha256Json, sha256File } from '../bundle/hash.js';\nimport { EXIT, exitCodeFor, FlowError } from '../shared/exit.js';\nimport { PLAYHEAD_VERSION } from '../shared/version.js';\nimport type { Verdict } from '../verify/types.js';\n\n/** Emit machine-readable outputs for a verdict (stdout JSON and/or a JUnit file). */\nasync function emitReports(verdict: Verdict, opts: { json?: boolean; junit?: string }): Promise<void> {\n if (opts.json) console.log(JSON.stringify(verdict, null, 2));\n if (opts.junit) {\n const { toJUnit } = await import('../verify/report.js');\n await writeFile(resolve(opts.junit), toJUnit(verdict));\n log.ok(`junit → ${opts.junit}`);\n }\n}\n\nconst program = new Command();\n\nprogram\n .name('playhead')\n .description('Product video as a build artifact: spec + live product → finished, verified video.')\n .version(PLAYHEAD_VERSION)\n .option('--verbose', 'debug logging');\n\nprogram.hook('preAction', (cmd) => {\n if (cmd.opts().verbose) setVerbose(true);\n});\n\nprogram\n .command('render')\n .description('capture → compose → verify; exit 0 only if every spec is publishable')\n .argument('<specs...>', 'spec YAML path(s) — multiple files render as a pool')\n .option('-o, --out <dir>', 'output directory (per-spec subdirs when rendering several)', 'out')\n .option('-w, --workers <n>', 'concurrent renders when given multiple specs', '2')\n .option('--vision', 'run the Claude vision review (needs ANTHROPIC_API_KEY)')\n .option('--json', 'print the verdict JSON to stdout (human logs go to stderr)')\n .option('--junit <path>', 'write a JUnit XML report (one testcase per check)')\n .option('--jira <issueKey>', 'report the outcome (evidence + verdict comment) to an existing Jira issue — success OR flow failure')\n .option('--headed', 'show the browser while capturing')\n .action(async (specPaths: string[], opts: { out: string; workers: string; vision?: boolean; json?: boolean; junit?: string; jira?: string; headed?: boolean }) => {\n // Exit contract: 0 pass · 1 flow failure (app broke; failure clip rendered) ·\n // 2 quality failure (not publishable) · 3 infra · 4 usage.\n const renderOne = async (specPath: string, outDir: string): Promise<number> => {\n const spec = await loadSpec(specPath);\n await mkdir(outDir, { recursive: true });\n if (spec.output.kind === 'before-after') {\n const { renderBeforeAfter } = await import('../beforeafter.js');\n const res = await renderBeforeAfter(spec, { outDir, headless: !opts.headed, vision: opts.vision ?? false });\n return res.verdict === 'publishable' ? EXIT.OK : EXIT.QUALITY;\n }\n try {\n const { bundleDir } = await capture(spec, { outDir, headless: !opts.headed });\n const bundle = await openBundle(bundleDir);\n const result = await compose(bundle, spec, { outDir });\n const verdict = await verify(bundle, result.manifest, result.videoPath, {\n outDir,\n vision: opts.vision ?? false,\n });\n await emitReports(verdict, opts);\n return verdict.verdict === 'publishable' ? EXIT.OK : EXIT.QUALITY;\n } catch (e) {\n if (e instanceof FlowError) {\n log.error(e.message);\n // FAILURE CLIP: compose the partial bundle so the red run hands the developer\n // something to WATCH — the flow up to the break, ending on a card naming it.\n try {\n const bundle = await openBundle(join(outDir, 'capture'));\n const result = await compose(bundle, spec, { outDir, fileName: 'failure.mp4' });\n log.ok(`failure clip → ${result.videoPath}`);\n } catch (clipErr) {\n log.warn(`could not render the failure clip: ${(clipErr as Error).message}`);\n }\n return EXIT.FLOW;\n }\n throw e;\n }\n };\n\n if (specPaths.length === 1) {\n const code = await renderOne(specPaths[0]!, resolve(opts.out));\n // Report the outcome to Jira EITHER way: a publishable video is fix-verification\n // evidence; a flow failure attaches the failure clip + diagnosis. Reporting problems\n // never mask the render's own exit code.\n if (opts.jira && code !== EXIT.INFRA && code !== EXIT.USAGE) {\n try {\n const { reportToJira } = await import('../integrations/jira.js');\n await reportToJira(opts.jira, resolve(opts.out));\n } catch (e) {\n log.error(`jira report failed: ${(e as Error).message}`);\n }\n }\n process.exitCode = code;\n return;\n }\n if (opts.jira) log.warn('--jira is single-spec only for now — skipping the report for this multi-spec pool');\n\n // Pool: N specs render concurrently, each in its own browser and its own out subdir.\n // Compose/verify are pure functions of the bundle, so parallelism is safe by construction.\n const workers = Math.max(1, Number(opts.workers) || 2);\n log.info(`rendering ${specPaths.length} specs with ${workers} worker(s)`);\n const queue = [...specPaths];\n const results = new Map<string, number | Error>();\n await Promise.all(\n Array.from({ length: Math.min(workers, queue.length) }, async () => {\n for (let path = queue.shift(); path !== undefined; path = queue.shift()) {\n const name = path.replace(/\\.ya?ml$/, '').split('/').pop()!;\n try {\n results.set(path, await renderOne(path, resolve(join(opts.out, name))));\n } catch (e) {\n results.set(path, e as Error);\n }\n }\n }),\n );\n // Pool exit code: the worst individual outcome.\n let worst = EXIT.OK as number;\n for (const [path, res] of results) {\n if (res === EXIT.OK) log.ok(path);\n else if (typeof res === 'number') {\n worst = Math.max(worst, res);\n log.error(`${path} — ${res === EXIT.FLOW ? 'flow failed' : 'not publishable'}`);\n } else {\n worst = Math.max(worst, exitCodeFor(res));\n log.error(`${path} — ${res.message.split('\\n')[0]}`);\n }\n }\n process.exitCode = worst;\n });\n\nprogram\n .command('capture')\n .description('capture a live app into a re-renderable bundle')\n .argument('<spec>', 'path to spec YAML')\n .option('-o, --out <dir>', 'output directory', 'out')\n .option('--from-scene <id>', 'fast-forward earlier steps (state only, unfilmed) and film from this scene — for iterating on one scene')\n .option('--headed', 'show the browser while capturing')\n .action(async (specPath: string, opts: { out: string; headed?: boolean; fromScene?: string }) => {\n const spec = await loadSpec(specPath);\n await mkdir(resolve(opts.out), { recursive: true });\n await capture(spec, { outDir: resolve(opts.out), headless: !opts.headed, ...(opts.fromScene ? { fromScene: opts.fromScene } : {}) });\n });\n\nprogram\n .command('compose')\n .description('re-render video from a capture bundle — no live app needed')\n .argument('<bundle>', 'path to a capture bundle directory')\n .option('-o, --out <dir>', 'output directory (default: bundle parent)')\n .option(\n '--spec <file>',\n 'compose with a LIVE spec file instead of the bundled snapshot — captions, narration, theme, audio, pacing all come from it, so text edits are a re-compose, never a re-capture',\n )\n .option('--expect-sha <hex>', 'assert the rendered MP4 hashes to this sha256 (determinism check: same bundle + spec → same video)')\n .action(async (bundleDir: string, opts: { out?: string; spec?: string; expectSha?: string }) => {\n const bundle = await openBundle(resolve(bundleDir));\n const spec = opts.spec\n ? await loadSpec(resolve(opts.spec))\n : JSON.parse(\n await (await import('node:fs/promises')).readFile(join(resolve(bundleDir), 'spec.resolved.json'), 'utf8'),\n );\n if (opts.spec && sha256Json(spec.scenes.map((s: { id: string }) => s.id)) !== sha256Json(\n (JSON.parse(await (await import('node:fs/promises')).readFile(join(resolve(bundleDir), 'spec.resolved.json'), 'utf8')) as { scenes: { id: string }[] }).scenes.map((s) => s.id),\n )) {\n log.warn('--spec scene ids differ from the captured spec — steps that moved will keep their captured footage positions');\n }\n const outDir = resolve(opts.out ?? join(resolve(bundleDir), '..'));\n await mkdir(outDir, { recursive: true });\n const result = await compose(bundle, spec, { outDir, theme: resolveTheme(spec) });\n if (opts.expectSha) {\n const got = result.manifest.videoSha256 ?? (await sha256File(result.videoPath));\n if (got !== opts.expectSha.toLowerCase()) {\n log.error(`determinism check failed: rendered ${got.slice(0, 16)}…, expected ${opts.expectSha.slice(0, 16)}…`);\n process.exitCode = EXIT.QUALITY;\n } else {\n log.ok(`determinism check: sha256 matches (${got.slice(0, 16)}…)`);\n }\n }\n });\n\nprogram\n .command('validate')\n .description('preflight a spec against the LIVE app: every locator checked in one pass, all failures reported with suggestions — before a single frame is captured')\n .argument('<spec>', 'path to spec YAML')\n .option('--headed', 'show the browser')\n .action(async (specPath: string, opts: { headed?: boolean }) => {\n const spec = await loadSpec(specPath);\n const { validateLive, formatValidateResult } = await import('../authoring/validate.js');\n log.info(`validating \"${spec.title}\" against ${spec.app.url}`);\n const res = await validateLive(spec, { headless: !opts.headed });\n console.log(formatValidateResult(res));\n process.exitCode = res.ok ? 0 : 1;\n });\n\nprogram\n .command('login')\n .description('open a headed browser for you to log in, then save the session for authed captures (app.storageState) — Playhead never sees credentials')\n .argument('<url>', 'the app login URL')\n .option('-o, --out <file>', 'where to save the storage state', 'playhead-session.json')\n .action(async (url: string, opts: { out: string }) => {\n const { PlaywrightDriver } = await import('../capture/playwright-driver.js');\n const driver = new PlaywrightDriver();\n await driver.launch({ viewport: { w: 1440, h: 900 }, dpr: 1, headless: false });\n await driver.goto(url);\n log.info('log in in the browser window, then press Enter here to save the session…');\n await new Promise<void>((res) => {\n process.stdin.resume();\n process.stdin.once('data', () => res());\n });\n await driver.saveStorageState(resolve(opts.out));\n await driver.close();\n process.stdin.pause();\n log.ok(`session saved → ${opts.out} (reference it from the spec: app.storageState: ${opts.out})`);\n });\n\nprogram\n .command('jira')\n .description('report render evidence to an EXISTING Jira issue: attach the video/failure clip, verdict, contact sheet, and console log, and post a verdict comment')\n .argument('<action>', 'only \"report\" for now')\n .argument('<issueKey>', 'e.g. PROJ-123')\n .option('-o, --out <dir>', 'the render output directory holding the artifacts', 'out')\n .action(async (action: string, issueKey: string, opts: { out: string }) => {\n if (action !== 'report') {\n log.error(`unknown jira action \"${action}\" — only \"report\" is supported`);\n process.exitCode = EXIT.USAGE;\n return;\n }\n const { reportToJira } = await import('../integrations/jira.js');\n await reportToJira(issueKey, resolve(opts.out));\n });\n\nprogram\n .command('verify')\n .description('run the verification suite against a rendered video')\n .argument('<bundle>', 'path to the capture bundle directory')\n .argument('<video>', 'path to the rendered MP4')\n .option('-m, --manifest <path>', 'compose manifest path (default: next to the video)')\n .option('--vision', 'run the Claude vision review')\n .option('--json', 'print the verdict JSON to stdout')\n .option('--junit <path>', 'write a JUnit XML report')\n .action(async (bundleDir: string, videoPath: string, opts: { manifest?: string; vision?: boolean; json?: boolean; junit?: string }) => {\n const bundle = await openBundle(resolve(bundleDir));\n const manifestPath = opts.manifest ?? join(resolve(videoPath), '..', 'compose-manifest.json');\n const manifest = await loadComposeManifest(manifestPath);\n const verdict = await verify(bundle, manifest, resolve(videoPath), {\n outDir: join(resolve(videoPath), '..'),\n vision: opts.vision ?? false,\n });\n await emitReports(verdict, opts);\n process.exitCode = verdict.verdict === 'publishable' ? EXIT.OK : EXIT.QUALITY;\n });\n\nprogram\n .command('attest')\n .description('re-verify a verdict.json: artifact hashes recomputed, signature checked (PLAYHEAD_SIGNING_KEY) — proves the verdict describes THESE files and was not edited')\n .argument('<verdict>', 'path to verdict.json (or the verify/ directory containing it)')\n .option('--bundle <dir>', 'also re-hash the capture bundle against the verdict')\n .action(async (verdictPath: string, opts: { bundle?: string }) => {\n const { readFile } = await import('node:fs/promises');\n const p = verdictPath.endsWith('.json') ? resolve(verdictPath) : join(resolve(verdictPath), 'verdict.json');\n const verdict = JSON.parse(await readFile(p, 'utf8')) as Verdict;\n let ok = true;\n\n const videoSha = await sha256File(verdict.video.path).catch(() => null);\n if (videoSha === verdict.video.sha256) log.ok(`video sha256 matches (${videoSha!.slice(0, 12)}…)`);\n else {\n ok = false;\n log.error(`video hash mismatch: verdict says ${verdict.video.sha256.slice(0, 12)}…, file is ${videoSha ? videoSha.slice(0, 12) + '…' : 'missing'}`);\n }\n\n if (opts.bundle) {\n const bundle = await openBundle(resolve(opts.bundle));\n const events = sha256Json(bundle.events);\n const frames = sha256Json(bundle.frames);\n if (events === verdict.bundleHashes.events && frames === verdict.bundleHashes.framesIndex) {\n log.ok('bundle hashes match (events + frame index)');\n } else {\n ok = false;\n log.error('bundle hash mismatch — the bundle is not the one this verdict describes');\n }\n }\n\n const { signVerdict, signablePayload } = await import('../verify/report.js');\n if (!verdict.signature) {\n log.warn('verdict is unsigned (no PLAYHEAD_SIGNING_KEY at verify time) — content integrity not attestable');\n } else if (!process.env.PLAYHEAD_SIGNING_KEY) {\n ok = false;\n log.error('verdict is signed but PLAYHEAD_SIGNING_KEY is not set — cannot check the signature');\n } else {\n const { signature: _sig, ...unsigned } = verdict;\n void signablePayload; // (payload construction is inside signVerdict)\n const expect = signVerdict(unsigned);\n if (expect === verdict.signature) log.ok('signature valid — verdict content is untampered');\n else {\n ok = false;\n log.error('SIGNATURE MISMATCH — the verdict was modified after signing');\n }\n }\n log.info(\n `provenance: playhead ${verdict.provenance.playheadVersion}, spec ${verdict.provenance.specHash.slice(0, 12)}…, captured ${verdict.provenance.capturedAt}, ${verdict.provenance.host}`,\n );\n process.exitCode = ok ? EXIT.OK : EXIT.QUALITY;\n });\n\nprogram\n .command('explore')\n .description('inspect a live app and print a grounded catalog of addressable elements')\n .argument('<url>', 'the running app URL to explore')\n .option('--viewport <wxh>', 'viewport, e.g. 1280x720', '1280x720')\n .option('--storage-state <file>', 'session file from \"playhead login\" for authed screens')\n .option('--headed', 'show the browser')\n .action(async (url: string, opts: { viewport: string; headed?: boolean; storageState?: string }) => {\n const { exploreUrl, formatCatalog } = await import('../authoring/explore.js');\n const [w, h] = opts.viewport.split('x').map(Number);\n const snap = await exploreUrl(url, { viewport: { w: w!, h: h! }, headless: !opts.headed, ...(opts.storageState ? { storageStatePath: resolve(opts.storageState) } : {}) });\n console.log(formatCatalog(snap));\n });\n\nprogram\n .command('author')\n .description('agent-author a grounded, validated spec by exploring the app toward a goal')\n .argument('<url>', 'the running app URL')\n .argument('<goal>', 'natural-language description of the flow to demo')\n .option('-o, --out <file>', 'where to write the spec', 'playhead.yaml')\n .option('--title <title>', 'video title (defaults to the goal)')\n .option('--kind <kind>', 'output kind', 'walkthrough')\n .option('--viewport <wxh>', 'viewport', '1280x720')\n .option('--max-steps <n>', 'safety cap on authored steps', '40')\n .option('--headed', 'show the browser')\n .action(async (url: string, goal: string, opts: { out: string; title?: string; kind: string; viewport: string; maxSteps: string; headed?: boolean }) => {\n const { authorSpec } = await import('../authoring/author.js');\n const [w, h] = opts.viewport.split('x').map(Number);\n await authorSpec({\n url,\n goal,\n outPath: resolve(opts.out),\n ...(opts.title ? { title: opts.title } : {}),\n viewport: { w: w!, h: h! },\n maxSteps: Number(opts.maxSteps),\n headless: !opts.headed,\n });\n });\n\nprogram\n .command('init')\n .description('scaffold a starter spec')\n .argument('[path]', 'where to write it', 'playhead.yaml')\n .action(async (path: string) => {\n try {\n await access(path);\n log.error(`${path} already exists`);\n process.exitCode = 1;\n return;\n } catch {\n /* does not exist — good */\n }\n await writeFile(path, STARTER_SPEC);\n log.ok(`wrote ${path} — edit it, then run: playhead render ${path}`);\n });\n\nprogram\n .command('mcp')\n .description('run Playhead as an MCP server (stdio) so a coding agent can drive it')\n .action(async () => {\n const { startMcpServer } = await import('../mcp/server.js');\n await startMcpServer();\n });\n\nprogram\n .command('doctor')\n .description('check that ffmpeg, the browser, and fonts are ready')\n .option('--ci', 'also check CI/container prerequisites (TTS, sandbox, shm)')\n .action(async (opts: { ci?: boolean }) => {\n let ok = true;\n if (opts.ci) {\n // TTS availability: narration degrades to silent when absent, but CI should know.\n const { execFile } = await import('node:child_process');\n const { promisify } = await import('node:util');\n const which = promisify(execFile);\n const hasSay = await which('which', ['say']).then(() => true).catch(() => false);\n if (hasSay) log.ok('tts: macOS `say` available');\n else log.warn('tts: no `say` binary — output.audio.narration will render SILENT on this host (Linux TTS provider planned)');\n if (process.platform === 'linux') {\n log.info('linux: run chromium with a base image that provides fonts + sandbox deps (see Dockerfile), and give /dev/shm ≥ 512MB or pass --disable-dev-shm-usage');\n }\n if (!process.env.PLAYHEAD_SIGNING_KEY) log.warn('signing: PLAYHEAD_SIGNING_KEY not set — verdicts will be unsigned');\n else log.ok('signing: PLAYHEAD_SIGNING_KEY set');\n }\n try {\n const res = await runBinary(ffmpegPath(), ['-version']);\n log.ok(`ffmpeg: ${res.stdout.split('\\n')[0]}`);\n } catch (e) {\n ok = false;\n log.error(`ffmpeg: ${(e as Error).message}`);\n }\n try {\n const res = await runBinary(ffprobePath(), ['-version']);\n log.ok(`ffprobe: ${res.stdout.split('\\n')[0]}`);\n } catch (e) {\n ok = false;\n log.error(`ffprobe: ${(e as Error).message}`);\n }\n try {\n const { chromium } = await import('playwright');\n const path = chromium.executablePath();\n await access(path);\n log.ok(`chromium: ${path}`);\n } catch {\n ok = false;\n log.error('chromium: not installed — run: npx playwright install chromium');\n }\n try {\n const { registerFonts } = await import('../theme/index.js');\n registerFonts();\n log.ok('fonts: Inter registered');\n } catch (e) {\n ok = false;\n log.error(`fonts: ${(e as Error).message}`);\n }\n if (!process.env.ANTHROPIC_API_KEY) log.info(pc.dim('vision review: ANTHROPIC_API_KEY not set (optional)'));\n process.exitCode = ok ? 0 : 1;\n });\n\nconst STARTER_SPEC = `playhead: 1\ntitle: \"My product walkthrough\"\napp:\n url: http://localhost:3000\n viewport: 1280x720\noutput:\n kind: walkthrough\n pacing: normal\nscenes:\n - id: first-flow\n title: \"Do the thing\"\n steps:\n - click: 'role=button[name=\"Get started\"]'\n - type: { target: 'label=Name', text: \"Ada Lovelace\" }\n - click: 'role=button[name=\"Save\"]'\n - expect: { target: 'text=\"Saved\"', visible: true }\n`;\n\nprogram.parseAsync().catch((e: Error) => {\n log.error(e.message);\n // 4 = usage (bad spec/args) · 1 = flow (app broke) · 3 = infra (everything else unexpected)\n process.exitCode = exitCodeFor(e);\n});\n"],"mappings":"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","names":["ctx","resolve","count","resolve","plane","join","sleep","writeFile","resolve","round1","readFile","join","join","dirname","createRequire","require","log","log","log","plane","shot","log","plan","log","lowerFirst","ctx","ctx","sharp","createCanvas","ctx","createRequire","require","resolve","writeFile","mkdtemp","join","tmpdir","spawn","resolve","createCanvas","plane","ctx","mkdir","writeFile","existsSync","join","createHash","createRequire","ffprobePath","require","execFile","promisify","mkdir","existsSync","join","createRequire","exec","ffmpegPath","require","join","writeFile","sharp","ctx","rect","cap","CLICK_KINDS","writeFile","createCanvas","ctx","truncate","readFile","join","mkdir","writeFile","readFile","pc","ctx","join","mkdir","readFile","join","existsSync","content","firstLine","sleep","writeFile","SETTLE","writeFile","mkdir","readFile","join","z","validateLive","formatValidateResult","reportToJira","collectEvidence","mkdir","writeFile","join","resolve","pc","toJUnit","renderBeforeAfter","reportToJira","validateLive","formatValidateResult","PlaywrightDriver","readFile","signVerdict","signablePayload","exploreUrl","formatCatalog","authorSpec","startMcpServer","execFile","promisify","chromium","registerFonts"]}
|
|
1
|
+
{"version":3,"sources":["../../src/spec/locators.ts","../../src/spec/schema.ts","../../src/spec/parse.ts","../../src/shared/easing.ts","../../src/shared/log.ts","../../src/capture/playwright-driver.ts","../../src/bundle/hash.ts","../../src/shared/version.ts","../../src/bundle/writer.ts","../../src/shared/geometry.ts","../../src/shared/exit.ts","../../src/capture/executor.ts","../../src/bundle/reader.ts","../../src/theme/index.ts","../../src/compose/types.ts","../../src/compose/kinds.ts","../../src/capture/events.ts","../../src/audio/timing.ts","../../src/compose/timeline/pacing.ts","../../src/compose/camera/interpolate.ts","../../src/compose/camera/planner.ts","../../src/compose/cursor/path.ts","../../src/compose/captions.ts","../../src/compose/overlays/text.ts","../../src/compose/overlays/build.ts","../../src/compose/cursor/render.ts","../../src/compose/overlays/draw.ts","../../src/compose/render/frameStore.ts","../../src/shared/ffmpeg.ts","../../src/compose/render/encoder.ts","../../src/compose/render/renderer.ts","../../src/audio/tts.ts","../../src/audio/mux.ts","../../src/compose/index.ts","../../src/verify/media.ts","../../src/verify/checks.ts","../../src/verify/contact-sheet.ts","../../src/verify/vision.ts","../../src/verify/report.ts","../../src/verify/runner.ts","../../src/beforeafter.ts","../../src/integrations/jira.ts","../../src/authoring/catalog.ts","../../src/authoring/explore.ts","../../src/authoring/validate.ts","../../src/authoring/serialize.ts","../../src/authoring/author.ts","../../src/mcp/server.ts","../../src/cli/index.ts"],"sourcesContent":["/**\n * Playhead locator grammar — resilient, label/role-based element addressing.\n *\n * role=button[name=\"Add user\"] role + accessible name\n * role=cell[name=/api key/i] regex accessible name\n * label=Email form control by label\n * text=\"User added\" visible text\n * placeholder=Search input placeholder\n * testid=add-user data-testid\n * css=#legacy .thing escape hatch (warned)\n * ... >> nth=1 pick among multiple matches\n * frame=#preview >> role=button[name=\"Save\"] pierce into an iframe (chainable)\n * frame=iframe[name=a] >> frame=#inner >> text=\"Hi\" nested frames\n *\n * Parsed form is serializable (regexes stored as {source, flags}) so it can live\n * in spec.resolved.json and events.json.\n */\n\nexport interface RegexSpec {\n source: string;\n flags: string;\n}\n\nexport type TextMatch = { exact: string } | { substring: string } | { regex: RegexSpec };\n\nexport type LocatorBase =\n | { kind: 'role'; role: string; name?: TextMatch }\n | { kind: 'label'; match: TextMatch }\n | { kind: 'text'; match: TextMatch }\n | { kind: 'placeholder'; match: TextMatch }\n | { kind: 'testid'; value: string }\n | { kind: 'css'; selector: string };\n\nexport interface ParsedLocator {\n base: LocatorBase;\n nth?: number;\n /** CSS selectors of the iframe chain to pierce (outermost first) before resolving `base`. */\n frames?: string[];\n /** The original spec string, kept for captions/diagnostics. */\n raw: string;\n}\n\nexport class LocatorParseError extends Error {}\n\nexport function parseLocator(input: string): ParsedLocator {\n const raw = input.trim();\n let nth: number | undefined;\n\n // Segments: [frame=SEL ...] BASE [nth=N]\n const parts = raw.split('>>').map((p) => p.trim());\n const frames: string[] = [];\n while (parts.length > 0 && parts[0]!.startsWith('frame=')) {\n const sel = unquote(parts.shift()!.slice('frame='.length).trim());\n if (!sel) throw new LocatorParseError(`Empty frame selector in \"${raw}\"`);\n frames.push(sel);\n }\n if (parts.length === 0) {\n throw new LocatorParseError(`Locator \"${raw}\" has frames but no element — add a base like role=... after the frame chain`);\n }\n const body = parts.shift()!;\n if (parts.length > 0) {\n const tail = parts.join(' >> ');\n const m = /^nth=(\\d+)$/.exec(tail);\n if (!m) throw new LocatorParseError(`Unsupported locator suffix \"${tail}\" in \"${raw}\" (only \"nth=N\" is supported)`);\n nth = Number(m[1]);\n }\n const withFrames = (p: ParsedLocator): ParsedLocator => (frames.length > 0 ? { ...p, frames } : p);\n\n const eq = body.indexOf('=');\n if (eq === -1) {\n throw new LocatorParseError(\n `Locator \"${raw}\" is missing an engine prefix — expected role=, label=, text=, placeholder=, testid= or css=`,\n );\n }\n const engine = body.slice(0, eq).trim();\n const rest = body.slice(eq + 1).trim();\n\n switch (engine) {\n case 'role': {\n const m = /^([\\w-]+)(?:\\[name=(.+)\\])?$/.exec(rest);\n if (!m) throw new LocatorParseError(`Malformed role locator \"${raw}\" — expected role=button[name=\"...\"]`);\n const base: LocatorBase = { kind: 'role', role: m[1]! };\n if (m[2] !== undefined) base.name = parseTextMatch(m[2]!, raw);\n return withFrames({ base, nth, raw });\n }\n case 'label':\n return withFrames({ base: { kind: 'label', match: parseTextMatch(rest, raw) }, nth, raw });\n case 'text':\n return withFrames({ base: { kind: 'text', match: parseTextMatch(rest, raw) }, nth, raw });\n case 'placeholder':\n return withFrames({ base: { kind: 'placeholder', match: parseTextMatch(rest, raw) }, nth, raw });\n case 'testid': {\n if (!rest) throw new LocatorParseError(`Empty testid in locator \"${raw}\"`);\n return withFrames({ base: { kind: 'testid', value: unquote(rest) }, nth, raw });\n }\n case 'css': {\n if (!rest) throw new LocatorParseError(`Empty css selector in locator \"${raw}\"`);\n return withFrames({ base: { kind: 'css', selector: rest }, nth, raw });\n }\n default:\n throw new LocatorParseError(\n `Unknown locator engine \"${engine}\" in \"${raw}\" — expected role, label, text, placeholder, testid or css`,\n );\n }\n}\n\nfunction parseTextMatch(s: string, context: string): TextMatch {\n const v = s.trim();\n if (v.startsWith('/')) {\n const m = /^\\/(.+)\\/([a-z]*)$/.exec(v);\n if (!m) throw new LocatorParseError(`Malformed regex \"${v}\" in locator \"${context}\"`);\n try {\n new RegExp(m[1]!, m[2]!);\n } catch {\n throw new LocatorParseError(`Invalid regex \"${v}\" in locator \"${context}\"`);\n }\n return { regex: { source: m[1]!, flags: m[2]! } };\n }\n if ((v.startsWith('\"') && v.endsWith('\"') && v.length >= 2) || (v.startsWith(\"'\") && v.endsWith(\"'\") && v.length >= 2)) {\n return { exact: v.slice(1, -1) };\n }\n if (!v) throw new LocatorParseError(`Empty text match in locator \"${context}\"`);\n return { substring: v };\n}\n\nfunction unquote(s: string): string {\n if ((s.startsWith('\"') && s.endsWith('\"')) || (s.startsWith(\"'\") && s.endsWith(\"'\"))) return s.slice(1, -1);\n return s;\n}\n\n/** Human-readable form of what a locator points at, used for captions when the accessible name is unavailable. */\nexport function locatorDisplayName(loc: ParsedLocator): string {\n const b = loc.base;\n switch (b.kind) {\n case 'role':\n return b.name ? textMatchDisplay(b.name) : b.role;\n case 'label':\n case 'text':\n case 'placeholder':\n return textMatchDisplay(b.match);\n case 'testid':\n return b.value;\n case 'css':\n return b.selector;\n }\n}\n\nfunction textMatchDisplay(m: TextMatch): string {\n if ('exact' in m) return m.exact;\n if ('substring' in m) return m.substring;\n return m.regex.source;\n}\n","import { z } from 'zod';\nimport { parseLocator } from './locators.js';\n\n/** \"1280x800\" → {w, h} */\nconst dimensions = z\n .string()\n .regex(/^\\d+x\\d+$/, 'expected WIDTHxHEIGHT, e.g. 1280x800')\n .transform((s) => {\n const [w, h] = s.split('x').map(Number);\n return { w: w!, h: h! };\n });\n\nconst locatorString = z.string().min(1).superRefine((val, ctx) => {\n try {\n parseLocator(val);\n } catch (e) {\n ctx.addIssue({ code: 'custom', message: (e as Error).message });\n }\n});\n\nconst focusHint = z.union([z.literal('target'), z.literal('wide'), locatorString]);\n\n/** Per-step extras shared by every action. */\nconst EXTRA_KEYS = ['caption', 'narration', 'focus', 'mask', 'shot', 'timeout'] as const;\n\n/** Common optional step fields. */\nconst stepExtras = {\n caption: z.string().optional(),\n /** The SPOKEN line for TTS narration — unconstrained by the caption card's size. Resolution:\n * spoken = narration ?? caption ?? auto; on-screen card = caption ?? auto. */\n narration: z.string().optional(),\n focus: focusHint.optional(),\n /** Camera-shot boundary control: 'cut' forces this step into its own shot; 'continue' merges\n * it into the previous shot even when the heuristic would split. Decouples camera cuts from\n * scene structure (scenes stay narrative). */\n shot: z.enum(['cut', 'continue']).optional(),\n /** Per-step budget override (ms) for finding the target / meeting the expectation. */\n timeout: z.number().int().positive().optional(),\n};\n\nconst targetOrShorthand = z.union([\n locatorString,\n z.object({ target: locatorString, ...stepExtras }),\n]);\n\n// ---- normalized step forms (the discriminated union everything downstream consumes) ----\n\n// Every step variant is .strict(): an unknown field inside a step payload (a typo like `txet:`,\n// or a knob that doesn't exist like `zoom:`) must FAIL LOUDLY — silently dropping it makes a\n// misspelled option indistinguishable from a feature that works badly.\nconst gotoStep = z.object({ action: z.literal('goto'), url: z.string(), ...stepExtras }).strict();\nconst pointerStep = z\n .object({\n action: z.enum(['click', 'dblclick', 'hover']),\n target: locatorString,\n ...stepExtras,\n })\n .strict();\nconst typeStep = z\n .object({\n action: z.literal('type'),\n target: locatorString,\n text: z.string(),\n mask: z.boolean().default(false),\n ...stepExtras,\n })\n .strict();\nconst pressStep = z.object({ action: z.literal('press'), keys: z.string(), ...stepExtras }).strict();\nconst selectStep = z\n .object({\n action: z.literal('select'),\n target: locatorString,\n value: z.string(),\n ...stepExtras,\n })\n .strict();\nconst scrollStep = z\n .object({\n action: z.literal('scroll'),\n target: locatorString.optional(),\n by: z.object({ x: z.number().default(0), y: z.number() }).strict().optional(),\n ...stepExtras,\n })\n .strict();\nconst expectStep = z\n .object({\n action: z.literal('expect'),\n target: locatorString,\n visible: z.boolean().optional(),\n text: z.string().optional(),\n /** Exact number of matching elements (e.g. rows in a filtered table). */\n count: z.number().int().min(0).optional(),\n ...stepExtras,\n })\n .strict();\n/** `wait: <ms>` is the discouraged blind sleep; `wait: { for: <locator>, state?, timeout? }`\n * is the structured form — wait until an element is visible/hidden, never a fixed nap. */\nconst waitStep = z\n .object({\n action: z.literal('wait'),\n ms: z.number().int().positive().optional(),\n for: locatorString.optional(),\n state: z.enum(['visible', 'hidden']).default('visible'),\n ...stepExtras,\n })\n .strict()\n .refine((s) => (s.ms !== undefined) !== (s.for !== undefined), {\n message: 'wait needs exactly one of `ms` (blind sleep, discouraged) or `for` (an element to wait on)',\n });\n\nexport const stepSchema = z.discriminatedUnion('action', [\n gotoStep,\n pointerStep,\n typeStep,\n pressStep,\n selectStep,\n scrollStep,\n expectStep,\n waitStep,\n]);\n\nexport type Step = z.infer<typeof stepSchema>;\n\n// ---- YAML authoring form: `- click: '...'` / `- type: { target, text }` with optional sibling keys ----\n\nconst ACTION_KEYS = ['goto', 'click', 'dblclick', 'hover', 'type', 'press', 'select', 'scroll', 'expect', 'wait'] as const;\n\nconst authoredStep = z\n .record(z.string(), z.unknown())\n .superRefine((obj, ctx) => {\n const actions = ACTION_KEYS.filter((k) => k in obj);\n if (actions.length !== 1) {\n // Echo what the author actually wrote and suggest the nearest action — \"expected one of\n // ten actions\" with no mention of the offending key forces a by-eye diff of the file.\n const unknown = Object.keys(obj).filter((k) => !(EXTRA_KEYS as readonly string[]).includes(k));\n const hints = unknown\n .map((k) => ({ k, near: nearestAction(k) }))\n .filter((h): h is { k: string; near: string } => h.near !== null)\n .map((h) => ` — did you mean \"${h.near}\" instead of \"${h.k}\"?`)\n .join('');\n ctx.addIssue({\n code: 'custom',\n message:\n actions.length === 0\n ? `Step has no action (found: ${unknown.join(', ') || 'nothing'})${hints || ` — expected one of: ${ACTION_KEYS.join(', ')}`}`\n : `Step has multiple actions (${actions.join(', ')}) — exactly one is allowed`,\n });\n return;\n }\n const known = new Set<string>([...ACTION_KEYS, ...EXTRA_KEYS]);\n for (const key of Object.keys(obj)) {\n if (!known.has(key)) {\n ctx.addIssue({ code: 'custom', message: `Unknown step field \"${key}\"` });\n }\n }\n })\n .transform((obj) => normalizeStep(obj));\n\n/** Nearest valid action to a typo (edit distance ≤ 2), or null. */\nfunction nearestAction(key: string): string | null {\n let best: string | null = null;\n let bestD = 3;\n for (const a of ACTION_KEYS) {\n const d = editDistance(key.toLowerCase(), a);\n if (d < bestD) {\n bestD = d;\n best = a;\n }\n }\n return best;\n}\n\nexport function editDistance(a: string, b: string): number {\n const dp = Array.from({ length: a.length + 1 }, (_, i) => [i, ...Array(b.length).fill(0)] as number[]);\n for (let j = 0; j <= b.length; j++) dp[0]![j] = j;\n for (let i = 1; i <= a.length; i++) {\n for (let j = 1; j <= b.length; j++) {\n dp[i]![j] = Math.min(\n dp[i - 1]![j]! + 1,\n dp[i]![j - 1]! + 1,\n dp[i - 1]![j - 1]! + (a[i - 1] === b[j - 1] ? 0 : 1),\n );\n }\n }\n return dp[a.length]![b.length]!;\n}\n\nfunction normalizeStep(obj: Record<string, unknown>): unknown {\n const action = ACTION_KEYS.find((k) => k in obj)!;\n const payload = obj[action];\n const extras: Record<string, unknown> = {};\n for (const k of EXTRA_KEYS) {\n if (k in obj) extras[k] = obj[k];\n }\n\n if (typeof payload === 'string') {\n // shorthand value: locator for element actions, url for goto, keys for press\n if (action === 'goto') return { action, url: payload, ...extras };\n if (action === 'press') return { action, keys: payload, ...extras };\n return { action, target: payload, ...extras };\n }\n if (typeof payload === 'number' && action === 'wait') {\n return { action, ms: payload, ...extras };\n }\n if (payload !== null && typeof payload === 'object') {\n return { action, ...(payload as Record<string, unknown>), ...extras };\n }\n return { action, value: payload, ...extras };\n}\n\n// ---- top-level spec ----\n//\n// Every object here is .strict(): a key the schema doesn't know is an ERROR, never silently\n// dropped. The spec must mean what it says — an author must be able to tell \"I configured this\n// wrong\" apart from \"this configuration does nothing\".\n\nexport const specSchema = z\n .object({\n playhead: z.literal(1),\n title: z.string().min(1),\n /** Title-card subtitle. Defaults to the app's host — set this for anything shareable. */\n subtitle: z.string().optional(),\n app: z\n .object({\n url: z.string().url(),\n /** Capture viewport. When omitted it is derived from output.aspect so portrait/square\n * outputs are captured at a matching viewport (the app reflows natively, no cropping). */\n viewport: dimensions.optional(),\n storageState: z.string().optional(),\n /** Fail fast when auth is stale: this locator must match after the initial load, or the\n * capture aborts — instead of confidently filming the login page. */\n assertLoggedIn: locatorString.optional(),\n /** For before/after: a second app to capture the same flow against (the \"before\"). */\n compareUrl: z.string().url().optional(),\n /** Determinism controls: same spec → same pixels regardless of where/when it runs. */\n environment: z\n .object({\n timezone: z.string().optional(),\n locale: z.string().optional(),\n colorScheme: z.enum(['light', 'dark']).optional(),\n /** Freeze Date at this ISO timestamp — \"3 minutes ago\" stops drifting between runs. */\n fixedTime: z.string().optional(),\n reducedMotion: z.boolean().optional(),\n })\n .strict()\n .optional(),\n /** Request interception: block third-party noise, stub responses, replay a HAR. */\n network: z\n .object({\n block: z.array(z.string()).optional(),\n stub: z\n .array(\n z\n .object({\n url: z.string(),\n status: z.number().int().optional(),\n body: z.string().optional(),\n contentType: z.string().optional(),\n })\n .strict(),\n )\n .optional(),\n har: z.string().optional(),\n })\n .strict()\n .optional(),\n /** window.confirm()/alert() policy. Default accept — the silent auto-dismiss films the\n * cancel branch of confirm-guarded flows. */\n dialogs: z.enum(['accept', 'dismiss']).optional(),\n /** Settle tuning for slow backends / chatty apps. */\n settle: z\n .object({\n idleMs: z.number().int().positive().optional(),\n capMs: z.number().int().positive().optional(),\n })\n .strict()\n .optional(),\n })\n .strict(),\n output: z\n .object({\n kind: z\n .enum(['walkthrough', 'demo', 'bug-repro', 'before-after', 'release', 'social'])\n .default('walkthrough'),\n aspect: z.enum(['16:9', '9:16', '1:1']).default('16:9'),\n /** Output resolution; when omitted it is derived from the aspect. */\n resolution: dimensions.optional(),\n fps: z.number().int().min(24).max(60).default(30),\n pacing: z.enum(['relaxed', 'normal', 'brisk']).optional(),\n /**\n * Multiplier on per-step dwell (min-step duration, post-action holds, outro).\n * 1 = the pacing preset as-is. Raise it for long-form teaching walkthroughs\n * where each screen should linger so a viewer can read and absorb it.\n */\n dwellScale: z.number().min(0.5).max(4).optional(),\n /**\n * Audio. `narration: tts` speaks each step's caption (pacing grows so every line finishes\n * before its step ends). `sfx` adds a soft synthesized click at each click beat. `music`\n * lays a user-supplied bed under everything, ducked beneath narration. Any audio work\n * finishes with loudness normalization (EBU R128, I=-16).\n */\n audio: z\n .object({\n narration: z.enum(['none', 'tts']).default('none'),\n // 'say' — macOS built-in (zero deps, Mac-only, robotic).\n // 'kokoro' — natural neural voice, offline, cross-platform; needs the optional\n // kokoro-js package (npm i kokoro-js). Voices: af_heart (default), am_michael, …\n provider: z.enum(['say', 'kokoro']).default('say'),\n voice: z.string().optional(),\n rate: z.number().int().min(80).max(400).optional(),\n /** Click sound effects at click/select beats. Defaults on when this block is present. */\n sfx: z.boolean().default(true),\n /** Music bed from a local audio file (no asset is bundled — bring your own licensed track). */\n music: z\n .object({\n file: z.string(),\n gainDb: z.number().min(-40).max(6).default(-19),\n })\n .strict()\n .optional(),\n })\n .strict()\n // The kokoro voice set is deliberately limited to two curated, natural voices —\n // Heart (default) and Michael. Aliases 'heart'/'michael' are accepted.\n .refine(\n (a) =>\n a.provider !== 'kokoro' ||\n a.voice === undefined ||\n ['heart', 'af_heart', 'michael', 'am_michael'].includes(a.voice),\n { message: \"kokoro voice must be 'heart' (default) or 'michael'\", path: ['voice'] },\n )\n .optional(),\n /** Closing card. When set, the video ends on a title-card-styled end card. */\n endCard: z\n .object({\n title: z.string().min(1),\n subtitle: z.string().optional(),\n })\n .strict()\n .optional(),\n })\n .strict()\n .prefault({}),\n // No `name` field: exactly one theme exists today, and a knob that is accepted but ignored is\n // a lie. It returns when a theme registry does.\n theme: z\n .object({\n accent: z\n .string()\n .regex(/^#[0-9a-fA-F]{6}$/, 'expected a #rrggbb hex color')\n .optional(),\n captions: z.enum(['bottom', 'top', 'off']).default('bottom'),\n })\n .strict()\n .prefault({}),\n masking: z\n .array(\n z\n .object({\n target: locatorString,\n style: z.enum(['solid', 'blur']).default('solid'),\n })\n .strict(),\n )\n .default([]),\n scenes: z\n .array(\n z\n .object({\n id: z.string().regex(/^[a-z0-9][a-z0-9-]*$/, 'scene ids are lowercase kebab-case'),\n title: z.string().optional(),\n steps: z.array(authoredStep.pipe(stepSchema)).min(1),\n })\n .strict(),\n )\n .min(1),\n })\n .strict();\n\nexport type Spec = z.infer<typeof specSchema>;\nexport type Scene = Spec['scenes'][number];\nexport type OutputSettings = Spec['output'];\nexport type MaskRule = Spec['masking'][number];\nexport type OutputKind = Spec['output']['kind'];\nexport type Aspect = Spec['output']['aspect'];\n\n/** Capture viewport + output resolution for each aspect (portrait/square reflow, never crop). */\nexport const ASPECTS: Record<Aspect, { viewport: { w: number; h: number }; resolution: { w: number; h: number } }> = {\n '16:9': { viewport: { w: 1280, h: 720 }, resolution: { w: 1920, h: 1080 } },\n '9:16': { viewport: { w: 720, h: 1280 }, resolution: { w: 1080, h: 1920 } },\n '1:1': { viewport: { w: 900, h: 900 }, resolution: { w: 1080, h: 1080 } },\n};\n\n/** The capture viewport: explicit spec value, else derived from the output aspect. */\nexport function resolveViewport(spec: Spec): { w: number; h: number } {\n return spec.app.viewport ?? ASPECTS[spec.output.aspect].viewport;\n}\n\n/** The output resolution: explicit spec value, else derived from the aspect. */\nexport function resolveResolution(spec: Spec): { w: number; h: number } {\n return spec.output.resolution ?? ASPECTS[spec.output.aspect].resolution;\n}\n\n/** A step with its position in the spec — the unit the capture executor and compositor work in. */\nexport interface AddressedStep {\n sceneId: string;\n sceneIndex: number;\n stepIndex: number;\n /** Global 1-based index across all scenes, used for step numbering. */\n ordinal: number;\n step: Step;\n}\n\nexport function flattenSteps(spec: Spec): AddressedStep[] {\n const out: AddressedStep[] = [];\n let ordinal = 0;\n spec.scenes.forEach((scene, sceneIndex) => {\n scene.steps.forEach((step, stepIndex) => {\n ordinal += 1;\n out.push({ sceneId: scene.id, sceneIndex, stepIndex, ordinal, step });\n });\n });\n return out;\n}\n","import { readFile } from 'node:fs/promises';\nimport { dirname, resolve as resolvePath } from 'node:path';\nimport { parseDocument, LineCounter, type Document } from 'yaml';\nimport { z } from 'zod';\nimport { specSchema, editDistance, type Spec } from './schema.js';\n\nexport class SpecError extends Error {\n constructor(\n message: string,\n public readonly issues: string[] = [],\n ) {\n super(message);\n }\n}\n\n/** Every key the schema knows, for \"did you mean\" suggestions on unrecognized keys. */\nconst KNOWN_KEYS = [\n 'playhead', 'title', 'subtitle', 'app', 'output', 'theme', 'masking', 'scenes', 'vars', 'extends',\n 'url', 'viewport', 'storageState', 'compareUrl', 'assertLoggedIn', 'environment', 'network', 'dialogs', 'settle',\n 'timezone', 'locale', 'colorScheme', 'fixedTime', 'reducedMotion', 'block', 'stub', 'har', 'status', 'body', 'contentType', 'idleMs', 'capMs',\n 'kind', 'aspect', 'resolution', 'fps', 'pacing', 'dwellScale', 'audio', 'endCard',\n 'narration', 'provider', 'voice', 'rate', 'sfx', 'music', 'file', 'gainDb',\n 'accent', 'captions',\n 'target', 'style', 'id', 'steps', 'shot', 'timeout',\n 'goto', 'click', 'dblclick', 'hover', 'type', 'press', 'select', 'scroll', 'expect', 'wait',\n 'caption', 'focus', 'mask', 'text', 'value', 'keys', 'ms', 'by', 'visible', 'hidden', 'count',\n 'for', 'state', 'x', 'y',\n];\n\nfunction suggest(key: string): string | null {\n let best: string | null = null;\n let bestD = 3;\n for (const k of KNOWN_KEYS) {\n const d = editDistance(key.toLowerCase(), k.toLowerCase());\n if (d > 0 && d < bestD) {\n bestD = d;\n best = k;\n }\n }\n return best;\n}\n\n/**\n * Parse + validate YAML text into a Spec. Supports:\n * - `vars:` — `{{name}}` interpolation across every string in the spec; values may reference\n * the environment as `${env.NAME}` or `${env.NAME:-default}`. Unknown `{{var}}` is an error.\n * - line/column positions on every validation error (mapped back to the YAML source).\n * `extends:` requires file context — use loadSpec.\n */\nexport function parseSpec(yamlText: string, sourcePath = '<inline>'): Spec {\n const lineCounter = new LineCounter();\n const doc = parseDocument(yamlText, { lineCounter, keepSourceTokens: true });\n if (doc.errors.length > 0) {\n const first = doc.errors[0]!;\n throw new SpecError(`${sourcePath}: not valid YAML — ${first.message}`);\n }\n const raw = doc.toJS() as Record<string, unknown> | null;\n if (raw && typeof raw === 'object' && 'extends' in raw) {\n throw new SpecError(`${sourcePath}: \"extends\" needs a file on disk — load the spec with loadSpec/the CLI, not inline text`);\n }\n return validateResolved(interpolate(raw, sourcePath), sourcePath, doc, lineCounter);\n}\n\n/** Load a spec file, resolving `extends:` (base file merged under this one) and `vars:`. */\nexport async function loadSpec(path: string): Promise<Spec> {\n const merged = await loadRaw(resolvePath(path), 0);\n // Re-parse the LEAF file for position mapping: merged keys that came from a base file simply\n // won't have positions, which is the honest best effort for multi-file specs.\n const text = await readFile(resolvePath(path), 'utf8');\n const lineCounter = new LineCounter();\n const doc = parseDocument(text, { lineCounter });\n return validateResolved(interpolate(merged, path), path, doc, lineCounter);\n}\n\n/** Read a YAML file to a plain object, recursively merging its `extends:` base underneath it. */\nasync function loadRaw(path: string, depth: number): Promise<Record<string, unknown>> {\n if (depth > 4) throw new SpecError(`${path}: extends chain deeper than 4 — check for a cycle`);\n const text = await readFile(path, 'utf8');\n const doc = parseDocument(text);\n if (doc.errors.length > 0) throw new SpecError(`${path}: not valid YAML — ${doc.errors[0]!.message}`);\n const raw = (doc.toJS() ?? {}) as Record<string, unknown>;\n const base = raw.extends;\n delete raw.extends;\n if (base === undefined) return raw;\n if (typeof base !== 'string') throw new SpecError(`${path}: \"extends\" must be a path string`);\n const baseObj = await loadRaw(resolvePath(dirname(path), base), depth + 1);\n return mergeSpecs(baseObj, raw);\n}\n\n/** Merge rule: objects merge deep, scalars in the child win, `masking`/`scenes` arrays append\n * (base first), any other array is replaced by the child's. */\nfunction mergeSpecs(base: Record<string, unknown>, child: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = { ...base };\n for (const [k, v] of Object.entries(child)) {\n const b = out[k];\n if (Array.isArray(b) && Array.isArray(v) && (k === 'masking' || k === 'scenes')) {\n out[k] = [...b, ...v];\n } else if (isPlainObject(b) && isPlainObject(v)) {\n out[k] = mergeSpecs(b, v);\n } else {\n out[k] = v;\n }\n }\n return out;\n}\n\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n return typeof v === 'object' && v !== null && !Array.isArray(v);\n}\n\n/** Resolve `vars:` (+ `${env.X[:-default]}` in their values) and interpolate `{{name}}` across\n * every string in the document. Fails loudly on an unknown var or unset env with no default —\n * a URL that silently renders \"undefined\" is worse than a parse error. */\nfunction interpolate(raw: unknown, sourcePath: string): unknown {\n if (!isPlainObject(raw)) return raw;\n const varsIn = isPlainObject(raw.vars) ? raw.vars : {};\n const vars = new Map<string, string>();\n for (const [name, value] of Object.entries(varsIn)) {\n vars.set(name, resolveEnv(String(value), sourcePath));\n }\n const doc = { ...raw };\n delete doc.vars;\n\n const seen = (s: string): string => {\n const withEnv = resolveEnv(s, sourcePath);\n return withEnv.replace(/\\{\\{\\s*([a-zA-Z0-9_.-]+)\\s*\\}\\}/g, (_, name: string) => {\n const v = vars.get(name);\n if (v === undefined) {\n const near = suggest(name) ?? [...vars.keys()].find((k) => editDistance(k, name) <= 2);\n throw new SpecError(\n `${sourcePath}: unknown variable {{${name}}}${near ? ` — did you mean {{${near}}}?` : ''} (declared vars: ${[...vars.keys()].join(', ') || 'none'})`,\n );\n }\n return v;\n });\n };\n const walk = (v: unknown): unknown => {\n if (typeof v === 'string') return seen(v);\n if (Array.isArray(v)) return v.map(walk);\n if (isPlainObject(v)) return Object.fromEntries(Object.entries(v).map(([k, val]) => [k, walk(val)]));\n return v;\n };\n return walk(doc);\n}\n\n/** `${env.NAME}` / `${env.NAME:-default}` → the environment value (or default). */\nfunction resolveEnv(s: string, sourcePath: string): string {\n return s.replace(/\\$\\{env\\.([A-Za-z_][A-Za-z0-9_]*)(?::-([^}]*))?\\}/g, (_, name: string, dflt?: string) => {\n const v = process.env[name];\n if (v !== undefined) return v;\n if (dflt !== undefined) return dflt;\n throw new SpecError(`${sourcePath}: environment variable ${name} is not set and has no default (use \\${env.${name}:-fallback})`);\n });\n}\n\nfunction validateResolved(\n resolved: unknown,\n sourcePath: string,\n doc: Document,\n lineCounter: LineCounter,\n): Spec {\n const result = specSchema.safeParse(resolved);\n if (!result.success) {\n const issues = result.error.issues.map((iss) => formatIssue(iss, sourcePath, doc, lineCounter));\n throw new SpecError(`${sourcePath}: invalid spec\\n - ${issues.join('\\n - ')}`, issues);\n }\n return result.data;\n}\n\nfunction formatIssue(\n iss: z.core.$ZodIssue,\n sourcePath: string,\n doc: Document,\n lineCounter: LineCounter,\n): string {\n const where = iss.path.length ? humanPath(iss.path) : 'spec';\n const pos = positionOf(iss.path, doc, lineCounter);\n const at = pos ? `${sourcePath}:${pos.line}:${pos.col} ` : '';\n // Strict-mode \"unrecognized key\" errors get a nearest-known-key suggestion, so a typo like\n // `acent:` reads as \"did you mean accent?\" instead of a bare rejection.\n if (iss.code === 'unrecognized_keys') {\n const keys = (iss as { keys: string[] }).keys;\n const hints = keys\n .map((k) => ({ k, near: suggest(k) }))\n .map((h) => (h.near ? `\"${h.k}\" (did you mean \"${h.near}\"?)` : `\"${h.k}\"`))\n .join(', ');\n return `${at}${where}: unknown key${keys.length > 1 ? 's' : ''} ${hints}`;\n }\n return `${at}${where}: ${iss.message}`;\n}\n\n/** YAML source position for a Zod issue path (walking as deep as the leaf document allows). */\nfunction positionOf(\n path: PropertyKey[],\n doc: Document,\n lineCounter: LineCounter,\n): { line: number; col: number } | null {\n for (let depth = path.length; depth > 0; depth--) {\n try {\n const node = doc.getIn(path.slice(0, depth) as (string | number)[], true) as\n | { range?: [number, number, number] }\n | undefined;\n if (node?.range) {\n const pos = lineCounter.linePos(node.range[0]);\n return { line: pos.line, col: pos.col };\n }\n } catch {\n /* keep walking up */\n }\n }\n return null;\n}\n\nfunction humanPath(path: PropertyKey[]): string {\n // scenes.0.steps.2 → scenes[0].steps[2]\n return path\n .map((seg, i) => (typeof seg === 'number' ? `[${seg}]` : i === 0 ? String(seg) : `.${String(seg)}`))\n .join('');\n}\n","/** Cubic bezier easing (CSS-style: fixed endpoints (0,0) and (1,1)). Serializable by its four control values. */\nexport type BezierParams = [number, number, number, number];\n\nexport const EASE_ZOOM: BezierParams = [0.4, 0, 0.2, 1];\nexport const EASE_PAN: BezierParams = [0.3, 0, 0.15, 1];\n\n/** Evaluate a CSS cubic-bezier at progress t ∈ [0,1] (solves x(t)=t for the parameter, returns y). */\nexport function cubicBezier(p: BezierParams, t: number): number {\n if (t <= 0) return 0;\n if (t >= 1) return 1;\n const [x1, y1, x2, y2] = p;\n // Newton-Raphson on x(u) = t\n let u = t;\n for (let i = 0; i < 8; i++) {\n const x = bez(u, x1, x2) - t;\n if (Math.abs(x) < 1e-6) break;\n const dx = dbez(u, x1, x2);\n if (Math.abs(dx) < 1e-6) break;\n u -= x / dx;\n }\n return bez(Math.max(0, Math.min(1, u)), y1, y2);\n}\n\nfunction bez(u: number, a: number, b: number): number {\n const v = 1 - u;\n return 3 * v * v * u * a + 3 * v * u * u * b + u * u * u;\n}\n\nfunction dbez(u: number, a: number, b: number): number {\n const v = 1 - u;\n return 3 * v * v * a + 6 * v * u * (b - a) + 3 * u * u * (1 - b);\n}\n\n/** Minimum-jerk position profile: smooth human-like travel, s(0)=0, s(1)=1, zero velocity/acceleration at ends. */\nexport function minJerk(t: number): number {\n if (t <= 0) return 0;\n if (t >= 1) return 1;\n return t * t * t * (10 - 15 * t + 6 * t * t);\n}\n","import pc from 'picocolors';\n\nlet verbose = false;\n\nexport function setVerbose(v: boolean): void {\n verbose = v;\n}\n\n// ALL human logging goes to stderr: stdout belongs to machine output (--json, catalogs),\n// so `playhead render --json | jq` works without ANSI noise corrupting the payload.\nexport const log = {\n info(msg: string): void {\n console.error(pc.dim('[playhead]') + ' ' + msg);\n },\n step(msg: string): void {\n console.error(pc.cyan(' ▸ ') + msg);\n },\n ok(msg: string): void {\n console.error(pc.green(' ✓ ') + msg);\n },\n warn(msg: string): void {\n console.error(pc.yellow(' ⚠ ') + msg);\n },\n error(msg: string): void {\n console.error(pc.red(' ✗ ') + msg);\n },\n debug(msg: string): void {\n if (verbose) console.error(pc.dim(' · ' + msg));\n },\n};\n","import { chromium, type Browser, type BrowserContext, type Page, type CDPSession, type Locator, type FrameLocator } from 'playwright';\nimport type {\n Driver,\n DriverLaunchOptions,\n MaskInstruction,\n RawInteractable,\n ScreencastFrame,\n ScreencastOptions,\n} from './driver-api.js';\nimport type { ParsedLocator, TextMatch } from '../spec/locators.js';\nimport type { TargetInfo, CursorWaypoint } from './events.js';\nimport type { Point } from '../shared/geometry.js';\nimport { minJerk } from '../shared/easing.js';\nimport { log } from '../shared/log.js';\n\n/** Budget for a single input dispatch (mouse/keyboard) — these have no Playwright timeout of\n * their own and a wedged renderer otherwise blocks them forever. */\nconst INPUT_TIMEOUT_MS = 5000;\n\nconst MASK_INIT_SCRIPT = `\n(() => {\n if (window.__playheadMaskInstalled) return;\n window.__playheadMaskInstalled = true;\n // Each masked element gets its own overlay box parented into that element's own DOM subtree.\n // This is what makes masking survive the top layer: an element inside a <dialog> modal (or a\n // popover) paints above a document-level overlay, so the box must be a descendant of the same\n // top-layer subtree to cover it. A position:fixed box stays out of flow, so parenting it into a\n // flex/grid container does not disturb layout.\n const boxes = new Map();\n const base = (box) => {\n box.setAttribute('aria-hidden', 'true');\n box.style.position = 'fixed';\n box.style.pointerEvents = 'none';\n box.style.zIndex = '2147483647';\n box.style.borderRadius = '5px';\n box.style.margin = '0';\n };\n const sync = (box, el, style) => {\n const r = el.getBoundingClientRect();\n const pad = 3; // cover focus rings / borders just outside the element box\n box.style.left = (r.left - pad) + 'px';\n box.style.top = (r.top - pad) + 'px';\n box.style.width = (r.width + pad * 2) + 'px';\n box.style.height = (r.height + pad * 2) + 'px';\n box.style.display = r.width > 0 && r.height > 0 ? 'block' : 'none';\n if (style === 'blur') {\n box.style.backdropFilter = 'blur(18px)';\n box.style.webkitBackdropFilter = 'blur(18px)';\n box.style.background = 'rgba(120,124,140,0.45)';\n } else {\n box.style.backdropFilter = '';\n box.style.background = '#2a2f3a';\n }\n };\n // In-page rule matching: CSS-expressible mask rules (testid=, css=) are pushed into\n // window.__playheadMaskCssRules and re-scanned continuously, so an element that APPEARS\n // MID-STEP (a token in a modal, an email in a toast, a row from the fetch settle waits on)\n // is tagged the frame it appears — not seconds later at the next step boundary. Node-side\n // tagging remains the backstop for rules needing Playwright semantics (role/label/text).\n let scanTick = 0;\n const scanRules = () => {\n const rules = window.__playheadMaskCssRules || [];\n for (const r of rules) {\n try {\n for (const el of document.querySelectorAll(r.css)) {\n if (!el.hasAttribute('data-playhead-mask')) el.setAttribute('data-playhead-mask', r.style);\n }\n } catch (e) {}\n }\n };\n const tick = () => {\n try {\n if (scanTick++ % 3 === 0) scanRules(); // every ~3 frames — cheap, and a 1-frame leak beats a 1-step leak\n const tagged = new Set(document.querySelectorAll('[data-playhead-mask]'));\n for (const [el, box] of boxes) {\n if (!tagged.has(el) || !el.isConnected) { box.remove(); boxes.delete(el); }\n }\n for (const el of tagged) {\n const parent = el.parentElement || document.body;\n let box = boxes.get(el);\n if (!box) {\n box = document.createElement('div');\n base(box);\n parent.appendChild(box);\n boxes.set(el, box);\n } else if (box.parentElement !== parent) {\n parent.appendChild(box);\n }\n sync(box, el, el.getAttribute('data-playhead-mask'));\n }\n } catch (e) {}\n requestAnimationFrame(tick);\n };\n requestAnimationFrame(tick);\n})();\n`;\n\n/** In-page fallback accessible-name computation for when the CDP AX lookup fails. */\nconst FALLBACK_NAME_FN = `(el) => {\n const norm = (s) => (s || '').replace(/\\\\s+/g, ' ').trim();\n const label = el.getAttribute('aria-label');\n if (label) return norm(label);\n const labelledBy = el.getAttribute('aria-labelledby');\n if (labelledBy) {\n const parts = labelledBy.split(/\\\\s+/).map((id) => {\n const ref = document.getElementById(id);\n return ref ? ref.textContent : '';\n });\n const joined = norm(parts.join(' '));\n if (joined) return joined;\n }\n if (el.labels && el.labels.length) return norm(el.labels[0].textContent);\n if (el.alt) return norm(el.alt);\n const text = norm(el.textContent);\n if (text) return text.slice(0, 80);\n if (el.placeholder) return norm(el.placeholder);\n if (el.title) return norm(el.title);\n return null;\n}`;\n\n/** In-page: gather every interactable element with the fields needed to author a grounded locator. */\nconst COLLECT_INTERACTABLES_FN = `() => {\n const norm = (s) => (s || '').replace(/\\\\s+/g, ' ').trim();\n // Accessible text = visible text excluding aria-hidden / hidden subtrees, matching how the\n // ARIA name is computed (so a decorative icon inside a link doesn't leak into the name).\n const accText = (el) => {\n let t = '';\n const walk = (node) => {\n if (node.nodeType === 3) { t += node.textContent; return; }\n if (node.nodeType !== 1) return;\n if (node.getAttribute && (node.getAttribute('aria-hidden') === 'true' || node.hasAttribute('hidden'))) return;\n for (const c of node.childNodes) walk(c);\n };\n walk(el);\n return norm(t);\n };\n const IMPLICIT = { A: 'link', BUTTON: 'button', SELECT: 'combobox', TEXTAREA: 'textbox', SUMMARY: 'button' };\n const inputRole = (el) => {\n const t = (el.getAttribute('type') || 'text').toLowerCase();\n if (t === 'checkbox') return 'checkbox';\n if (t === 'radio') return 'radio';\n if (t === 'range') return 'slider';\n if (t === 'button' || t === 'submit' || t === 'reset') return 'button';\n if (t === 'search') return 'searchbox';\n return 'textbox';\n };\n const accName = (el) => {\n const al = el.getAttribute('aria-label'); if (al) return norm(al);\n const lb = el.getAttribute('aria-labelledby');\n if (lb) { const parts = lb.split(/\\\\s+/).map((id) => { const r = document.getElementById(id); return r ? r.textContent : ''; }); const j = norm(parts.join(' ')); if (j) return j; }\n if (el.labels && el.labels.length) return accText(el.labels[0]);\n if (el.alt) return norm(el.alt);\n // NEVER walk a <select>'s subtree: that concatenates every <option> into a monster\n // \"Choose option...grayrednavy…\" pseudo-name that no human would write as a locator.\n if (el.tagName === 'SELECT' || el.tagName === 'DATALIST') {\n const sel = el.selectedOptions && el.selectedOptions[0];\n return sel ? norm(sel.textContent) : null;\n }\n const txt = accText(el); if (txt) return txt.slice(0, 80);\n if (el.placeholder) return norm(el.placeholder);\n if (el.title) return norm(el.title);\n return null;\n };\n // Landmark region for catalog grouping: which part of the page the element lives in.\n const regionOf = (el) => {\n const lm = el.closest('[role=dialog], dialog, nav, [role=navigation], header, [role=banner], aside, [role=complementary], footer, [role=contentinfo], main, [role=main]');\n if (!lm) return 'page';\n const tag = lm.tagName.toLowerCase();\n const role = lm.getAttribute && lm.getAttribute('role');\n if (tag === 'dialog' || role === 'dialog') return 'dialog';\n if (tag === 'nav' || role === 'navigation') return 'nav';\n if (tag === 'header' || role === 'banner') return 'header';\n if (tag === 'aside' || role === 'complementary') return 'sidebar';\n if (tag === 'footer' || role === 'contentinfo') return 'footer';\n return 'main';\n };\n const sel = 'button, a[href], input, select, textarea, summary, [role=button], [role=link], [role=tab], [role=switch], [role=menuitem], [role=checkbox], [contenteditable=\"\"], [contenteditable=true], h1, h2, h3';\n const seen = new Set();\n const out = [];\n for (const el of document.querySelectorAll(sel)) {\n if (seen.has(el)) continue; seen.add(el);\n const r = el.getBoundingClientRect();\n const style = getComputedStyle(el);\n const visible = r.width > 1 && r.height > 1 && style.visibility !== 'hidden' && style.display !== 'none' &&\n r.bottom > 0 && r.top < innerHeight && r.right > 0 && r.left < innerWidth;\n const tag = el.tagName;\n const explicit = el.getAttribute('role');\n const role = explicit || IMPLICIT[tag] || (tag === 'INPUT' ? inputRole(el) : (tag[0] === 'H' && tag.length === 2 ? 'heading' : null));\n let label = null;\n if (el.labels && el.labels.length) label = norm(el.labels[0].textContent);\n const options = tag === 'SELECT' ? Array.from(el.options).map((o) => norm(o.textContent)) : undefined;\n out.push({\n tag, role,\n accessibleName: accName(el),\n label,\n placeholder: el.getAttribute && el.getAttribute('placeholder') ? norm(el.getAttribute('placeholder')) : null,\n testId: el.getAttribute && (el.getAttribute('data-testid') || el.getAttribute('data-test-id')) || null,\n text: accText(el).slice(0, 80) || null,\n bbox: { x: r.x, y: r.y, w: r.width, h: r.height },\n visible,\n inputType: tag === 'INPUT' ? (el.getAttribute('type') || 'text').toLowerCase() : (tag === 'SELECT' ? 'select' : null),\n region: regionOf(el),\n ...(options ? { options } : {}),\n });\n }\n return out;\n}`;\n\nexport class PlaywrightDriver implements Driver {\n private browser!: Browser;\n private context!: BrowserContext;\n private page!: Page;\n private cdp!: CDPSession;\n /** Dedicated CDP session for the capture loop so its screenshots never contend with the\n * executor's accessibility/geometry lookups on the main session (which could deadlock). */\n private captureCdp!: CDPSession;\n private cursor: Point = { x: 0, y: 0 };\n private navCallbacks: ((url: string, t: number) => void)[] = [];\n private captureActive = false;\n private captureLoop: Promise<void> | null = null;\n private captureOnFrame: ((f: ScreencastFrame) => void) | null = null;\n private captureOpts: ScreencastOptions | null = null;\n private inflightGrab: Promise<void> | null = null;\n private lastFrameNodeMs = 0;\n private clockOffset = 0;\n private tagCounter = 0;\n private typingMaskLoc: ParsedLocator | null = null;\n\n async launch(opts: DriverLaunchOptions): Promise<void> {\n const env = opts.environment;\n this.browser = await chromium.launch({ headless: opts.headless ?? true });\n this.context = await this.browser.newContext({\n viewport: { width: opts.viewport.w, height: opts.viewport.h },\n deviceScaleFactor: opts.dpr,\n colorScheme: env?.colorScheme ?? 'light',\n ...(env?.timezone ? { timezoneId: env.timezone } : {}),\n ...(env?.locale ? { locale: env.locale } : {}),\n ...(env?.reducedMotion ? { reducedMotion: 'reduce' as const } : {}),\n ...(opts.storageStatePath ? { storageState: opts.storageStatePath } : {}),\n });\n this.context.setDefaultTimeout(10_000);\n this.context.setDefaultNavigationTimeout(20_000);\n\n // Network interception: blocked third-party noise, canned responses, HAR replay.\n const net = opts.network;\n if (net?.har) await this.context.routeFromHAR(net.har, { notFound: 'fallback' });\n for (const glob of net?.block ?? []) {\n await this.context.route(glob, (route) => route.fulfill({ status: 204, body: '' }));\n }\n for (const stub of net?.stub ?? []) {\n await this.context.route(stub.url, (route) =>\n route.fulfill({\n status: stub.status ?? 200,\n body: stub.body ?? '',\n contentType: stub.contentType ?? 'application/json',\n }),\n );\n }\n\n this.page = await this.context.newPage();\n if (env?.fixedTime) await this.page.clock.setFixedTime(new Date(env.fixedTime));\n await this.page.addInitScript(MASK_INIT_SCRIPT);\n this.cdp = await this.context.newCDPSession(this.page);\n this.captureCdp = await this.context.newCDPSession(this.page);\n this.page.on('framenavigated', (frame) => {\n if (frame === this.page.mainFrame()) {\n const t = Date.now();\n for (const cb of this.navCallbacks) cb(frame.url(), t);\n }\n });\n\n // Evidence + correctness listeners.\n this.page.on('console', (msg) => this.pushConsole(msg.type(), msg.text()));\n this.page.on('pageerror', (err) => this.pushConsole('pageerror', err.message));\n this.page.on('crash', () => this.pushConsole('crash', 'page crashed'));\n // Dialogs: Playwright's default DISMISSES, so a confirm()-guarded delete silently films the\n // cancel branch. Accept by default (spec-controllable), and always record it.\n const dialogPolicy = opts.dialogs ?? 'accept';\n this.page.on('dialog', (dialog) => {\n this.pushConsole('dialog', `${dialog.type()}(\"${dialog.message()}\") → ${dialogPolicy}`);\n void (dialogPolicy === 'accept' ? dialog.accept() : dialog.dismiss()).catch(() => {});\n });\n // Popups/new tabs: capture stays on the main page — record loudly instead of failing silently.\n this.context.on('page', (p) => {\n if (p !== this.page) {\n this.pushConsole('popup', `new tab/popup opened: ${p.url()} (not filmed — capture follows the main page)`);\n log.warn(`popup opened (${p.url()}) — multi-tab capture is not yet supported; footage stays on the main page`);\n }\n });\n\n this.cursor = { x: opts.viewport.w / 2, y: opts.viewport.h * 0.6 };\n await this.page.mouse.move(this.cursor.x, this.cursor.y);\n }\n\n private consoleBuf: { t: number; type: string; text: string }[] = [];\n\n private pushConsole(type: string, text: string): void {\n this.consoleBuf.push({ t: Date.now(), type, text: text.slice(0, 500) });\n if (this.consoleBuf.length > 500) this.consoleBuf.shift();\n }\n\n consoleLog(): { t: number; type: string; text: string }[] {\n return [...this.consoleBuf];\n }\n\n async close(): Promise<void> {\n if (!this.browser) return;\n await withTimeout(this.browser.close(), 8000).catch(() => {});\n }\n\n async measureClockOffset(): Promise<number> {\n const samples: number[] = [];\n for (let i = 0; i < 5; i++) {\n const t0 = Date.now();\n const browserNow = await withTimeout(this.page.evaluate(() => Date.now()), 2000).catch(() => t0);\n const t1 = Date.now();\n samples.push(browserNow - (t0 + t1) / 2);\n }\n samples.sort((a, b) => a - b);\n this.clockOffset = samples[2]!;\n return this.clockOffset;\n }\n\n async goto(url: string): Promise<void> {\n await this.page.goto(url, { waitUntil: 'load' });\n // fonts.ready can stay pending FOREVER on a wedged dev server (one stalled font asset never\n // resolves the promise — .catch() only covers rejection). Race it in-page against a short\n // timer, and bound the evaluate itself so a blocked main thread can't hang the capture.\n await withTimeout(\n this.page.evaluate(\n () => Promise.race([(document as any).fonts?.ready, new Promise((r) => setTimeout(r, 2000))]),\n ),\n 3000,\n ).catch(() => {});\n }\n\n onNavigation(cb: (url: string, t: number) => void): void {\n this.navCallbacks.push(cb);\n }\n\n currentUrl(): string {\n return this.page.url();\n }\n\n async currentTitle(): Promise<string> {\n return this.page.title().catch(() => '');\n }\n\n async ariaSnapshot(): Promise<string> {\n return this.page.locator('body').ariaSnapshot().catch(() => '');\n }\n\n async countMatches(loc: ParsedLocator): Promise<number> {\n try {\n return await this.toLocator(loc).count();\n } catch {\n return 0;\n }\n }\n\n async collectInteractables(): Promise<RawInteractable[]> {\n const collect = new Function(`return (${COLLECT_INTERACTABLES_FN})()`) as () => RawInteractable[];\n const out = await withTimeout(this.page.evaluate(collect), 10_000).catch(() => [] as RawInteractable[]);\n\n // Pierce one level of iframes that have an addressable selector, so exploration SEES frame\n // content (a Storybook canvas, an embedded widget) and emits frame-qualified locators.\n const handles = await this.page.$$('iframe').catch(() => []);\n for (const h of handles) {\n try {\n const sel = await h.evaluate((el: HTMLIFrameElement) => {\n if (el.id) return `#${CSS.escape(el.id)}`;\n const name = el.getAttribute('name');\n if (name) return `iframe[name=\"${name}\"]`;\n const tid = el.getAttribute('data-testid');\n if (tid) return `iframe[data-testid=\"${tid}\"]`;\n return null;\n });\n if (!sel) continue;\n const frame = await h.contentFrame();\n if (!frame) continue;\n const rect = await h.boundingBox();\n const inner = await withTimeout(\n frame.evaluate(collect),\n 8000,\n ).catch(() => [] as RawInteractable[]);\n for (const e of inner) {\n out.push({\n ...e,\n framePrefix: `frame=${sel}`,\n bbox: rect ? { x: e.bbox.x + rect.x, y: e.bbox.y + rect.y, w: e.bbox.w, h: e.bbox.h } : e.bbox,\n });\n }\n } catch {\n /* cross-origin or detached frame — unexplorable, skip */\n }\n }\n return out;\n }\n\n // ---------- locating & measuring ----------\n\n private toLocator(loc: ParsedLocator): Locator {\n // Frame chain first: `frame=#preview >> role=...` pierces into the iframe(s). Page-level\n // locators pierce shadow DOM for free but NEVER iframes — this is what makes an app whose\n // content lives in a frame (Storybook canvases, embedded checkouts, MFEs) addressable.\n let scope: Page | FrameLocator = this.page;\n for (const sel of loc.frames ?? []) scope = scope.frameLocator(sel);\n const b = loc.base;\n let l: Locator;\n switch (b.kind) {\n case 'role':\n l = scope.getByRole(b.role as Parameters<Page['getByRole']>[0], b.name ? { name: toPw(b.name), exact: isExact(b.name) } : {});\n break;\n case 'label':\n l = scope.getByLabel(toPw(b.match), { exact: isExact(b.match) });\n break;\n case 'text':\n l = scope.getByText(toPw(b.match), { exact: isExact(b.match) });\n break;\n case 'placeholder':\n l = scope.getByPlaceholder(toPw(b.match), { exact: isExact(b.match) });\n break;\n case 'testid':\n l = scope.getByTestId(b.value);\n break;\n case 'css':\n l = scope.locator(b.selector);\n break;\n }\n if (loc.nth !== undefined) l = l.nth(loc.nth);\n return l;\n }\n\n async resolveTarget(loc: ParsedLocator, timeoutMs: number): Promise<TargetInfo> {\n const locator = this.toLocator(loc);\n try {\n await locator.waitFor({ state: 'visible', timeout: timeoutMs });\n } catch (e) {\n // Never collapse distinct failures into one string: an ambiguous locator (strict-mode\n // violation), a hidden-but-present element, and a genuinely missing element each need a\n // different fix from the author — say which one this is.\n const msg = (e as Error).message ?? '';\n if (/strict mode violation/i.test(msg)) {\n const count = await locator.count().catch(() => -1);\n throw new Error(\n `Locator is ambiguous: ${loc.raw} matches ${count >= 0 ? count : 'multiple'} elements — add '>> nth=N' to pick one`,\n );\n }\n const count = await this.countMatches(loc);\n const reason =\n count === 0\n ? 'no matching element on the page'\n : `${count} match(es) present but none became visible`;\n throw new Error(\n `Target not resolvable: ${loc.raw} — ${reason} within ${timeoutMs}ms on ${this.page.url()} (${firstLine(msg)})`,\n );\n }\n await locator.scrollIntoViewIfNeeded().catch(() => {});\n // Layout stability: two identical geometry samples one frame apart.\n const deadline = Date.now() + timeoutMs;\n let prev: string | null = null;\n while (Date.now() < deadline) {\n const box = await locator.boundingBox();\n const sig = box ? `${box.x},${box.y},${box.width},${box.height}` : null;\n if (sig && sig === prev) break;\n prev = sig;\n await this.nextFrame();\n }\n const info = await this.measure(locator, loc);\n if (!info) throw new Error(`Target disappeared while measuring: ${loc.raw}`);\n return info;\n }\n\n /** Wait for the page to paint one frame, bounded — a concurrent screenshot must never let this hang. */\n private async nextFrame(): Promise<void> {\n await withTimeout(\n this.page.evaluate(() => new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(r)))),\n 1500,\n ).catch(() => {});\n }\n\n async tryMeasure(loc: ParsedLocator): Promise<TargetInfo | null> {\n const locator = this.toLocator(loc);\n try {\n if (!(await locator.isVisible())) return null;\n return await this.measure(locator, loc);\n } catch {\n return null;\n }\n }\n\n private async measure(locator: Locator, loc: ParsedLocator): Promise<TargetInfo | null> {\n const tag = `ph-${++this.tagCounter}`;\n const geom = await locator\n .evaluate((el, t) => {\n el.setAttribute('data-playhead-t', t);\n const r = el.getBoundingClientRect();\n return {\n bbox: { x: r.x, y: r.y, w: r.width, h: r.height },\n scroll: { x: window.scrollX, y: window.scrollY },\n };\n }, tag)\n .catch(() => null);\n if (!geom) return null;\n // Frame-scoped elements: getBoundingClientRect is relative to the FRAME's viewport, but\n // every consumer (camera, verification pixel sampling, click coordinates) works in MAIN\n // viewport space. locator.boundingBox() is main-frame-relative — use it for position.\n if (loc.frames && loc.frames.length > 0) {\n const box = await withTimeout(locator.boundingBox(), 3000).catch(() => null);\n if (box) geom.bbox = { x: box.x, y: box.y, w: box.width, h: box.height };\n }\n\n let role: string | null = null;\n let name: string | null = null;\n try {\n const evalRes = (await withTimeout(\n this.cdp.send('Runtime.evaluate', {\n expression: `document.querySelector('[data-playhead-t=\"${tag}\"]')`,\n }),\n 4000,\n )) as { result: { objectId?: string } };\n if (evalRes.result.objectId) {\n const desc = (await withTimeout(\n this.cdp.send('DOM.describeNode', { objectId: evalRes.result.objectId }),\n 4000,\n )) as { node: { backendNodeId: number } };\n const ax = (await withTimeout(\n this.cdp.send('Accessibility.getPartialAXTree', {\n backendNodeId: desc.node.backendNodeId,\n fetchRelatives: false,\n }),\n 4000,\n )) as { nodes: { role?: { value?: string }; name?: { value?: string }; ignored?: boolean }[] };\n const node = ax.nodes?.[0];\n if (node && !node.ignored) {\n role = node.role?.value ?? null;\n name = node.name?.value ?? null;\n }\n await this.cdp.send('Runtime.releaseObject', { objectId: evalRes.result.objectId }).catch(() => {});\n }\n } catch (e) {\n log.debug(`AX lookup failed for ${loc.raw}: ${(e as Error).message}`);\n }\n if (!name) {\n name = await locator.evaluate(new Function('el', `return (${FALLBACK_NAME_FN})(el)`) as (el: Element) => string | null).catch(() => null);\n }\n await locator.evaluate((el) => el.removeAttribute('data-playhead-t')).catch(() => {});\n return { role, accessibleName: name, bbox: geom.bbox, scroll: geom.scroll };\n }\n\n // ---------- input ----------\n\n cursorPos(): Point {\n return { ...this.cursor };\n }\n\n async moveCursor(to: Point, durationMs: number): Promise<CursorWaypoint[]> {\n const from = { ...this.cursor };\n const waypoints: CursorWaypoint[] = [{ x: from.x, y: from.y, t: Date.now() }];\n const stepMs = 12;\n const steps = Math.max(2, Math.round(durationMs / stepMs));\n for (let i = 1; i <= steps; i++) {\n const p = minJerk(i / steps);\n const x = from.x + (to.x - from.x) * p;\n const y = from.y + (to.y - from.y) * p;\n // Input dispatch has no Playwright timeout and a wedged renderer can block it forever.\n await withTimeout(this.page.mouse.move(x, y), INPUT_TIMEOUT_MS);\n waypoints.push({ x, y, t: Date.now() });\n if (i < steps) await sleep(stepMs);\n }\n this.cursor = { ...to };\n return waypoints;\n }\n\n async clickAt(p: Point, opts?: { double?: boolean }): Promise<{ tDown: number; tUp: number }> {\n await withTimeout(this.page.mouse.move(p.x, p.y), INPUT_TIMEOUT_MS);\n this.cursor = { ...p };\n const tDown = Date.now();\n await withTimeout(this.page.mouse.down(), INPUT_TIMEOUT_MS);\n await sleep(70);\n await withTimeout(this.page.mouse.up(), INPUT_TIMEOUT_MS);\n if (opts?.double) {\n await sleep(60);\n await withTimeout(this.page.mouse.down({ clickCount: 2 }), INPUT_TIMEOUT_MS);\n await sleep(60);\n await withTimeout(this.page.mouse.up({ clickCount: 2 }), INPUT_TIMEOUT_MS);\n }\n return { tDown, tUp: Date.now() };\n }\n\n async typeText(text: string, delayMs: number): Promise<{ tFirst: number; tLast: number }> {\n const tFirst = Date.now();\n // Budget scales with the text: the typing itself takes length × delay by design.\n await withTimeout(this.page.keyboard.type(text, { delay: delayMs }), 10_000 + text.length * delayMs * 2);\n return { tFirst, tLast: Date.now() };\n }\n\n async press(keys: string): Promise<{ tDown: number }> {\n const tDown = Date.now();\n await withTimeout(this.page.keyboard.press(keys), INPUT_TIMEOUT_MS);\n return { tDown };\n }\n\n /**\n * The REAL click: Playwright's locator.click with actionability + hit-target verification and\n * retry. The cosmetic cursor has already animated to the target; this dispatches the action\n * through the checks a raw coordinate click bypasses (a toast/sticky header drifting under\n * the point between measure and click silently redirects a coordinate click).\n */\n async actClick(loc: ParsedLocator, opts?: { double?: boolean; timeoutMs?: number }): Promise<{ tDown: number; tUp: number }> {\n const locator = this.toLocator(loc);\n const tDown = Date.now();\n if (opts?.double) await locator.dblclick({ delay: 60, timeout: opts?.timeoutMs ?? 10_000 });\n else await locator.click({ delay: 70, timeout: opts?.timeoutMs ?? 10_000 });\n return { tDown, tUp: Date.now() };\n }\n\n async selectOption(loc: ParsedLocator, value: string): Promise<void> {\n const locator = this.toLocator(loc);\n try {\n await locator.selectOption({ label: value });\n } catch {\n await locator.selectOption(value);\n }\n // Leave the page CLEAN: dismiss any native popup the interaction opened and drop focus, so\n // the next step's locators aren't fighting a lingering dropdown or :focus-visible state.\n await withTimeout(this.page.keyboard.press('Escape'), INPUT_TIMEOUT_MS).catch(() => {});\n await withTimeout(\n locator.evaluate((el) => (el as HTMLElement).blur?.()),\n 2000,\n ).catch(() => {});\n }\n\n async scrollIntoView(loc: ParsedLocator): Promise<void> {\n const locator = this.toLocator(loc);\n await withTimeout(\n locator.evaluate((el) => el.scrollIntoView({ behavior: 'smooth', block: 'center' })),\n 5000,\n );\n }\n\n async scrollBy(by: { x: number; y: number }): Promise<void> {\n await withTimeout(\n this.page.evaluate(({ x, y }) => window.scrollBy({ left: x, top: y, behavior: 'smooth' }), by),\n 5000,\n );\n }\n\n async waitForScrollSettle(timeoutMs: number): Promise<void> {\n const deadline = Date.now() + timeoutMs;\n let prev = Number.NaN;\n let stable = 0;\n while (Date.now() < deadline) {\n // Bound the evaluate itself: the outer deadline is only consulted between iterations, so a\n // single evaluate blocked by a busy main thread would otherwise blow straight past it.\n const y = await withTimeout(this.page.evaluate(() => window.scrollY), 1500).catch(() => prev);\n if (y === prev) {\n if (++stable >= 2) return;\n } else {\n stable = 0;\n prev = y;\n }\n await sleep(60);\n }\n }\n\n async expectState(\n loc: ParsedLocator,\n opts: { visible?: boolean; text?: string; count?: number },\n timeoutMs: number,\n ): Promise<void> {\n const locator = this.toLocator(loc);\n const deadline = Date.now() + timeoutMs;\n let lastErr = 'condition not met';\n while (Date.now() < deadline) {\n try {\n if (opts.count !== undefined) {\n const n = await locator.count();\n if (n === opts.count) return;\n lastErr = `expected ${opts.count} match(es), found ${n}`;\n await sleep(100);\n continue;\n }\n const visible = await locator.first().isVisible();\n if (opts.visible !== undefined && visible !== opts.visible) {\n lastErr = `expected visible=${opts.visible}, got ${visible}`;\n } else if (opts.text !== undefined) {\n const content = visible ? await locator.first().innerText() : '';\n if (!content.includes(opts.text)) {\n lastErr = `expected text to include \"${opts.text}\"`;\n } else {\n return;\n }\n } else {\n return;\n }\n } catch (e) {\n lastErr = (e as Error).message;\n }\n await sleep(100);\n }\n throw new Error(`expect failed for ${loc.raw}: ${lastErr}`);\n }\n\n // ---------- settling ----------\n\n /** Open requests → their start time. Long-lived streams (HMR sockets, SSE, long-polls) stop\n * counting after LONG_REQUEST_MS so a dev server can't pin the settle at its cap forever. */\n private pending = new Map<unknown, number>();\n private lastNetActivity = 0;\n private netTrackingInstalled = false;\n\n private installNetTracking(): void {\n if (this.netTrackingInstalled) return;\n this.netTrackingInstalled = true;\n this.lastNetActivity = Date.now();\n const IGNORED_TYPES = new Set(['eventsource', 'websocket', 'ping']);\n this.page.on('request', (req) => {\n if (IGNORED_TYPES.has(req.resourceType())) return;\n this.pending.set(req, Date.now());\n this.lastNetActivity = Date.now();\n });\n const done = (req: unknown) => {\n if (this.pending.delete(req)) this.lastNetActivity = Date.now();\n };\n this.page.on('requestfinished', done);\n this.page.on('requestfailed', done);\n }\n\n private static readonly LONG_REQUEST_MS = 2000;\n\n async settle(opts: { idleMs: number; capMs: number }): Promise<void> {\n this.installNetTracking();\n const start = Date.now();\n // Network idle — counting only requests younger than LONG_REQUEST_MS, so persistent\n // streams don't hold the gate.\n let capped = true;\n while (Date.now() - start < opts.capMs) {\n const now = Date.now();\n let inflight = 0;\n for (const t of this.pending.values()) {\n if (now - t < PlaywrightDriver.LONG_REQUEST_MS) inflight += 1;\n }\n if (inflight === 0 && now - this.lastNetActivity >= opts.idleMs) {\n capped = false;\n break;\n }\n await sleep(30);\n }\n if (capped) log.debug(`settle hit its ${opts.capMs}ms cap — footage may include in-flight loading`);\n // Real quiescence: no DOM mutations for 250ms AND no running finite animations (infinite\n // spinners are excluded — they'd block forever and their looping is the state, not a\n // transition). Bounded: a busy page costs at most ~1.8s here.\n await withTimeout(\n this.page.evaluate(\n () =>\n new Promise<void>((resolve) => {\n const done = () => {\n obs.disconnect();\n resolve();\n };\n let timer: ReturnType<typeof setTimeout>;\n const arm = () => {\n clearTimeout(timer);\n timer = setTimeout(() => {\n const running = (document.getAnimations?.() ?? []).filter((a) => {\n const t = a.effect?.getTiming?.();\n return a.playState === 'running' && t && t.iterations !== Infinity;\n });\n if (running.length === 0) done();\n else arm();\n }, 250);\n };\n const obs = new MutationObserver(() => arm());\n obs.observe(document.documentElement, { subtree: true, childList: true, attributes: true, characterData: true });\n arm();\n setTimeout(done, 1500); // hard floor: never block longer than this\n }),\n ),\n 1800,\n ).catch(() => {});\n // Final paint flush.\n await this.nextFrame();\n }\n\n async saveStorageState(path: string): Promise<void> {\n await this.context.storageState({ path });\n }\n\n // ---------- masking ----------\n\n /**\n * Install CSS-expressible mask rules for continuous in-page tagging (see MASK_INIT_SCRIPT).\n * Rules that can't be expressed as CSS (role/label/text) return false and stay Node-tagged.\n */\n async installMaskRules(rules: MaskInstruction[]): Promise<void> {\n const cssRules = rules\n .map((r) => ({ css: maskRuleToCss(r.loc), style: r.style }))\n .filter((r): r is { css: string; style: 'solid' | 'blur' } => r.css !== null);\n if (cssRules.length === 0) return;\n const payload = JSON.stringify(cssRules);\n // Init script → future documents (navigations); evaluate → the current one.\n await this.page.addInitScript(`window.__playheadMaskCssRules = ${payload};`);\n await withTimeout(\n this.page.evaluate((json) => ((window as any).__playheadMaskCssRules = JSON.parse(json)), payload),\n 3000,\n ).catch(() => {});\n }\n\n async applyMasks(\n rules: MaskInstruction[],\n ): Promise<{ style: 'solid' | 'blur'; x: number; y: number; w: number; h: number }[]> {\n const tagged: { style: 'solid' | 'blur'; x: number; y: number; w: number; h: number }[] = [];\n for (const rule of rules) {\n const locator = this.toLocator(rule.loc);\n // .all() (not a single-match locator) so rules matching many elements — e.g. every API-key\n // cell — are each tagged and measured, without tripping strict-mode.\n const all = await locator.all().catch(() => [] as Locator[]);\n for (const el of all) {\n const box = await el\n .evaluate((node, style) => {\n node.setAttribute('data-playhead-mask', style);\n const r = (node as HTMLElement).getBoundingClientRect();\n return { x: r.x, y: r.y, w: r.width, h: r.height };\n }, rule.style)\n .catch(() => null);\n if (box && box.w > 0 && box.h > 0) tagged.push({ style: rule.style, ...box });\n }\n }\n return tagged;\n }\n\n async setTypingMask(loc: ParsedLocator | null): Promise<void> {\n if (loc) {\n this.typingMaskLoc = loc;\n const locator = this.toLocator(loc);\n await locator.evaluate((el) => el.setAttribute('data-playhead-mask', 'solid')).catch(() => {});\n } else if (this.typingMaskLoc) {\n const locator = this.toLocator(this.typingMaskLoc);\n await locator.evaluate((el) => el.removeAttribute('data-playhead-mask')).catch(() => {});\n this.typingMaskLoc = null;\n }\n }\n\n // ---------- frame capture ----------\n //\n // Headless Chromium's CDP screencast is hard-locked to CSS-pixel resolution and ignores\n // deviceScaleFactor, so a paced Page.captureScreenshot loop with clip.scale is what actually\n // yields 2x frames (the zoom headroom the camera planner needs).\n\n async startCapture(onFrame: (f: ScreencastFrame) => void, opts: ScreencastOptions): Promise<void> {\n this.captureOnFrame = onFrame;\n this.captureOpts = opts;\n this.captureActive = true;\n const intervalMs = 1000 / opts.fps;\n this.captureLoop = (async () => {\n while (this.captureActive) {\n const started = Date.now();\n await this.grabFrame();\n const elapsed = Date.now() - started;\n if (elapsed < intervalMs) await sleep(intervalMs - elapsed);\n }\n })();\n }\n\n /** Grab a frame, coalescing on any in-flight grab (so callers can await the current one). */\n private grabFrame(): Promise<void> {\n if (this.inflightGrab) return this.inflightGrab;\n this.inflightGrab = this.doGrab().finally(() => {\n this.inflightGrab = null;\n });\n return this.inflightGrab;\n }\n\n private grabFailures = 0;\n\n private async doGrab(): Promise<void> {\n if (!this.captureOpts || !this.captureOnFrame) return;\n try {\n const opts = this.captureOpts;\n const vp = this.page.viewportSize() ?? { width: 1280, height: 720 };\n // The screenshot clip is in PAGE coordinates, so it must track the current scroll offset;\n // a fixed {0,0} clip captures document-top (scrolled out of view) as blank once the page\n // scrolls. Clipping to [scrollX, scrollY, vp] captures exactly the visible viewport, which\n // is also the space the event bounding boxes live in. Read the offset via getLayoutMetrics\n // (a native CDP call) rather than page JS, so it never contends with the page thread and\n // stall the capture loop during navigation.\n const scroll = await this.readScroll();\n // 1.5s budget: a stall costs one frame, not eighty. (Was 4s — during navigations that\n // produced measured 4-second frame voids at exactly the action beat.)\n const shot = (await withTimeout(\n this.captureCdp.send('Page.captureScreenshot', {\n format: opts.format,\n quality: opts.quality,\n clip: { x: scroll.x, y: scroll.y, width: vp.width, height: vp.height, scale: opts.scale },\n captureBeyondViewport: false,\n }),\n 1500,\n )) as { data: string };\n const tNodeMs = Date.now();\n this.lastFrameNodeMs = tNodeMs;\n this.grabFailures = 0;\n this.captureOnFrame({ data: Buffer.from(shot.data, 'base64'), tNodeMs });\n } catch {\n // withTimeout abandons but cannot cancel the CDP send, and Chromium serves a session's\n // sends IN ORDER — so a wedged screenshot head-of-line blocks every later grab on this\n // session. After consecutive failures, tear the session down and start a fresh one.\n this.grabFailures += 1;\n if (this.grabFailures >= 2) {\n try {\n await this.captureCdp.detach().catch(() => {});\n this.captureCdp = await this.context.newCDPSession(this.page);\n log.warn('capture: recreated CDP session after stalled screenshots');\n this.grabFailures = 0;\n } catch {\n /* context mid-navigation — next grab retries */\n }\n }\n }\n }\n\n private async readScroll(): Promise<{ x: number; y: number }> {\n try {\n const m = (await withTimeout(this.captureCdp.send('Page.getLayoutMetrics'), 1500)) as {\n cssVisualViewport?: { pageX?: number; pageY?: number };\n visualViewport?: { pageX?: number; pageY?: number };\n };\n const vv = m.cssVisualViewport ?? m.visualViewport;\n return { x: Math.round(vv?.pageX ?? 0), y: Math.round(vv?.pageY ?? 0) };\n } catch {\n return { x: 0, y: 0 };\n }\n }\n\n async stopCapture(): Promise<void> {\n this.captureActive = false;\n await this.captureLoop?.catch(() => {});\n this.captureLoop = null;\n }\n\n lastFrameAt(): number {\n return this.lastFrameNodeMs;\n }\n\n async captureNow(): Promise<void> {\n // Wait out any in-flight grab (it may predate the action), then force a guaranteed fresh one\n // that reflects the settled post-action state. Never gives up early under load.\n if (this.inflightGrab) await this.inflightGrab.catch(() => {});\n await this.grabFrame();\n }\n}\n\nfunction toPw(m: TextMatch): string | RegExp {\n if ('exact' in m) return m.exact;\n if ('substring' in m) return m.substring;\n return new RegExp(m.regex.source, m.regex.flags);\n}\n\nfunction isExact(m: TextMatch): boolean {\n return 'exact' in m;\n}\n\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n\n/** CSS selector for a mask rule when the locator engine is CSS-expressible; null otherwise. */\nfunction maskRuleToCss(loc: ParsedLocator): string | null {\n const b = loc.base;\n if (b.kind === 'css') return b.selector;\n if (b.kind === 'testid') return `[data-testid=${JSON.stringify(b.value)}]`;\n return null;\n}\n\nfunction firstLine(s: string): string {\n const line = s.split('\\n')[0] ?? '';\n return line.length > 160 ? `${line.slice(0, 159)}…` : line;\n}\n\n/** Reject if a promise (typically a CDP send) doesn't settle in time, so a stalled call can't freeze the pipeline. */\nfunction withTimeout<T>(p: Promise<T>, ms: number): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => reject(new Error(`operation timed out after ${ms}ms`)), ms);\n p.then(\n (v) => {\n clearTimeout(timer);\n resolve(v);\n },\n (e) => {\n clearTimeout(timer);\n reject(e);\n },\n );\n });\n}\n","import { createHash } from 'node:crypto';\nimport { createReadStream } from 'node:fs';\n\nexport function sha256Json(value: unknown): string {\n return createHash('sha256').update(JSON.stringify(value)).digest('hex');\n}\n\nexport function sha256File(path: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const hash = createHash('sha256');\n createReadStream(path)\n .on('data', (d) => hash.update(d))\n .on('end', () => resolve(hash.digest('hex')))\n .on('error', reject);\n });\n}\n","import { createRequire } from 'node:module';\n\n/** The ONE version source: package.json. Bundle manifests, the CLI, the MCP server, and\n * verdict provenance all read this — they can never disagree with the installed package. */\nexport const PLAYHEAD_VERSION: string = (\n createRequire(import.meta.url)('../../package.json') as { version: string }\n).version;\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport sharp from 'sharp';\nimport type { Spec } from '../spec/schema.js';\nimport type { EventLog } from '../capture/events.js';\nimport type { BundleManifest, FrameIndexEntry, MaskSample } from './types.js';\nimport { sha256Json } from './hash.js';\nimport { PLAYHEAD_VERSION } from '../shared/version.js';\n\n\nexport class BundleWriter {\n private frames: FrameIndexEntry[] = [];\n private pendingWrites: Promise<unknown>[] = [];\n private maskSamples: MaskSample[] = [];\n private counter = 0;\n private ready: Promise<void>;\n\n constructor(\n private readonly dir: string,\n private readonly captureFormat: 'jpeg' | 'png',\n ) {\n this.ready = mkdir(join(dir, 'frames'), { recursive: true }).then(() => {});\n }\n\n /** Queue a frame write. `t` is capture-relative ms. */\n addFrame(data: Buffer, t: number): void {\n this.counter += 1;\n const name = `${String(this.counter).padStart(6, '0')}.${this.captureFormat === 'jpeg' ? 'jpg' : 'png'}`;\n this.frames.push({ f: name, t: round1(t) });\n this.pendingWrites.push(\n this.ready.then(() => writeFile(join(this.dir, 'frames', name), data)),\n );\n }\n\n addMaskSample(sample: MaskSample): void {\n this.maskSamples.push(sample);\n }\n\n frameCount(): number {\n return this.counter;\n }\n\n async finish(meta: {\n spec: Spec;\n events: EventLog;\n appUrl: string;\n viewport: { w: number; h: number };\n dpr: number;\n clockOffsetMs: number;\n durationMs: number;\n partial?: boolean;\n failure?: { stepRef: string; message: string };\n }): Promise<BundleManifest> {\n await this.ready;\n await Promise.all(this.pendingWrites);\n this.frames.sort((a, b) => a.t - b.t);\n\n // Actual frame pixel size is the source of truth for frame-space scale.\n let frameW = meta.viewport.w * meta.dpr;\n let frameH = meta.viewport.h * meta.dpr;\n const first = this.frames[0];\n if (first) {\n const info = await sharp(join(this.dir, 'frames', first.f)).metadata();\n if (info.width && info.height) {\n frameW = info.width;\n frameH = info.height;\n }\n }\n\n const manifest: BundleManifest = {\n schema: 'playhead/bundle@1',\n playheadVersion: PLAYHEAD_VERSION,\n specHash: sha256Json(meta.spec),\n appUrl: meta.appUrl,\n viewport: meta.viewport,\n dpr: meta.dpr,\n frameW,\n frameH,\n clockOffsetMs: meta.clockOffsetMs,\n frameCount: this.frames.length,\n durationMs: round1(meta.durationMs),\n createdAtIso: new Date().toISOString(),\n captureFormat: this.captureFormat,\n hashes: {\n events: sha256Json(meta.events),\n framesIndex: sha256Json(this.frames),\n },\n ...(meta.partial ? { partial: true } : {}),\n ...(meta.failure ? { failure: meta.failure } : {}),\n };\n\n await Promise.all([\n writeFile(join(this.dir, 'frames', 'index.json'), JSON.stringify(this.frames)),\n writeFile(join(this.dir, 'events.json'), JSON.stringify(meta.events, null, 2)),\n writeFile(join(this.dir, 'masks.json'), JSON.stringify(this.maskSamples, null, 2)),\n writeFile(join(this.dir, 'spec.resolved.json'), JSON.stringify(meta.spec, null, 2)),\n writeFile(join(this.dir, 'manifest.json'), JSON.stringify(manifest, null, 2)),\n ]);\n return manifest;\n }\n}\n\nfunction round1(n: number): number {\n return Math.round(n * 10) / 10;\n}\n","/** Axis-aligned rectangle. Space is documented at each use site (viewport CSS px, frame px, or output px). */\nexport interface Rect {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\nexport interface Point {\n x: number;\n y: number;\n}\n\nexport function rectCenter(r: Rect): Point {\n return { x: r.x + r.w / 2, y: r.y + r.h / 2 };\n}\n\nexport function rectUnion(a: Rect, b: Rect): Rect {\n const x = Math.min(a.x, b.x);\n const y = Math.min(a.y, b.y);\n return {\n x,\n y,\n w: Math.max(a.x + a.w, b.x + b.w) - x,\n h: Math.max(a.y + a.h, b.y + b.h) - y,\n };\n}\n\nexport function padRect(r: Rect, pad: number): Rect {\n return { x: r.x - pad, y: r.y - pad, w: r.w + pad * 2, h: r.h + pad * 2 };\n}\n\n/** True when `inner` lies fully inside `outer`, with an optional margin inside `outer`. */\nexport function rectContains(outer: Rect, inner: Rect, margin = 0): boolean {\n return (\n inner.x >= outer.x + margin &&\n inner.y >= outer.y + margin &&\n inner.x + inner.w <= outer.x + outer.w - margin &&\n inner.y + inner.h <= outer.y + outer.h - margin\n );\n}\n\nexport function clamp(v: number, min: number, max: number): number {\n return v < min ? min : v > max ? max : v;\n}\n\nexport function lerp(a: number, b: number, t: number): number {\n return a + (b - a) * t;\n}\n\nexport function dist(a: Point, b: Point): number {\n return Math.hypot(a.x - b.x, a.y - b.y);\n}\n\n/**\n * Camera state on the source viewport plane. The visible window always has the\n * OUTPUT aspect ratio (width-anchored): zoom=1 shows the full viewport width,\n * with height vpW/zoom/outAspect — the camera pans vertically over pages taller\n * than 16:9 rather than distorting them.\n */\nexport interface CameraState {\n cx: number;\n cy: number;\n zoom: number;\n}\n\nexport interface CameraPlane {\n vpW: number;\n vpH: number;\n outW: number;\n outH: number;\n}\n\n/** The viewport-space rect visible at a camera state (output-aspect, width-anchored). */\nexport function visibleRect(cam: CameraState, plane: CameraPlane): Rect {\n const w = plane.vpW / cam.zoom;\n const h = (w * plane.outH) / plane.outW;\n return { x: cam.cx - w / 2, y: cam.cy - h / 2, w, h };\n}\n\n/** Minimum zoom that keeps the visible window inside a page of this height. */\nexport function minZoom(plane: CameraPlane): number {\n return Math.max(1, plane.vpW / ((plane.vpH * plane.outW) / plane.outH));\n}\n\n/** Clamp a camera so its visible rect stays inside the viewport. */\nexport function clampCamera(cam: CameraState, plane: CameraPlane): CameraState {\n const zoom = Math.max(cam.zoom, minZoom(plane));\n const w = plane.vpW / zoom;\n const h = (w * plane.outH) / plane.outW;\n return {\n zoom,\n cx: clamp(cam.cx, w / 2, plane.vpW - w / 2),\n cy: clamp(cam.cy, h / 2, plane.vpH - h / 2),\n };\n}\n\n/** Project a viewport-space rect into output space given a camera state. */\nexport function projectRect(r: Rect, cam: CameraState, plane: CameraPlane): Rect {\n const vis = visibleRect(cam, plane);\n const s = plane.outW / vis.w;\n return { x: (r.x - vis.x) * s, y: (r.y - vis.y) * s, w: r.w * s, h: r.h * s };\n}\n\n/** Project a viewport-space point into output space given a camera state. */\nexport function projectPoint(p: Point, cam: CameraState, plane: CameraPlane): Point {\n const vis = visibleRect(cam, plane);\n const s = plane.outW / vis.w;\n return { x: (p.x - vis.x) * s, y: (p.y - vis.y) * s };\n}\n","/**\n * Typed exit codes — a CI pipeline must be able to tell WHICH kind of red this is:\n *\n * 0 pass — rendered and publishable\n * 1 flow failure — the APP broke the flow (locator gone, expect failed, step timeout);\n * a partial bundle + failure clip exist\n * 2 quality fail — the flow ran but the video failed verification (framing, captions, audio)\n * 3 infra failure — environment problems (browser/ffmpeg missing, launch failed)\n * 4 usage error — bad spec / bad arguments\n *\n * A test tool that can't distinguish \"your app is broken\" from \"the video is ugly\" from\n * \"the runner is misconfigured\" gets `|| true`'d. This is the contract that prevents that.\n */\nexport const EXIT = {\n OK: 0,\n FLOW: 1,\n QUALITY: 2,\n INFRA: 3,\n USAGE: 4,\n} as const;\n\n/** The app broke the scripted flow (capture-time step failure). */\nexport class FlowError extends Error {\n readonly exitCode = EXIT.FLOW;\n}\n\n/** Environment/tooling problem — nothing about the app or the spec. */\nexport class InfraError extends Error {\n readonly exitCode = EXIT.INFRA;\n}\n\n/** Classify an arbitrary thrown error into an exit code. SpecErrors are matched by name to\n * avoid a circular import with the spec parser. */\nexport function exitCodeFor(e: unknown): number {\n if (e && typeof e === 'object') {\n if ('exitCode' in e && typeof (e as { exitCode: unknown }).exitCode === 'number') {\n return (e as { exitCode: number }).exitCode;\n }\n if ((e as Error).name === 'SpecError' || e instanceof Object && (e as Error).constructor?.name === 'SpecError') {\n return EXIT.USAGE;\n }\n }\n return EXIT.INFRA;\n}\n","import { join } from 'node:path';\nimport type { Spec, AddressedStep } from '../spec/schema.js';\nimport { flattenSteps, resolveViewport } from '../spec/schema.js';\nimport { parseLocator } from '../spec/locators.js';\nimport type { Driver, MaskInstruction } from './driver-api.js';\nimport { PlaywrightDriver } from './playwright-driver.js';\nimport type { ActionEvent, CaptureEvent, CursorWaypoint, EventLog, TargetInfo } from './events.js';\nimport { BundleWriter } from '../bundle/writer.js';\nimport { rectCenter, clamp, dist } from '../shared/geometry.js';\nimport { log } from '../shared/log.js';\nimport { FlowError } from '../shared/exit.js';\n\nexport interface CaptureOptions {\n outDir: string;\n headless?: boolean;\n captureFormat?: 'jpeg' | 'png';\n quality?: number;\n driver?: Driver;\n /**\n * Iteration accelerator: steps BEFORE this scene run fast (no cursor choreography, no\n * filming, no events) purely to build app state; capture starts at this scene. The bundle\n * is a partial covering only the filmed scenes — for iterating on one scene, not shipping.\n */\n fromScene?: string;\n}\n\nconst SETTLE = { idleMs: 300, capMs: 5000 };\nconst TARGET_TIMEOUT_MS = 10_000;\nconst EXPECT_TIMEOUT_MS = 10_000;\nconst TYPE_DELAY_MS = 45;\n/** Hard budget for one step end-to-end (resolve + cursor + action). A step that can't finish in\n * this window is failed with its stepRef instead of hanging the whole capture. */\nconst STEP_BUDGET_MS = 45_000;\n/** Watchdog: overall capture deadline. Long specs are bounded per-step anyway; this is the\n * backstop that guarantees a capture NEVER runs unbounded (the 7-minute-hang class). */\nconst CAPTURE_DEADLINE_MS = 10 * 60_000;\n\nexport async function capture(spec: Spec, opts: CaptureOptions): Promise<{ bundleDir: string }> {\n const bundleDir = join(opts.outDir, 'capture');\n const driver = opts.driver ?? new PlaywrightDriver();\n const dpr = 2;\n const format = opts.captureFormat ?? 'jpeg';\n const writer = new BundleWriter(bundleDir, format);\n const events: CaptureEvent[] = [];\n const maskRules: MaskInstruction[] = spec.masking.map((m) => ({\n loc: parseLocator(m.target),\n style: m.style,\n }));\n\n const viewport = resolveViewport(spec);\n const settleCfg = {\n idleMs: spec.app.settle?.idleMs ?? SETTLE.idleMs,\n capMs: spec.app.settle?.capMs ?? SETTLE.capMs,\n };\n log.info(`capturing \"${spec.title}\" from ${spec.app.url}`);\n await driver.launch({\n viewport,\n dpr,\n headless: opts.headless ?? true,\n ...(spec.app.storageState ? { storageStatePath: spec.app.storageState } : {}),\n ...(spec.app.environment ? { environment: spec.app.environment } : {}),\n ...(spec.app.network ? { network: spec.app.network } : {}),\n ...(spec.app.dialogs ? { dialogs: spec.app.dialogs } : {}),\n });\n\n // Clock scaffolding lives OUTSIDE the try so the finally can finalize the bundle: a failed\n // step must never destroy the footage already captured (the failure is when video evidence\n // matters most). t0 is re-based after clock sync below.\n let t0 = Date.now();\n const rel = (nodeMs: number) => nodeMs - t0;\n const now = () => rel(Date.now());\n let clockOffsetMs = 0;\n let failure: { stepRef: string; message: string } | undefined;\n let currentStepRef = '';\n\n try {\n clockOffsetMs = await driver.measureClockOffset();\n t0 = Date.now();\n\n driver.onNavigation((url, tNode) => {\n events.push({ type: 'navigation', url, t: rel(tNode) });\n });\n\n const startFilming = () =>\n driver.startCapture((frame) => writer.addFrame(frame.data, rel(frame.tNodeMs)), {\n format,\n quality: opts.quality ?? 82,\n scale: dpr,\n // 24 requested ≈ 20-22 achieved with the screenshot loop's ~25ms capture cost; frame\n // blending at compose smooths the rest. (True 30+ needs the screencast source — planned.)\n fps: 24,\n });\n // Filming starts up-front normally, but AFTER the fast-forward pre-roll with --from-scene:\n // pre-roll steps build state and must never appear on film.\n if (!opts.fromScene) await startFilming();\n\n // Initial navigation + masks. CSS-expressible rules also go in-page for continuous tagging,\n // so elements that appear MID-step get masked the frame they appear.\n await driver.installMaskRules(maskRules);\n await driver.goto(spec.app.url);\n await applyMasksAndSample(driver, maskRules, writer, now);\n await driver.settle(settleCfg);\n if (spec.app.assertLoggedIn) {\n // Fail FAST on stale auth instead of confidently filming the login page.\n await driver\n .expectState(parseLocator(spec.app.assertLoggedIn), { visible: true }, 8000)\n .catch(() => {\n throw new Error(\n `assertLoggedIn failed: ${spec.app.assertLoggedIn} not visible — storageState stale? Re-run: playhead login ${spec.app.url}`,\n );\n });\n }\n // Guarantee PRE-first-action footage: heavy initial loads can stall the first grabs (CDP\n // contention), and a first frame that lands after the first click makes the before-state\n // unprovable — for verification and for the viewer alike.\n if (!opts.fromScene) await driver.captureNow();\n\n let steps = flattenSteps(spec);\n const totalSteps = steps.length;\n if (opts.fromScene) {\n const idx = steps.findIndex((s) => s.sceneId === opts.fromScene);\n if (idx < 0) throw new Error(`--from-scene: no scene with id \"${opts.fromScene}\" in the spec`);\n log.info(`fast-forwarding ${idx} step(s) to scene \"${opts.fromScene}\" (state only, not filmed)`);\n for (const pre of steps.slice(0, idx)) {\n currentStepRef = `${pre.sceneId}/${pre.stepIndex} (fast-forward)`;\n await fastForwardStep(driver, pre.step);\n }\n currentStepRef = '';\n steps = steps.slice(idx);\n await driver.settle(settleCfg);\n await startFilming();\n await driver.captureNow();\n }\n\n for (const addressed of steps) {\n currentStepRef = `${addressed.sceneId}/${addressed.stepIndex}`;\n if (now() > CAPTURE_DEADLINE_MS) {\n throw new Error(`capture watchdog: exceeded ${CAPTURE_DEADLINE_MS / 60000} minutes at step ${currentStepRef}`);\n }\n log.step(`${addressed.ordinal}/${totalSteps} ${describeStep(addressed)}`);\n const event = await withStepBudget(\n executeStep(driver, addressed, { rel, now }, spec.app.url),\n STEP_BUDGET_MS,\n currentStepRef,\n );\n // Re-tag masks (new DOM may match rules), then settle.\n await applyMasksAndSample(driver, maskRules, writer, now);\n await driver.settle(settleCfg);\n // A focus HINT naming a third locator (\"click here, LOOK there\") points at the step's\n // PAYOFF — waiting for it is part of settling this step. Poll briefly: the payoff often\n // appears a beat after network-idle (the app's own mutation delay), and stamping tSettled\n // before it exists would freeze the hold on pre-payoff footage.\n const focus = 'focus' in addressed.step ? addressed.step.focus : undefined;\n if (focus && focus !== 'target' && focus !== 'wide') {\n const loc = parseLocator(focus);\n for (let i = 0; i < 10 && !event.focusTarget; i++) {\n event.focusTarget = await driver.tryMeasure(loc);\n if (!event.focusTarget) await sleep(250);\n }\n if (!event.focusTarget) {\n log.warn(`${addressed.sceneId}/${addressed.stepIndex}: focus locator never appeared: ${focus}`);\n }\n }\n await ensurePostActionFrame(driver, event.tAction, rel);\n // tSettled must point at a frame that reflects the settled state (payoff included).\n // captureNow above guarantees a fresh one, so stamp after it — even instant hash-route\n // navigations whose settle returned in ~100ms then have on-film proof of their effect.\n event.tSettled = now();\n if (event.targetPre && event.locator) {\n event.targetPost = await driver.tryMeasure(parseLocator(event.locator));\n }\n if (addressed.step.action === 'type' && addressed.step.mask && event.locator) {\n const info = await driver.tryMeasure(parseLocator(event.locator));\n if (info) writer.addMaskSample({ t: now(), rects: [{ style: 'solid', ...info.bbox }] });\n }\n events.push(event);\n }\n currentStepRef = '';\n\n // Trailing beat so the final state has footage to hold on.\n await driver.settle(settleCfg);\n await driver.captureNow();\n await sleep(400);\n return { bundleDir };\n } catch (e) {\n const message = (e as Error).message;\n failure = { stepRef: currentStepRef || '(setup)', message };\n // Failure diagnostics, best-effort: where we were and what the page looked like.\n try {\n const aria = await driver.ariaSnapshot();\n const url = driver.currentUrl();\n const { writeFile } = await import('node:fs/promises');\n await writeFile(\n join(bundleDir, 'failure.json'),\n JSON.stringify({ stepRef: failure.stepRef, message, url, at: new Date().toISOString() }, null, 2),\n );\n if (aria) await writeFile(join(bundleDir, 'failure-aria.txt'), aria);\n } catch {\n /* diagnostics are best-effort */\n }\n // A capture-time failure is the APP breaking the flow — exit code 1, not an infra error.\n throw new FlowError(\n `${message}\\n (partial bundle with ${writer.frameCount()} frames saved to ${bundleDir} — failure.json has the details)`,\n );\n } finally {\n // Finalize the bundle EVEN ON FAILURE: frames/index.json + manifest are what make the\n // captured footage openable, and a failed run's footage is the most valuable footage.\n await driver.stopCapture().catch(() => {});\n // Console/pageerror/dialog/popup evidence — what bug-repro needs and failure diagnosis reads.\n try {\n const consoleLog = driver.consoleLog();\n if (consoleLog.length > 0) {\n const { writeFile } = await import('node:fs/promises');\n await writeFile(\n join(bundleDir, 'console.json'),\n JSON.stringify(consoleLog.map((c) => ({ ...c, t: rel(c.t) })), null, 2),\n );\n }\n } catch {\n /* best-effort */\n }\n const durationMs = now();\n const eventLog: EventLog = {\n schema: 'playhead/events@1',\n meta: {\n viewport,\n dpr,\n frameW: 0, // finalized by writer from the first frame's real dimensions\n frameH: 0,\n clockOffsetMs,\n startedAtIso: new Date(t0).toISOString(),\n durationMs,\n appUrl: spec.app.url,\n },\n events,\n };\n try {\n const manifest = await writer.finish({\n spec,\n events: eventLog,\n appUrl: spec.app.url,\n viewport,\n dpr,\n clockOffsetMs,\n durationMs,\n ...(failure ? { partial: true, failure } : {}),\n });\n if (!failure) {\n log.ok(`bundle: ${manifest.frameCount} frames, ${(durationMs / 1000).toFixed(1)}s → ${bundleDir}`);\n } else {\n log.warn(`partial bundle: ${manifest.frameCount} frames up to ${failure.stepRef} → ${bundleDir}`);\n }\n } catch (finishErr) {\n log.warn(`could not finalize bundle: ${(finishErr as Error).message}`);\n }\n await driver.close();\n }\n}\n\n/** Advance app state with no filming, no cursor choreography, minimal waits (fast-forward\n * pre-roll for --from-scene). Blind `wait: ms` sleeps are skipped; expects are best-effort. */\nasync function fastForwardStep(driver: Driver, step: import('../spec/schema.js').Step): Promise<void> {\n const T = step.timeout ?? 8000;\n switch (step.action) {\n case 'goto':\n await driver.goto(step.url);\n break;\n case 'click':\n case 'dblclick': {\n const t = await driver.resolveTarget(parseLocator(step.target), T);\n await driver.clickAt(rectCenter(t.bbox), { double: step.action === 'dblclick' });\n break;\n }\n case 'hover':\n break; // no lasting state\n case 'type': {\n const t = await driver.resolveTarget(parseLocator(step.target), T);\n await driver.clickAt(rectCenter(t.bbox));\n await driver.typeText(step.text, 0);\n break;\n }\n case 'press':\n await driver.press(step.keys);\n break;\n case 'select':\n await driver.selectOption(parseLocator(step.target), step.value);\n break;\n case 'scroll':\n if (step.target) await driver.scrollIntoView(parseLocator(step.target));\n else if (step.by) await driver.scrollBy(step.by);\n await driver.waitForScrollSettle(1500);\n break;\n case 'expect':\n await driver\n .expectState(parseLocator(step.target), { ...(step.visible !== undefined ? { visible: step.visible } : {}) }, T)\n .catch(() => {});\n break;\n case 'wait':\n if (step.for) {\n await driver.expectState(parseLocator(step.for), { visible: step.state !== 'hidden' }, T).catch(() => {});\n }\n break;\n }\n await driver.settle({ idleMs: 200, capMs: 2500 });\n}\n\n/** Fail a step with its ref when it exceeds the budget, instead of hanging the capture. */\nfunction withStepBudget<T>(p: Promise<T>, ms: number, stepRef: string): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(\n () => reject(new Error(`step ${stepRef} exceeded its ${ms / 1000}s budget`)),\n ms,\n );\n p.then(\n (v) => { clearTimeout(timer); resolve(v); },\n (e) => { clearTimeout(timer); reject(e); },\n );\n });\n}\n\ninterface Clock {\n rel: (nodeMs: number) => number;\n now: () => number;\n}\n\nasync function executeStep(driver: Driver, addressed: AddressedStep, clock: Clock, appUrl: string): Promise<ActionEvent> {\n const { step, sceneId, stepIndex, ordinal } = addressed;\n const base: ActionEvent = {\n type: 'action',\n kind: step.action,\n sceneId,\n stepIndex,\n ordinal,\n cursorPath: [],\n tStart: clock.now(),\n tAction: 0,\n tActionEnd: 0,\n tSettled: 0,\n ...(step.caption ? { caption: step.caption } : {}),\n ...(step.narration ? { narration: step.narration } : {}),\n ...(step.shot ? { shot: step.shot } : {}),\n ...('focus' in step && step.focus ? { focus: step.focus } : {}),\n };\n // Per-step override for target-resolution / expectation budgets.\n const budgetMs = step.timeout ?? TARGET_TIMEOUT_MS;\n\n switch (step.action) {\n case 'goto': {\n // Relative URLs resolve against app.url, so a spec can say `goto: /deals` and be pointed\n // at any environment by changing one line.\n const url = new URL(step.url, appUrl).href;\n base.locator = url;\n base.tAction = clock.now();\n await driver.goto(url);\n base.tActionEnd = clock.now();\n return base;\n }\n case 'click':\n case 'dblclick':\n case 'hover': {\n base.locator = step.target;\n const loc = parseLocator(step.target);\n const pre = await driver.resolveTarget(loc, budgetMs);\n base.targetPre = pre;\n base.cursorPath = await moveToTarget(driver, pre, clock);\n if (step.action === 'hover') {\n base.tAction = clock.now();\n base.tActionEnd = base.tAction;\n } else {\n // Cosmetic cursor is already on the target; the ACTION goes through locator.click so\n // actionability + hit-target verification + retry come for free (a raw coordinate\n // click is silently redirected by anything drifting under the point).\n const { tDown, tUp } = await driver.actClick(loc, {\n double: step.action === 'dblclick',\n timeoutMs: budgetMs,\n });\n base.tAction = clock.rel(tDown);\n base.tActionEnd = clock.rel(tUp);\n }\n return base;\n }\n case 'type': {\n base.locator = step.target;\n const loc = parseLocator(step.target);\n const pre = await driver.resolveTarget(loc, budgetMs);\n base.targetPre = pre;\n base.cursorPath = await moveToTarget(driver, pre, clock);\n await driver.actClick(loc, { timeoutMs: budgetMs });\n if (step.mask) {\n // Tag before any keystroke lands; the overlay stays for the rest of the capture.\n await driver.setTypingMask(loc);\n }\n const { tFirst, tLast } = await driver.typeText(step.text, TYPE_DELAY_MS);\n base.tAction = clock.rel(tFirst);\n base.tActionEnd = clock.rel(tLast);\n base.masked = step.mask;\n base.typedText = step.mask ? '•'.repeat(Math.min(step.text.length, 8)) : step.text;\n return base;\n }\n case 'press': {\n base.locator = step.keys;\n const { tDown } = await driver.press(step.keys);\n base.tAction = clock.rel(tDown);\n base.tActionEnd = clock.now();\n return base;\n }\n case 'select': {\n base.locator = step.target;\n const loc = parseLocator(step.target);\n const pre = await driver.resolveTarget(loc, budgetMs);\n base.targetPre = pre;\n base.cursorPath = await moveToTarget(driver, pre, clock);\n // No raw pre-click: it opens the native popup that nothing dismisses. selectOption\n // handles focus + change events; the cursor visit above supplies the visual beat.\n base.tAction = clock.now();\n await driver.selectOption(loc, step.value);\n base.typedText = step.value;\n base.tActionEnd = clock.now();\n return base;\n }\n case 'scroll': {\n base.tAction = clock.now();\n if (step.target) {\n base.locator = step.target;\n const loc = parseLocator(step.target);\n await driver.scrollIntoView(loc);\n await driver.waitForScrollSettle(2500); // measure only once the scroll has stopped\n base.targetPre = await driver.tryMeasure(loc);\n } else if (step.by) {\n await driver.scrollBy(step.by);\n await driver.waitForScrollSettle(2500);\n }\n base.tActionEnd = clock.now();\n return base;\n }\n case 'expect': {\n base.locator = step.target;\n const loc = parseLocator(step.target);\n await driver.expectState(\n loc,\n { ...(step.visible !== undefined ? { visible: step.visible } : {}), ...(step.text !== undefined ? { text: step.text } : {}), ...(step.count !== undefined ? { count: step.count } : {}) },\n step.timeout ?? EXPECT_TIMEOUT_MS,\n );\n base.targetPre = await driver.tryMeasure(loc);\n base.tAction = clock.now();\n base.tActionEnd = base.tAction;\n return base;\n }\n case 'wait': {\n base.tAction = clock.now();\n if (step.for) {\n // Structured wait: block on an element state instead of a blind sleep.\n base.locator = step.for;\n await driver.expectState(\n parseLocator(step.for),\n { visible: step.state !== 'hidden' },\n step.timeout ?? EXPECT_TIMEOUT_MS,\n );\n } else {\n await sleep(step.ms ?? 0);\n }\n base.tActionEnd = clock.now();\n return base;\n }\n }\n}\n\nasync function moveToTarget(driver: Driver, target: TargetInfo, clock: Clock): Promise<CursorWaypoint[]> {\n const to = rectCenter(target.bbox);\n const travel = clamp(250 + dist(driver.cursorPos(), to) * 0.5, 300, 700);\n const waypoints = await driver.moveCursor(to, travel);\n return waypoints.map((w) => ({ x: round1(w.x), y: round1(w.y), t: round1(clock.rel(w.t)) }));\n}\n\n/**\n * Guarantee a fresh frame reflecting the settled post-action state. Always captures one (not\n * only when footage looks stale): a fast hash-route navigation settles in ~100ms, and without a\n * forced post-settle frame the \"after\" sample can land on the pre-navigation paint.\n */\nasync function ensurePostActionFrame(\n driver: Driver,\n tAction: number,\n rel: (nodeMs: number) => number,\n): Promise<void> {\n await sleep(24); // let the post-action paint flush\n await driver.captureNow();\n if (rel(driver.lastFrameAt()) <= tAction) {\n for (let i = 0; i < 2 && rel(driver.lastFrameAt()) <= tAction; i++) {\n await sleep(40);\n await driver.captureNow();\n }\n if (rel(driver.lastFrameAt()) <= tAction) {\n log.warn(`no captured frame after action at t=${tAction.toFixed(0)}ms — footage may hold a stale frame`);\n }\n }\n}\n\nasync function applyMasksAndSample(\n driver: Driver,\n rules: MaskInstruction[],\n writer: BundleWriter,\n now: () => number,\n): Promise<void> {\n if (rules.length === 0) return;\n const rects = await driver.applyMasks(rules);\n if (rects.length > 0) writer.addMaskSample({ t: now(), rects });\n}\n\nfunction describeStep(a: AddressedStep): string {\n const s = a.step;\n switch (s.action) {\n case 'goto':\n return `goto ${s.url}`;\n case 'type':\n return `type into ${s.target}${s.mask ? ' (masked)' : ''}`;\n case 'press':\n return `press ${s.keys}`;\n case 'wait':\n return `wait ${s.ms}ms`;\n case 'scroll':\n return `scroll ${s.target ?? JSON.stringify(s.by)}`;\n default:\n return `${s.action} ${'target' in s ? s.target : ''}`;\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n\nfunction round1(n: number): number {\n return Math.round(n * 10) / 10;\n}\n","import { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { BundleData, BundleManifest, FrameIndexEntry, MaskSample } from './types.js';\nimport type { EventLog } from '../capture/events.js';\n\nexport async function openBundle(dir: string): Promise<BundleData> {\n const [manifestRaw, eventsRaw, framesRaw, masksRaw] = await Promise.all([\n readFile(join(dir, 'manifest.json'), 'utf8'),\n readFile(join(dir, 'events.json'), 'utf8'),\n readFile(join(dir, 'frames', 'index.json'), 'utf8'),\n readFile(join(dir, 'masks.json'), 'utf8').catch(() => '[]'),\n ]);\n const manifest = JSON.parse(manifestRaw) as BundleManifest;\n if (manifest.schema !== 'playhead/bundle@1') {\n throw new Error(`Unsupported bundle schema \"${manifest.schema}\" in ${dir}`);\n }\n const events = JSON.parse(eventsRaw) as EventLog;\n const frames = JSON.parse(framesRaw) as FrameIndexEntry[];\n const maskSamples = JSON.parse(masksRaw) as MaskSample[];\n if (frames.length === 0) throw new Error(`Bundle ${dir} contains no frames`);\n return { dir, manifest, events, frames, maskSamples };\n}\n\n/** Index of the latest frame with t ≤ tMs (hold semantics); clamps to the first frame. */\nexport function frameIndexForTime(frames: FrameIndexEntry[], tMs: number): number {\n let lo = 0;\n let hi = frames.length - 1;\n if (tMs <= frames[0]!.t) return 0;\n if (tMs >= frames[hi]!.t) return hi;\n while (lo < hi) {\n const mid = (lo + hi + 1) >> 1;\n if (frames[mid]!.t <= tMs) lo = mid;\n else hi = mid - 1;\n }\n return lo;\n}\n\nexport function framePath(bundle: BundleData, index: number): string {\n return join(bundle.dir, 'frames', bundle.frames[index]!.f);\n}\n","import { existsSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\nimport { createRequire } from 'node:module';\nimport { GlobalFonts } from '@napi-rs/canvas';\nimport type { Spec } from '../spec/schema.js';\n\nexport interface ResolvedTheme {\n name: string;\n /** Accent color for cursor ripple, badges, highlights. */\n accent: string;\n /** Title-card and letterbox background. */\n bg: string;\n bgSubtle: string;\n /** Caption card background (rgba string). */\n surface: string;\n onSurface: string;\n onSurfaceDim: string;\n fontFamily: string;\n captionFontPx: number;\n captionMinFontPx: number;\n captionMaxLines: number;\n captionPosition: 'bottom' | 'top' | 'off';\n radius: number;\n}\n\nconst DEFAULT_THEME: ResolvedTheme = {\n name: 'default',\n accent: '#5B8DEF',\n bg: '#12161f',\n bgSubtle: '#1a2029',\n surface: 'rgba(18, 22, 31, 0.92)',\n onSurface: '#ffffff',\n onSurfaceDim: 'rgba(255,255,255,0.72)',\n fontFamily: 'Inter',\n // Broadcast-subtitle scale: ~3.3% of a 1080p frame. At the old 26px the caption was the same\n // size as the app's upscaled body copy and read as part of the UI, not narration above it.\n captionFontPx: 36,\n captionMinFontPx: 28,\n captionMaxLines: 2,\n captionPosition: 'bottom',\n radius: 12,\n};\n\nexport function resolveTheme(spec: Spec): ResolvedTheme {\n return {\n ...DEFAULT_THEME,\n ...(spec.theme.accent ? { accent: spec.theme.accent } : {}),\n captionPosition: spec.theme.captions,\n };\n}\n\nlet fontsRegistered = false;\n\n/** Register bundled Inter faces so rendering is deterministic across machines. */\nexport function registerFonts(): void {\n if (fontsRegistered) return;\n fontsRegistered = true;\n const require = createRequire(import.meta.url);\n let pkgDir: string;\n try {\n pkgDir = dirname(require.resolve('@expo-google-fonts/inter/package.json'));\n } catch {\n throw new Error('Font package @expo-google-fonts/inter not found — run npm install');\n }\n const faces: [string, string][] = [\n ['400Regular/Inter_400Regular.ttf', 'Inter'],\n ['500Medium/Inter_500Medium.ttf', 'Inter Medium'],\n ['600SemiBold/Inter_600SemiBold.ttf', 'Inter SemiBold'],\n ['700Bold/Inter_700Bold.ttf', 'Inter Bold'],\n ];\n for (const [rel, family] of faces) {\n const p = join(pkgDir, rel);\n if (existsSync(p)) GlobalFonts.registerFromPath(p, family);\n }\n}\n","import type { Rect, Point, CameraState } from '../shared/geometry.js';\nimport type { BezierParams } from '../shared/easing.js';\nimport type { ResolvedTheme } from '../theme/index.js';\nimport type { ActionKind } from '../capture/events.js';\n\nexport interface OutputProfile {\n width: number;\n height: number;\n fps: number;\n /** Output-px margins content must respect; bottom includes the caption band. */\n safeArea: { top: number; right: number; bottom: number; left: number };\n zoomQuantums: number[];\n /** Minimum rendered size (output px) of a focus rect's smaller dimension. */\n minFocusPx: number;\n captionMaxWidth: number;\n /**\n * The stage: footage renders inside `content` (a matte with rounded corners, shadow, and an\n * optional browser-chrome bar above it) instead of edge-to-edge. ALL camera math — planner,\n * renderer, cursor projection, verification — runs in content space via `stageContent()`,\n * so plan and pixels can never disagree about where footage lives. Absent = full-frame.\n */\n stage?: {\n /** Output-px rect the footage is drawn into. */\n content: Rect;\n /** Height of the browser-chrome bar drawn directly above `content` (0 = none). */\n chromeH: number;\n radius: number;\n };\n}\n\n/** The rect footage renders into: the stage's content when present, else the full frame. */\nexport function stageContent(profile: OutputProfile): Rect {\n return profile.stage?.content ?? { x: 0, y: 0, w: profile.width, h: profile.height };\n}\n\n/** Compute a stage for the profile: uniform matte margins + a chrome bar, preserving the\n * content's aspect (= the capture viewport's), so camera math scales cleanly. */\nexport function withStage(profile: OutputProfile, chrome: boolean): OutputProfile {\n const { width, height } = profile;\n const marginY = Math.round(height * 0.055);\n const chromeH = chrome ? Math.round(44 * (Math.min(width, height) / 1080)) : 0;\n const contentH = height - 2 * marginY - chromeH;\n const contentW = Math.round(contentH * (width / height));\n const x = Math.round((width - contentW) / 2);\n const y = marginY + chromeH;\n return {\n ...profile,\n stage: { content: { x, y, w: contentW, h: contentH }, chromeH, radius: Math.round(14 * (Math.min(width, height) / 1080)) },\n };\n}\n\nexport const PROFILE_16x9: OutputProfile = {\n width: 1920,\n height: 1080,\n fps: 30,\n safeArea: { top: 54, right: 96, bottom: 160, left: 96 },\n zoomQuantums: [1.0, 1.15, 1.3, 1.5, 1.7, 2.0],\n minFocusPx: 110,\n captionMaxWidth: 1040,\n};\n\n/** Portrait: reserve more top/bottom for platform UI chrome; captions span most of the width. */\nexport const PROFILE_9x16: OutputProfile = {\n width: 1080,\n height: 1920,\n fps: 30,\n safeArea: { top: 230, right: 56, bottom: 320, left: 56 },\n zoomQuantums: [1.0, 1.15, 1.3, 1.5, 1.7, 2.0],\n minFocusPx: 96,\n captionMaxWidth: 980,\n};\n\nexport const PROFILE_1x1: OutputProfile = {\n width: 1080,\n height: 1080,\n fps: 30,\n safeArea: { top: 80, right: 72, bottom: 200, left: 72 },\n zoomQuantums: [1.0, 1.15, 1.3, 1.5, 1.7, 2.0],\n minFocusPx: 100,\n captionMaxWidth: 940,\n};\n\n/** Resolve the output profile for an aspect, overlaying the spec's resolution + fps. */\nexport function profileForAspect(\n aspect: '16:9' | '9:16' | '1:1',\n resolution: { w: number; h: number },\n fps: number,\n): OutputProfile {\n const base = aspect === '9:16' ? PROFILE_9x16 : aspect === '1:1' ? PROFILE_1x1 : PROFILE_16x9;\n const scaleX = resolution.w / base.width;\n const scaleY = resolution.h / base.height;\n return {\n ...base,\n width: resolution.w,\n height: resolution.h,\n fps,\n safeArea: {\n top: Math.round(base.safeArea.top * scaleY),\n bottom: Math.round(base.safeArea.bottom * scaleY),\n left: Math.round(base.safeArea.left * scaleX),\n right: Math.round(base.safeArea.right * scaleX),\n },\n captionMaxWidth: Math.round(base.captionMaxWidth * scaleX),\n };\n}\n\nexport type TimeSegment =\n | { kind: 'source'; outStart: number; outEnd: number; srcStart: number; srcEnd: number }\n | { kind: 'freeze'; outStart: number; outEnd: number; srcAt: number }\n | { kind: 'card'; outStart: number; outEnd: number; cardId: string };\n\nexport interface CameraKeyframe {\n tOut: number;\n state: CameraState;\n /** Ease applied travelling from the previous keyframe to this one. */\n ease: BezierParams;\n}\n\nexport interface CursorSegment {\n tStart: number;\n tEnd: number;\n /** Arc-length-resampled polyline in viewport space. */\n path: Point[];\n clickAtEnd: boolean;\n}\n\nexport interface ClickRipple {\n tOut: number;\n /** Viewport space. */\n x: number;\n y: number;\n}\n\nexport interface CaptionOverlay {\n kind: 'caption';\n stepRef: string;\n ordinal: number;\n totalSteps: number;\n /** Whether to draw the numbered step badge (off for demo/release/social/factual styles). */\n showBadge: boolean;\n text: string;\n lines: string[];\n fontPx: number;\n /** Output-space card rect as rendered. */\n box: Rect;\n tStart: number;\n tEnd: number;\n shrunk: boolean;\n truncated: boolean;\n}\n\nexport interface TitleCardOverlay {\n kind: 'titleCard';\n cardId: string;\n title: string;\n subtitle?: string;\n tStart: number;\n tEnd: number;\n}\n\nexport interface DipTransition {\n kind: 'dip';\n tStart: number;\n tEnd: number;\n /** 'in' fades FROM the theme background into footage (post-title); 'out' fades footage\n * INTO the background (pre-end-card). Default 'in'. */\n direction?: 'in' | 'out';\n}\n\n/**\n * Act→react camera windows for a step that clicks one place and focuses another (\"click here,\n * LOOK there\"): the camera frames the action target around the beat, then hands off to the\n * focused payoff for the settled hold. Shared by the planner (to emit the handoff) and the\n * verifier (to assert each rect during ITS window) so plan and checks agree by construction.\n * Returns null when the step has no handoff (single rect, or too little hold to travel in).\n */\nexport function actReactWindows(step: StepMapEntry): {\n act: { rect: Rect; from: number; to: number };\n react: { rect: Rect; from: number; to: number };\n} | null {\n if (!step.focusRectVp || !step.targetRectVp) return null;\n if (step.focus === 'target' || step.focus === 'wide') return null;\n if (step.outEnd - step.outBeat < 1600) return null; // not enough hold to travel and settle\n return {\n act: { rect: step.targetRectVp, from: step.outBeat - 60, to: step.outBeat + 400 },\n react: { rect: step.focusRectVp, from: step.outBeat + 1100, to: step.outEnd },\n };\n}\n\n/** A persistent elapsed-time readout (bug-repro evidence). Rendered against the output clock. */\nexport interface ElapsedClockOverlay {\n kind: 'elapsedClock';\n tStart: number;\n tEnd: number;\n /** Output ms to subtract so the clock reads 0 at the first real action, not the title card. */\n zeroAtMs: number;\n}\n\n/** A brief scene-title label at each new scene (demo/before-after narrative structure). */\nexport interface ChapterLabelOverlay {\n kind: 'chapterLabel';\n title: string;\n ordinal: number;\n tStart: number;\n tEnd: number;\n}\n\n/** Closing card for a FAILED capture: the failure clip ends on what broke and why. */\nexport interface FailureCardOverlay {\n kind: 'failureCard';\n stepRef: string;\n message: string;\n tStart: number;\n tEnd: number;\n}\n\nexport type OverlayEntry =\n | CaptionOverlay\n | TitleCardOverlay\n | DipTransition\n | ElapsedClockOverlay\n | ChapterLabelOverlay\n | FailureCardOverlay;\n\nexport interface StepMapEntry {\n stepRef: string;\n sceneId: string;\n ordinal: number;\n kind: ActionKind;\n locator?: string;\n /** True for masked type steps — their visible effect is intentionally suppressed. */\n masked?: boolean;\n /** Viewport-space target rect at action time (bboxPre), when the step had a target. */\n targetRectVp?: Rect;\n /** Camera hint from the spec: 'target' | 'wide' | a locator string. */\n focus?: string;\n /** Shot-boundary control from the spec: 'cut' | 'continue'. */\n shot?: string;\n /** Measured rect of a locator-valued focus hint at the settled moment — the payoff the\n * camera should frame instead of the action target (\"click here, look there\"). */\n focusRectVp?: Rect;\n outStart: number;\n /** Output-clock moment the action lands. */\n outBeat: number;\n outEnd: number;\n srcAction: number;\n srcSettled: number;\n}\n\nexport interface ComposeDiagnostics {\n overflows: { stepRef: string; text: string; action: 'shrunk' | 'truncated' }[];\n cameraFallbacks: string[];\n clockWarnings: string[];\n}\n\nexport interface ComposeManifest {\n schema: 'playhead/compose@1';\n profile: OutputProfile;\n viewport: { w: number; h: number };\n durationMs: number;\n totalFrames: number;\n segments: TimeSegment[];\n camera: CameraKeyframe[];\n cursor: CursorSegment[];\n ripples: ClickRipple[];\n overlays: OverlayEntry[];\n /** Cross-dissolve windows at scene boundaries: old footage (held at srcFrom) fades into new. */\n transitions?: { tStart: number; tEnd: number; srcFrom: number }[];\n steps: StepMapEntry[];\n theme: ResolvedTheme;\n diagnostics: ComposeDiagnostics;\n bundleHashes: { events: string; framesIndex: string };\n videoSha256?: string;\n /** Present when voice narration was muxed in. `clips` records where each spoken line landed\n * on the output clock, so verification can reason about voice-covered windows. */\n audio?: {\n narrated: boolean;\n provider: string;\n voice: string;\n lines: number;\n clips?: { stepRef: string; tStart: number; durMs: number }[];\n };\n}\n","import type { OutputKind } from '../spec/schema.js';\n\nexport type CaptionStyle = 'instruction' | 'factual' | 'chapter';\n\n/** How a given output kind is composed — the same capture, a different treatment. */\nexport interface KindProfile {\n kind: OutputKind;\n /** Default pacing when the spec doesn't set one. */\n pacing: 'relaxed' | 'normal' | 'brisk';\n /** Caption phrasing: instructional (\"Click X\"), factual repro (\"Step 1 — click X\"), or narrative. */\n captionStyle: CaptionStyle;\n /** Prefix each caption with its number (\"1.\", \"2.\" …). */\n numberedCaptions: boolean;\n /** Draw a running elapsed-time clock (bug evidence). */\n elapsedClock: boolean;\n /** Insert a full-frame chapter card at each new scene (demo narrative structure). */\n chapterCards: boolean;\n /** Hold on the final state this long (ms) — bug-repro dwells on the defect. */\n outroMs: number;\n /** Typed input is shown as evidence even in fields that look sensitive (repro needs the values). */\n showTypedInput: boolean;\n /** Composition-driven camera emphasis + click spotlights. Off for bug-repro, which must stay\n * a literal record of the screen. */\n cameraEmphasis: boolean;\n /** Render footage on a stage (matte + rounded card + browser chrome) instead of edge-to-edge. */\n stage: boolean;\n}\n\nconst BASE: Omit<KindProfile, 'kind'> = {\n pacing: 'normal',\n captionStyle: 'instruction',\n numberedCaptions: true,\n elapsedClock: false,\n chapterCards: false,\n outroMs: 1600,\n showTypedInput: true,\n cameraEmphasis: true,\n stage: true,\n};\n\nconst PROFILES: Record<OutputKind, KindProfile> = {\n walkthrough: { kind: 'walkthrough', ...BASE },\n demo: {\n kind: 'demo',\n ...BASE,\n pacing: 'relaxed',\n captionStyle: 'chapter',\n numberedCaptions: false,\n chapterCards: true,\n outroMs: 2200,\n },\n 'bug-repro': {\n kind: 'bug-repro',\n ...BASE,\n pacing: 'normal',\n captionStyle: 'factual',\n numberedCaptions: true,\n elapsedClock: true,\n outroMs: 3000,\n // A repro is EVIDENCE: no directorial zoom, no spotlights, no matte — the literal screen.\n cameraEmphasis: false,\n stage: false,\n },\n 'before-after': { kind: 'before-after', ...BASE, pacing: 'normal', chapterCards: true, numberedCaptions: false },\n release: { kind: 'release', ...BASE, pacing: 'brisk', numberedCaptions: false, outroMs: 1400 },\n social: { kind: 'social', ...BASE, pacing: 'brisk', numberedCaptions: false, outroMs: 1400 },\n};\n\nexport function kindProfile(kind: OutputKind): KindProfile {\n return PROFILES[kind] ?? PROFILES.walkthrough;\n}\n","import type { Rect, Point } from '../shared/geometry.js';\n\n/** All event/frame times are milliseconds relative to capture start, on one normalized clock. */\n\nexport interface TargetInfo {\n role: string | null;\n accessibleName: string | null;\n /** Viewport-relative (client) CSS px — exactly the space the captured frames show. */\n bbox: Rect;\n /** Window scroll offsets at measure time, CSS px. */\n scroll: Point;\n}\n\nexport interface CursorWaypoint {\n x: number;\n y: number;\n t: number;\n}\n\nexport type ActionKind =\n | 'goto'\n | 'click'\n | 'dblclick'\n | 'hover'\n | 'type'\n | 'press'\n | 'select'\n | 'scroll'\n | 'expect'\n | 'wait';\n\nexport interface ActionEvent {\n type: 'action';\n kind: ActionKind;\n sceneId: string;\n stepIndex: number;\n /** Global 1-based step number across the whole spec. */\n ordinal: number;\n locator?: string;\n targetPre?: TargetInfo | null;\n targetPost?: TargetInfo | null;\n cursorPath: CursorWaypoint[];\n /** Redacted to bullets when masked — the real string never enters any artifact. */\n typedText?: string;\n masked?: boolean;\n /** Caption override from the spec, carried through for the compositor. */\n caption?: string;\n /** Spoken-line override from the spec (TTS narration), carried as a record — the live spec\n * wins at compose time. */\n narration?: string;\n /** Camera-shot boundary control from the spec ('cut' | 'continue'). */\n shot?: string;\n /** Camera hint from the spec: 'target' | 'wide' | a locator string. */\n focus?: string;\n /** When `focus` names a locator, its measured geometry at the settled moment — the payoff\n * rect the camera should frame (\"click here, look there\"). */\n focusTarget?: TargetInfo | null;\n tStart: number;\n /** Moment the action lands (mouse-down, first keystroke, key chord). */\n tAction: number;\n /** Action fully delivered (mouse-up, last keystroke). */\n tActionEnd: number;\n /** UI settled after the action (network idle + layout stable). */\n tSettled: number;\n}\n\nexport interface NavigationEvent {\n type: 'navigation';\n url: string;\n t: number;\n}\n\nexport type CaptureEvent = ActionEvent | NavigationEvent;\n\nexport interface EventLogMeta {\n viewport: { w: number; h: number };\n dpr: number;\n /** Actual pixel dimensions of captured frames (source of truth for frame-space scale). */\n frameW: number;\n frameH: number;\n clockOffsetMs: number;\n startedAtIso: string;\n durationMs: number;\n appUrl: string;\n}\n\nexport interface EventLog {\n schema: 'playhead/events@1';\n meta: EventLogMeta;\n events: CaptureEvent[];\n}\n\nexport function actionEvents(log: EventLog): ActionEvent[] {\n return log.events.filter((e): e is ActionEvent => e.type === 'action');\n}\n\nexport function navigationEvents(log: EventLog): NavigationEvent[] {\n return log.events.filter((e): e is NavigationEvent => e.type === 'navigation');\n}\n","/** Narration placement constants, shared by the timeline (dwell fitting) and the muxer. */\n\n/** A step's spoken line starts this long after the step (and its caption) begin. */\nexport const AUDIO_LEAD_MS = 150;\n/** Silence kept after a spoken line finishes before the step is allowed to end. */\nexport const AUDIO_TAIL_MS = 450;\n","import type { EventLog, ActionEvent, ActionKind } from '../../capture/events.js';\nimport { actionEvents } from '../../capture/events.js';\nimport type { TimeSegment, StepMapEntry } from '../types.js';\nimport { AUDIO_LEAD_MS, AUDIO_TAIL_MS } from '../../audio/timing.js';\n\nexport interface PacingConfig {\n factor: number;\n titleCardMs: number;\n introMaxMs: number;\n outroMs: number;\n idleGapMaxMs: number;\n idleGapOutMs: number;\n minStepMs: number;\n maxTypeOutMs: number;\n holds: Record<ActionKind, number>;\n}\n\nexport function pacingConfig(mode: 'relaxed' | 'normal' | 'brisk', kind?: { outroMs: number }): PacingConfig {\n const factor = mode === 'relaxed' ? 1.25 : mode === 'brisk' ? 0.8 : 1;\n return {\n factor,\n titleCardMs: 2200,\n introMaxMs: 1200,\n outroMs: kind?.outroMs ?? 1600,\n idleGapMaxMs: 1500,\n idleGapOutMs: 400,\n minStepMs: 1800 * factor,\n maxTypeOutMs: 4500,\n holds: {\n goto: 1200 * factor,\n click: 600 * factor,\n dblclick: 600 * factor,\n hover: 450 * factor,\n type: 450 * factor,\n press: 450 * factor,\n select: 600 * factor,\n scroll: 350 * factor,\n expect: 800 * factor,\n wait: 150,\n },\n };\n}\n\nexport interface TimelinePlan {\n segments: TimeSegment[];\n steps: StepMapEntry[];\n durationMs: number;\n}\n\n/**\n * Build the output timeline: title card, per-step source spans with compose-time\n * pacing (idle-gap trimming, post-action freezes, min-step extension), and an\n * outro hold on the final state.\n */\nexport function buildTimeline(log: EventLog, cfg: PacingConfig, audioMs?: Map<string, number>): TimelinePlan {\n const events = actionEvents(log);\n const segments: TimeSegment[] = [];\n const steps: StepMapEntry[] = [];\n\n segments.push({ kind: 'card', outStart: 0, outEnd: cfg.titleCardMs, cardId: 'title' });\n let out = cfg.titleCardMs;\n let src = events.length > 0 ? Math.max(0, events[0]!.tStart - cfg.introMaxMs) : 0;\n\n for (const e of events) {\n // Gap between the previous settle and this step's start.\n const gap = e.tStart - src;\n if (gap > 1) {\n const outDur = gap > cfg.idleGapMaxMs ? cfg.idleGapOutMs : gap;\n segments.push({ kind: 'source', outStart: out, outEnd: out + outDur, srcStart: src, srcEnd: e.tStart });\n out += outDur;\n }\n const stepOutStart = out;\n\n // Action span at natural rate (typing capped and sped up uniformly).\n const srcEnd = Math.max(e.tSettled, e.tActionEnd, e.tStart + 1);\n const spanSrc = srcEnd - e.tStart;\n let spanOut = spanSrc;\n if (e.kind === 'type' && spanSrc > cfg.maxTypeOutMs) spanOut = cfg.maxTypeOutMs;\n segments.push({ kind: 'source', outStart: out, outEnd: out + spanOut, srcStart: e.tStart, srcEnd });\n const outBeat = out + (e.tAction - e.tStart) * (spanOut / spanSrc);\n out += spanOut;\n\n // Post-action freeze: fixed hold, extended to satisfy the minimum step duration.\n let hold = cfg.holds[e.kind];\n if (out + hold - stepOutStart < cfg.minStepMs) hold = cfg.minStepMs - (out - stepOutStart);\n // Narration-driven pacing: grow the hold so the step lasts long enough for its\n // spoken line (lead-in + speech + tail) to finish before the step ends.\n const aud = audioMs?.get(`${e.sceneId}/${e.stepIndex}`);\n if (aud && aud > 0) {\n const need = AUDIO_LEAD_MS + aud + AUDIO_TAIL_MS;\n const have = out - stepOutStart + hold;\n if (have < need) hold += need - have;\n }\n // Act→react pacing: a step whose focus hands the camera off to a payoff element needs\n // enough post-beat hold for the travel plus a settled look at the destination.\n if (e.focusTarget && e.focus && e.focus !== 'target' && e.focus !== 'wide') {\n const needAfterBeat = 2100;\n const haveAfterBeat = out + hold - outBeat;\n if (haveAfterBeat < needAfterBeat) hold += needAfterBeat - haveAfterBeat;\n }\n if (hold > 0.5) {\n segments.push({ kind: 'freeze', outStart: out, outEnd: out + hold, srcAt: srcEnd });\n out += hold;\n }\n\n steps.push({\n stepRef: `${e.sceneId}/${e.stepIndex}`,\n sceneId: e.sceneId,\n ordinal: e.ordinal,\n kind: e.kind,\n ...(e.locator ? { locator: e.locator } : {}),\n ...(e.masked ? { masked: true } : {}),\n ...(e.targetPre ? { targetRectVp: e.targetPre.bbox } : {}),\n ...(e.focus ? { focus: e.focus } : {}),\n ...(e.shot ? { shot: e.shot } : {}),\n ...(e.focusTarget ? { focusRectVp: e.focusTarget.bbox } : {}),\n outStart: stepOutStart,\n outBeat,\n outEnd: out,\n srcAction: e.tAction,\n srcSettled: srcEnd,\n });\n src = srcEnd;\n }\n\n // Outro: hold the final state.\n const lastSrc = Math.max(src, log.meta.durationMs - 1);\n segments.push({ kind: 'freeze', outStart: out, outEnd: out + cfg.outroMs, srcAt: lastSrc });\n out += cfg.outroMs;\n\n return { segments, steps, durationMs: out };\n}\n\n/** Map an output time to a source time (null on card segments). */\nexport function sampleSource(segments: TimeSegment[], tOut: number): { srcAt: number | null; segment: TimeSegment } {\n const seg = segmentAt(segments, tOut);\n switch (seg.kind) {\n case 'card':\n return { srcAt: null, segment: seg };\n case 'freeze':\n return { srcAt: seg.srcAt, segment: seg };\n case 'source': {\n const u = (tOut - seg.outStart) / Math.max(1e-6, seg.outEnd - seg.outStart);\n return { srcAt: seg.srcStart + u * (seg.srcEnd - seg.srcStart), segment: seg };\n }\n }\n}\n\nexport function segmentAt(segments: TimeSegment[], tOut: number): TimeSegment {\n let lo = 0;\n let hi = segments.length - 1;\n if (tOut <= segments[0]!.outStart) return segments[0]!;\n if (tOut >= segments[hi]!.outEnd) return segments[hi]!;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (segments[mid]!.outEnd <= tOut) lo = mid + 1;\n else hi = mid;\n }\n return segments[lo]!;\n}\n\n/** Events keyed by stepRef, for callers pairing steps back to their events. */\nexport function eventByStepRef(log: EventLog): Map<string, ActionEvent> {\n const map = new Map<string, ActionEvent>();\n for (const e of actionEvents(log)) map.set(`${e.sceneId}/${e.stepIndex}`, e);\n return map;\n}\n","import type { CameraKeyframe } from '../types.js';\nimport type { CameraState } from '../../shared/geometry.js';\nimport { cubicBezier } from '../../shared/easing.js';\n\n/**\n * Sample the camera path at an output time. Keyframes are (time, state, ease-from-previous);\n * holds are expressed as consecutive keyframes with identical states. Zoom interpolates in\n * log space (linear zoom feels like it accelerates).\n */\nexport function sampleCamera(keyframes: CameraKeyframe[], tOut: number): CameraState {\n if (keyframes.length === 0) return { cx: 0, cy: 0, zoom: 1 };\n if (tOut <= keyframes[0]!.tOut) return { ...keyframes[0]!.state };\n const last = keyframes[keyframes.length - 1]!;\n if (tOut >= last.tOut) return { ...last.state };\n\n let lo = 0;\n let hi = keyframes.length - 1;\n while (lo < hi - 1) {\n const mid = (lo + hi) >> 1;\n if (keyframes[mid]!.tOut <= tOut) lo = mid;\n else hi = mid;\n }\n const a = keyframes[lo]!;\n const b = keyframes[hi]!;\n const u = (tOut - a.tOut) / Math.max(1e-6, b.tOut - a.tOut);\n const e = cubicBezier(b.ease, u);\n return {\n cx: a.state.cx + (b.state.cx - a.state.cx) * e,\n cy: a.state.cy + (b.state.cy - a.state.cy) * e,\n zoom: Math.exp(Math.log(a.state.zoom) + (Math.log(b.state.zoom) - Math.log(a.state.zoom)) * e),\n };\n}\n","import type { CameraKeyframe, OutputProfile, StepMapEntry } from '../types.js';\nimport { stageContent, actReactWindows } from '../types.js';\nimport type { EventLog } from '../../capture/events.js';\nimport { navigationEvents } from '../../capture/events.js';\nimport {\n type CameraPlane,\n type CameraState,\n type Rect,\n clamp,\n clampCamera,\n minZoom,\n padRect,\n projectRect,\n rectCenter,\n rectContains,\n rectUnion,\n} from '../../shared/geometry.js';\nimport { EASE_PAN, EASE_ZOOM } from '../../shared/easing.js';\nimport { sampleCamera } from './interpolate.js';\n\nconst FOCUS_PAD_VP = 24;\nconst SHOT_MAX_GAP_MS = 4000;\nconst PAN_DEADBAND_VP = 48;\nconst TRAVEL_MIN_MS = 500;\nconst TRAVEL_MAX_MS = 900;\nconst ARRIVE_LEAD_MS = 80;\n/** Target rendered height (output px) the zoom aims to give the smallest target — comfortably\n * above the verifier's 28px legibility floor so quantization rounding stays safe. */\nconst LEGIBLE_TARGET_PX = 34;\n\ninterface Shot {\n stepRefs: string[];\n sceneId: string;\n focus: Rect;\n /** Smallest unpadded target dimension across the shot's members (viewport px) — this, not the\n * union size, is what the legibility zoom must satisfy so every member stays readable. */\n minTargetDim: number;\n wide: boolean;\n outStart: number;\n firstBeat: number;\n outEnd: number;\n zoomIndex: number;\n state?: CameraState;\n}\n\nexport interface CameraPlanResult {\n keyframes: CameraKeyframe[];\n fallbacks: string[];\n}\n\n/**\n * Plan the camera path from measured step geometry. Craft rules: quantized zoom levels,\n * legibility-driven zoom selection, caption-safe-area bias, pull-backs on navigation and\n * long pans, and an analytic constraint pass that guarantees each target stays framed.\n */\nexport function planCamera(\n steps: StepMapEntry[],\n log: EventLog,\n profile: OutputProfile,\n durationMs: number,\n opts?: { emphasis?: boolean },\n): CameraPlanResult {\n // The camera projects into the STAGE's content rect (or the full frame without a stage):\n // one shared space for planner, renderer, cursor, and verification.\n const content = stageContent(profile);\n const plane: CameraPlane = {\n vpW: log.meta.viewport.w,\n vpH: log.meta.viewport.h,\n outW: content.w,\n outH: content.h,\n };\n const emphasis = opts?.emphasis ?? true;\n const fallbacks: string[] = [];\n\n // Sharpness-bounded zoom quantums: the frame buffer only has frameW real pixels across.\n // Upscales beyond ~1.28x read as soft, so cap quantums there. (The stage helps here: content\n // renders smaller than the frame, so the same capture supports deeper sharp zooms.)\n const sharpZoom = log.meta.frameW > 0 ? log.meta.frameW / content.w : 1.3;\n const zMaxAllowed = Math.max(minZoom(plane), sharpZoom * 1.28);\n const quantums = profile.zoomQuantums.filter((q) => q <= zMaxAllowed + 1e-6);\n if (quantums.length === 0) quantums.push(1);\n\n const navTimes = navigationEvents(log).map((n) => n.t);\n const shots = groupShots(steps, navTimes, plane, durationMs);\n\n for (let attempt = 0; attempt < 4; attempt++) {\n for (const shot of shots) shot.state = shotState(shot, quantums, plane, profile, emphasis);\n const keyframes = emitKeyframes(shots, plane, durationMs);\n const violation = checkConstraints(keyframes, steps, plane, profile);\n if (!violation) return { keyframes, fallbacks };\n\n // An act→react step owns TWO shots with the same stepRef — pick the one whose time window\n // contains the violation, falling back to stepRef membership.\n const shot =\n shots.find(\n (s) => s.stepRefs.includes(violation.stepRef) && violation.tOut >= s.outStart && violation.tOut <= s.outEnd,\n ) ?? shots.find((s) => s.stepRefs.includes(violation.stepRef));\n if (!shot || shot.zoomIndex === 0 || shot.wide) {\n fallbacks.push(`${violation.stepRef}: unresolvable framing violation — falling back to wide`);\n if (shot) shot.wide = true;\n else break;\n } else {\n shot.zoomIndex -= 1;\n fallbacks.push(`${violation.stepRef}: reduced shot zoom to satisfy framing constraints`);\n }\n }\n for (const shot of shots) shot.state = shotState(shot, quantums, plane, profile, emphasis);\n return { keyframes: emitKeyframes(shots, plane, durationMs), fallbacks };\n}\n\nfunction groupShots(steps: StepMapEntry[], navTimes: number[], plane: CameraPlane, durationMs: number): Shot[] {\n const shots: Shot[] = [];\n let current: Shot | null = null;\n\n const navBetween = (a: number, b: number) => navTimes.some((t) => t > a && t <= b);\n\n for (const step of steps) {\n // Act→react: the step clicks one place and focuses another, with enough hold to travel.\n // Emit TWO shots — frame the action target through the beat, then hand the camera off to\n // the payoff for the settled hold (\"click here, look there\" inside one step).\n const handoff = actReactWindows(step);\n if (handoff) {\n const actFocus = padRect(handoff.act.rect, FOCUS_PAD_VP);\n const reactFocus = padRect(handoff.react.rect, FOCUS_PAD_VP);\n shots.push({\n stepRefs: [step.stepRef],\n sceneId: step.sceneId,\n focus: actFocus,\n minTargetDim: Math.min(handoff.act.rect.w, handoff.act.rect.h),\n wide: false,\n outStart: step.outStart,\n firstBeat: step.outBeat,\n outEnd: handoff.act.to,\n zoomIndex: Number.MAX_SAFE_INTEGER,\n });\n shots.push({\n stepRefs: [step.stepRef],\n sceneId: step.sceneId,\n focus: reactFocus,\n minTargetDim: Math.min(handoff.react.rect.w, handoff.react.rect.h),\n wide: false,\n outStart: handoff.act.to,\n firstBeat: handoff.react.from, // arrive by the react window's start\n outEnd: step.outEnd,\n zoomIndex: Number.MAX_SAFE_INTEGER,\n });\n current = null; // never merge across a handoff\n continue;\n }\n\n let rect = step.kind === 'goto' ? undefined : step.targetRectVp;\n // goto and scroll are wide by nature: goto changes everything; a scroll's meaning is the\n // motion, not a specific small element (so scroll targets are exempt from the legibility\n // floor elsewhere — they need only be in frame).\n let wide = !rect || step.kind === 'goto' || step.kind === 'scroll';\n // The spec's focus hint is AUTHORITY, not a suggestion: 'wide' forces a wide shot; 'target'\n // forces this step's own framed shot (never merged away); a locator-valued focus swaps the\n // framed rect for the measured payoff element — this is what lets a goto or a sidebar click\n // frame the thing that CHANGED rather than the thing that was clicked.\n if (step.focus === 'wide') {\n wide = true;\n } else if (step.focusRectVp) {\n rect = step.focusRectVp;\n wide = false;\n } else if (step.focus === 'target' && rect) {\n wide = false;\n }\n // Spec shot control: 'cut' forces this step into a fresh shot; 'continue' merges into the\n // previous shot even when the heuristic would split — the author's cut list wins.\n if (step.shot === 'cut') current = null;\n const forceContinue = step.shot === 'continue';\n if (forceContinue && current && rect && current.sceneId === step.sceneId) {\n current.stepRefs.push(step.stepRef);\n current.focus = rectUnion(current.focus, padRect(rect, FOCUS_PAD_VP));\n current.minTargetDim = Math.min(current.minTargetDim, Math.min(rect.w, rect.h));\n current.outEnd = step.outEnd;\n continue;\n }\n const noMerge = step.focus === 'target' || step.focusRectVp !== undefined;\n // A shot never spans scenes: hash-route changes don't fire a navigation event, so scene\n // identity — not navBetween alone — is what keeps a tour's views from merging into one\n // un-zoomable mega-shot.\n if (current && !noMerge && current.sceneId === step.sceneId && !current.wide && !wide && rect) {\n const prevSrc = current.stepRefs.length > 0 ? steps.find((s) => s.stepRef === current!.stepRefs[current!.stepRefs.length - 1])!.srcSettled : 0;\n const union = rectUnion(current.focus, padRect(rect, FOCUS_PAD_VP));\n // A merge must keep the SMALLEST member legible: if the union can only be shown at a zoom\n // below what the smallest target needs, merging would dilute it (a small pipeline card\n // pulled into a wide modal shot renders too small) — so keep them as separate shots.\n const baseScale = plane.outW / plane.vpW;\n const mergedMinDim = Math.min(current.minTargetDim, Math.min(rect.w, rect.h));\n const zNeeded = Math.min(LEGIBLE_TARGET_PX / (mergedMinDim * baseScale), 1.6);\n const zFitUnion = fitZoom(union, plane) * 0.92;\n const fitsTogether = fitZoom(union, plane) >= 1.2 && zFitUnion >= zNeeded - 0.02;\n const closeInTime = step.outStart - current.outEnd < SHOT_MAX_GAP_MS;\n if (fitsTogether && closeInTime && !navBetween(prevSrc, step.srcAction)) {\n current.stepRefs.push(step.stepRef);\n current.focus = union;\n current.minTargetDim = Math.min(current.minTargetDim, Math.min(rect.w, rect.h));\n current.outEnd = step.outEnd;\n continue;\n }\n }\n current = {\n stepRefs: [step.stepRef],\n sceneId: step.sceneId,\n focus: rect ? padRect(rect, FOCUS_PAD_VP) : { x: 0, y: 0, w: plane.vpW, h: plane.vpH },\n minTargetDim: rect ? Math.min(rect.w, rect.h) : Math.min(plane.vpW, plane.vpH),\n wide,\n outStart: step.outStart,\n firstBeat: step.outBeat,\n outEnd: step.outEnd,\n zoomIndex: Number.MAX_SAFE_INTEGER, // resolved in shotState\n };\n shots.push(current);\n }\n if (shots.length > 0) shots[shots.length - 1]!.outEnd = Math.min(shots[shots.length - 1]!.outEnd, durationMs);\n return shots;\n}\n\n/** Max zoom at which a viewport rect still fits in the visible window with margin. */\nfunction fitZoom(rect: Rect, plane: CameraPlane): number {\n const zw = plane.vpW / rect.w;\n const zh = (plane.vpW * plane.outH) / plane.outW / rect.h;\n return Math.min(zw, zh);\n}\n\n/** Fraction of the fit-zoom a focus rect should occupy when the camera emphasises it: at 0.5\n * the subject fills roughly half the frame's limiting dimension — close enough to direct the\n * eye, wide enough to keep context. This, not legibility, is what makes shots feel FRAMED. */\nconst OCCUPANCY = 0.5;\n\nfunction shotState(\n shot: Shot,\n quantums: number[],\n plane: CameraPlane,\n profile: OutputProfile,\n emphasis: boolean,\n): CameraState {\n const zMin = minZoom(plane);\n if (shot.wide) {\n return clampCamera({ cx: plane.vpW / 2, cy: rectCenter(shot.focus).y, zoom: zMin }, plane);\n }\n const baseScale = plane.outW / plane.vpW;\n // Legibility is driven by the SMALLEST member target (so a small element merged into a large\n // shot still gets enough zoom), while fit is driven by the whole union (so nothing is cropped).\n const minDim = Math.max(6, shot.minTargetDim);\n const zLegibility = LEGIBLE_TARGET_PX / (minDim * baseScale);\n const zFit = fitZoom(shot.focus, plane) * 0.92;\n\n // Composition: zoom is a DIRECTORIAL choice, not just a legibility floor. Without this, any\n // target above ~23 viewport px resolves to zoom 1.0 and the whole video plays wide and flat.\n const zComposition = emphasis ? OCCUPANCY * fitZoom(shot.focus, plane) : 0;\n const zWant = Math.max(zLegibility, zComposition);\n\n // Choose the smallest quantum ≥ the wanted zoom (round UP — an under-framed subject is the\n // defect we most want to avoid), but never past what fits without cropping.\n const maxFit = Math.min(zFit, quantums[quantums.length - 1]!);\n let zoomIndex = 0;\n let reachedWant = false;\n for (let i = 0; i < quantums.length; i++) {\n if (quantums[i]! > maxFit + 1e-6) break;\n zoomIndex = i; // largest quantum that still fits, as a fallback\n if (!reachedWant && quantums[i]! >= zWant - 1e-6) {\n zoomIndex = i;\n reachedWant = true;\n break;\n }\n }\n shot.zoomIndex = Math.min(shot.zoomIndex, zoomIndex);\n const zoom = Math.max(quantums[shot.zoomIndex]!, zMin);\n\n const center = rectCenter(shot.focus);\n let state = clampCamera({ cx: center.x, cy: center.y, zoom }, plane);\n\n // Bias the focus rect into the content safe area (out of the caption band).\n for (let i = 0; i < 3; i++) {\n const proj = projectRect(shot.focus, state, plane);\n const safe = contentArea(profile);\n let dyOut = 0;\n if (proj.y + proj.h > safe.y + safe.h) dyOut = proj.y + proj.h - (safe.y + safe.h);\n else if (proj.y < safe.y) dyOut = proj.y - safe.y;\n let dxOut = 0;\n if (proj.x + proj.w > safe.x + safe.w) dxOut = proj.x + proj.w - (safe.x + safe.w);\n else if (proj.x < safe.x) dxOut = proj.x - safe.x;\n if (Math.abs(dxOut) < 1 && Math.abs(dyOut) < 1) break;\n const visW = plane.vpW / state.zoom;\n const scale = visW / plane.outW;\n state = clampCamera({ cx: state.cx + dxOut * scale, cy: state.cy + dyOut * scale, zoom: state.zoom }, plane);\n }\n return state;\n}\n\n/** The safe area, expressed in PLANE space (stage content coords when a stage is set): frame\n * margins translated into the content rect, with a small floor so it never collapses. */\nexport function contentArea(profile: OutputProfile): Rect {\n const s = stageContent(profile);\n const left = Math.max(profile.safeArea.left - s.x, 8);\n const top = Math.max(profile.safeArea.top - s.y, 8);\n const right = Math.min(s.w - 8, profile.width - profile.safeArea.right - s.x);\n const bottom = Math.min(s.h - 8, profile.height - profile.safeArea.bottom - s.y);\n return { x: left, y: top, w: Math.max(16, right - left), h: Math.max(16, bottom - top) };\n}\n\nfunction emitKeyframes(shots: Shot[], plane: CameraPlane, durationMs: number): CameraKeyframe[] {\n const kfs: CameraKeyframe[] = [];\n const wideState = clampCamera({ cx: plane.vpW / 2, cy: plane.vpH / 2, zoom: minZoom(plane) }, plane);\n let prevState = wideState;\n let prevEnd = 0;\n kfs.push({ tOut: 0, state: wideState, ease: EASE_ZOOM });\n\n for (const shot of shots) {\n const target = shot.state!;\n const panDist = Math.hypot(target.cx - prevState.cx, target.cy - prevState.cy);\n const zoomChanged = Math.abs(Math.log(target.zoom / prevState.zoom)) > 0.01;\n if (panDist < PAN_DEADBAND_VP / 2 && !zoomChanged) {\n prevEnd = shot.outEnd;\n continue;\n }\n\n // Long pans while zoomed read badly: pull wide first, then dive in.\n const viaWide =\n panDist > plane.vpW * 0.6 && prevState.zoom > 1.15 && target.zoom > 1.15 ? wideState : null;\n\n const arriveBy = Math.max(shot.firstBeat - ARRIVE_LEAD_MS, shot.outStart + 100);\n const travel = clamp(300 + panDist * 0.8, TRAVEL_MIN_MS, TRAVEL_MAX_MS);\n let moveStart = Math.max(prevEnd, arriveBy - travel);\n if (viaWide) {\n const mid = Math.max(prevEnd, moveStart - 350);\n kfs.push({ tOut: mid, state: prevState, ease: EASE_PAN });\n kfs.push({ tOut: Math.min(mid + 400, arriveBy - 200), state: viaWide, ease: EASE_ZOOM });\n moveStart = Math.min(mid + 400, arriveBy - 200);\n } else {\n kfs.push({ tOut: moveStart, state: prevState, ease: EASE_PAN });\n }\n const moveEnd = Math.max(arriveBy, moveStart + 250);\n kfs.push({ tOut: moveEnd, state: target, ease: zoomChanged ? EASE_ZOOM : EASE_PAN });\n prevState = target;\n prevEnd = shot.outEnd;\n }\n\n // Final pull-back to wide during the outro.\n if (prevState.zoom > wideState.zoom + 0.01 || Math.hypot(prevState.cx - wideState.cx, prevState.cy - wideState.cy) > PAN_DEADBAND_VP) {\n const start = Math.min(prevEnd + 100, durationMs - 900);\n kfs.push({ tOut: start, state: prevState, ease: EASE_ZOOM });\n kfs.push({ tOut: Math.min(start + 800, durationMs - 50), state: wideState, ease: EASE_ZOOM });\n }\n return dedupeSorted(kfs);\n}\n\nfunction dedupeSorted(kfs: CameraKeyframe[]): CameraKeyframe[] {\n kfs.sort((a, b) => a.tOut - b.tOut);\n const out: CameraKeyframe[] = [];\n for (const kf of kfs) {\n const last = out[out.length - 1];\n if (last && kf.tOut - last.tOut < 1) {\n out[out.length - 1] = kf;\n } else {\n out.push(kf);\n }\n }\n return out;\n}\n\ninterface Violation {\n stepRef: string;\n tOut: number;\n}\n\n/**\n * The \"never crop mid-element\" guarantee: analytically sample the planned path and assert\n * every target is fully in frame (not cropped) during its hold. The comfortable safe-area\n * margin is a preference in shotState, not a hard constraint here.\n */\nfunction checkConstraints(\n keyframes: CameraKeyframe[],\n steps: StepMapEntry[],\n plane: CameraPlane,\n profile: OutputProfile,\n): Violation | null {\n // The camera projects into stage-content space, so the containment frame is the content rect.\n const content = stageContent(profile);\n const frame: Rect = { x: 0, y: 0, w: content.w, h: content.h };\n for (const step of steps) {\n // Windows to validate: an act→react step promises the ACTION target around the beat and the\n // FOCUSED payoff during the settled hold (the camera travels between — unchecked by design).\n // Otherwise: the focused rect (or the target) across the whole hold.\n const handoff = actReactWindows(step);\n const rect = step.focusRectVp ?? step.targetRectVp;\n const windows = handoff\n ? [handoff.act, handoff.react]\n : rect\n ? [{ rect, from: Math.max(step.outStart, step.outBeat - 60), to: step.outEnd }]\n : [];\n for (const w of windows) {\n for (let t = w.from; t <= w.to; t += 100) {\n const cam = sampleCamera(keyframes, t);\n const proj = projectRect(w.rect, cam, plane);\n if (!rectContains(frame, proj, 2)) {\n return { stepRef: step.stepRef, tOut: t };\n }\n }\n }\n }\n return null;\n}\n","import type { CursorSegment, ClickRipple, StepMapEntry } from '../types.js';\nimport type { EventLog } from '../../capture/events.js';\nimport { eventByStepRef } from '../timeline/pacing.js';\nimport { type Point, clamp, dist } from '../../shared/geometry.js';\nimport { minJerk } from '../../shared/easing.js';\n\nconst RESAMPLE_POINTS = 32;\nconst CLICK_KINDS = new Set(['click', 'dblclick', 'select']);\nconst POINTER_KINDS = new Set(['click', 'dblclick', 'hover', 'type', 'select']);\n\nexport interface CursorPlan {\n segments: CursorSegment[];\n ripples: ClickRipple[];\n restStart: Point;\n}\n\n/**\n * Re-synthesize cursor motion on the output clock: recorded waypoints give the path SHAPE,\n * arrival is re-timed so the cursor lands on the target exactly at the action beat with a\n * minimum-jerk profile.\n */\nexport function planCursor(steps: StepMapEntry[], log: EventLog): CursorPlan {\n const events = eventByStepRef(log);\n const segments: CursorSegment[] = [];\n const ripples: ClickRipple[] = [];\n let rest: Point = { x: log.meta.viewport.w / 2, y: log.meta.viewport.h * 0.6 };\n const restStart = { ...rest };\n\n for (const step of steps) {\n if (!POINTER_KINDS.has(step.kind)) continue;\n const event = events.get(step.stepRef);\n if (!event || event.cursorPath.length < 2) continue;\n\n const raw: Point[] = event.cursorPath.map((w) => ({ x: w.x, y: w.y }));\n // Continuity: motion starts wherever the cursor last rested on the output clock.\n raw[0] = { ...rest };\n const path = resampleByArcLength(raw, RESAMPLE_POINTS);\n const travelDist = dist(path[0]!, path[path.length - 1]!);\n const travel = clamp(300 + travelDist * 0.6, 300, 900);\n\n const prevEnd = segments.length > 0 ? segments[segments.length - 1]!.tEnd : 0;\n const tEnd = step.outBeat;\n const tStart = Math.max(Math.min(step.outStart, tEnd - 100), tEnd - travel, prevEnd + 40);\n\n if (tEnd - tStart > 30) {\n segments.push({ tStart, tEnd, path, clickAtEnd: CLICK_KINDS.has(step.kind) });\n }\n rest = path[path.length - 1]!;\n if (CLICK_KINDS.has(step.kind)) {\n ripples.push({ tOut: step.outBeat, x: rest.x, y: rest.y });\n }\n }\n return { segments, ripples, restStart };\n}\n\n/** Position of the cursor at an output time (viewport space). */\nexport function sampleCursor(plan: CursorPlan, tOut: number): Point {\n const segs = plan.segments;\n if (segs.length === 0) return plan.restStart;\n if (tOut <= segs[0]!.tStart) return segs[0]!.path[0]!;\n\n for (let i = 0; i < segs.length; i++) {\n const s = segs[i]!;\n if (tOut < s.tStart) return segs[i - 1]!.path[segs[i - 1]!.path.length - 1]!;\n if (tOut <= s.tEnd) {\n const u = minJerk((tOut - s.tStart) / Math.max(1e-6, s.tEnd - s.tStart));\n const fi = u * (s.path.length - 1);\n const i0 = Math.floor(fi);\n const i1 = Math.min(i0 + 1, s.path.length - 1);\n const f = fi - i0;\n return {\n x: s.path[i0]!.x + (s.path[i1]!.x - s.path[i0]!.x) * f,\n y: s.path[i0]!.y + (s.path[i1]!.y - s.path[i0]!.y) * f,\n };\n }\n }\n const last = segs[segs.length - 1]!;\n return last.path[last.path.length - 1]!;\n}\n\n/** Resample a polyline to n points equally spaced by arc length. */\nfunction resampleByArcLength(points: Point[], n: number): Point[] {\n const cum: number[] = [0];\n for (let i = 1; i < points.length; i++) {\n cum.push(cum[i - 1]! + dist(points[i - 1]!, points[i]!));\n }\n const total = cum[cum.length - 1]!;\n if (total < 1e-6) return Array.from({ length: n }, () => ({ ...points[0]! }));\n const out: Point[] = [];\n let j = 0;\n for (let i = 0; i < n; i++) {\n const target = (i / (n - 1)) * total;\n while (j < cum.length - 2 && cum[j + 1]! < target) j++;\n const span = Math.max(1e-6, cum[j + 1]! - cum[j]!);\n const f = (target - cum[j]!) / span;\n out.push({\n x: points[j]!.x + (points[j + 1]!.x - points[j]!.x) * f,\n y: points[j]!.y + (points[j + 1]!.y - points[j]!.y) * f,\n });\n }\n return out;\n}\n","import type { ActionEvent } from '../capture/events.js';\nimport { parseLocator, locatorDisplayName } from '../spec/locators.js';\n\n/** Per-step text overrides from a LIVE spec, keyed by stepRef — the compose-time source of\n * truth for caption/narration text. The copies baked into events.json are only the record of\n * what was captured; preferring the live spec makes text edits a sub-second re-compose, never\n * a re-capture (capture once, compose forever — including the words). */\nexport interface StepTexts {\n caption?: string;\n narration?: string;\n}\n\n/**\n * Deterministic caption writer: turns a step + its recorded accessible label into\n * instruction text. Text resolution: live-spec caption ?? captured caption ?? auto-written.\n * Returns null for steps that produce no caption (expect/wait without caption).\n */\nexport function writeCaption(event: ActionEvent, texts?: StepTexts): string | null {\n if (texts?.caption) return texts.caption;\n if (event.caption) return event.caption;\n\n const label = bestLabel(event);\n switch (event.kind) {\n case 'click':\n return label ? `Click “${label}”` : 'Click the highlighted element';\n case 'dblclick':\n return label ? `Double-click “${label}”` : 'Double-click the highlighted element';\n case 'hover':\n return label ? `Hover over “${label}”` : 'Hover over the highlighted element';\n case 'type':\n return label ? `Enter the ${lowerFirst(label)}` : 'Enter a value';\n case 'press':\n return `Press ${event.locator ?? 'the key'}`;\n case 'select':\n return label && event.typedText\n ? `Choose “${event.typedText}” under ${label}`\n : label\n ? `Choose an option under ${label}`\n : 'Choose an option';\n case 'goto':\n return `Open ${prettyUrl(event.locator ?? '')}`;\n case 'scroll':\n return label ? `Scroll to ${label}` : 'Scroll down';\n case 'expect':\n case 'wait':\n return null;\n }\n}\n\n/**\n * The SPOKEN line for a step: live-spec narration ?? live-spec caption ?? captured narration ??\n * the caption. Narration is unconstrained by the caption card, so a spec can show a terse\n * on-screen label while the voice says the full sentence.\n */\nexport function writeNarration(event: ActionEvent, texts?: StepTexts): string | null {\n return texts?.narration ?? event.narration ?? writeCaption(event, texts);\n}\n\nfunction bestLabel(event: ActionEvent): string | null {\n const name = event.targetPre?.accessibleName?.trim();\n if (name) return truncate(name, 60);\n if (event.locator) {\n try {\n return truncate(locatorDisplayName(parseLocator(event.locator)), 60);\n } catch {\n return null;\n }\n }\n return null;\n}\n\nfunction lowerFirst(s: string): string {\n // Keep acronyms/proper-looking tokens intact (\"API key\" stays, \"Email\" lowers).\n if (s.length > 1 && s[1] === s[1]!.toUpperCase() && /[A-Z]/.test(s[1]!)) return s;\n return s.charAt(0).toLowerCase() + s.slice(1);\n}\n\nfunction prettyUrl(url: string): string {\n try {\n const u = new URL(url);\n return u.host + (u.pathname !== '/' ? u.pathname : '');\n } catch {\n return url;\n }\n}\n\nfunction truncate(s: string, max: number): string {\n return s.length <= max ? s : s.slice(0, max - 1) + '…';\n}\n","import { createCanvas, type SKRSContext2D } from '@napi-rs/canvas';\n\nlet measureCtx: SKRSContext2D | null = null;\n\nfunction ctx(): SKRSContext2D {\n if (!measureCtx) measureCtx = createCanvas(8, 8).getContext('2d');\n return measureCtx;\n}\n\nexport function measureText(text: string, font: string): number {\n const c = ctx();\n c.font = font;\n return c.measureText(text).width;\n}\n\nexport interface WrapResult {\n lines: string[];\n fontPx: number;\n widest: number;\n shrunk: boolean;\n truncated: boolean;\n}\n\n/**\n * Greedy word-wrap with overflow as a first-class fact: try at fontPx; if the text needs\n * more than maxLines, shrink once to minFontPx; if it still overflows, truncate the last\n * line with an ellipsis AND report it — never silently clip.\n */\nexport function wrapText(\n text: string,\n fontFor: (px: number) => string,\n maxWidth: number,\n fontPx: number,\n minFontPx: number,\n maxLines: number,\n): WrapResult {\n let attempt = wrapAt(text, fontFor(fontPx), maxWidth);\n if (attempt.length <= maxLines) {\n return { lines: attempt, fontPx, widest: widestOf(attempt, fontFor(fontPx)), shrunk: false, truncated: false };\n }\n attempt = wrapAt(text, fontFor(minFontPx), maxWidth);\n if (attempt.length <= maxLines) {\n return { lines: attempt, fontPx: minFontPx, widest: widestOf(attempt, fontFor(minFontPx)), shrunk: true, truncated: false };\n }\n const kept = attempt.slice(0, maxLines);\n let last = kept[maxLines - 1]!;\n const font = fontFor(minFontPx);\n while (last.length > 1 && measureText(last + '…', font) > maxWidth) {\n last = last.slice(0, -1).trimEnd();\n }\n kept[maxLines - 1] = last + '…';\n return { lines: kept, fontPx: minFontPx, widest: widestOf(kept, font), shrunk: true, truncated: true };\n}\n\nfunction wrapAt(text: string, font: string, maxWidth: number): string[] {\n const words = text.split(/\\s+/).filter(Boolean);\n const lines: string[] = [];\n let line = '';\n for (const word of words) {\n const candidate = line ? line + ' ' + word : word;\n if (line && measureText(candidate, font) > maxWidth) {\n lines.push(line);\n line = word;\n } else {\n line = candidate;\n }\n }\n if (line) lines.push(line);\n return lines.length > 0 ? lines : [''];\n}\n\nfunction widestOf(lines: string[], font: string): number {\n return Math.max(...lines.map((l) => measureText(l, font)));\n}\n\n/** Rounded-rect path helper shared by overlay drawing. */\nexport function roundRect(c: SKRSContext2D, x: number, y: number, w: number, h: number, r: number): void {\n const rr = Math.min(r, w / 2, h / 2);\n c.beginPath();\n c.moveTo(x + rr, y);\n c.arcTo(x + w, y, x + w, y + h, rr);\n c.arcTo(x + w, y + h, x, y + h, rr);\n c.arcTo(x, y + h, x, y, rr);\n c.arcTo(x, y, x + w, y, rr);\n c.closePath();\n}\n","import type { CameraKeyframe, CaptionOverlay, ComposeDiagnostics, OutputProfile, OverlayEntry, StepMapEntry } from '../types.js';\nimport { stageContent } from '../types.js';\nimport type { EventLog } from '../../capture/events.js';\nimport type { ResolvedTheme } from '../../theme/index.js';\nimport type { KindProfile } from '../kinds.js';\nimport { writeCaption, type StepTexts } from '../captions.js';\nimport { eventByStepRef } from '../timeline/pacing.js';\nimport { wrapText, measureText } from './text.js';\nimport { sampleCamera } from '../camera/interpolate.js';\nimport { projectRect, type CameraPlane, type Rect } from '../../shared/geometry.js';\n\nconst CARD_PAD_X = 26;\nconst CARD_PAD_Y = 16;\nconst BADGE_GAP = 14;\nconst CARD_BOTTOM_MARGIN = 44;\nconst CHAPTER_LABEL_MS = 1800;\n/** Adjacent captions overlap by this much and cross-dissolve (fade handles the blend). */\nconst CAPTION_CROSSFADE_MS = 240;\n\nfunction overlaps(a: Rect, b: Rect): boolean {\n return a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y;\n}\n\nexport function buildOverlays(\n steps: StepMapEntry[],\n log: EventLog,\n theme: ResolvedTheme,\n profile: OutputProfile,\n title: string,\n subtitle: string,\n titleCardEndMs: number,\n diagnostics: ComposeDiagnostics,\n kind: KindProfile,\n sceneTitles?: Map<string, string>,\n camera?: CameraKeyframe[],\n specTexts?: Map<string, StepTexts>,\n): OverlayEntry[] {\n const overlays: OverlayEntry[] = [];\n overlays.push({ kind: 'titleCard', cardId: 'title', title, subtitle, tStart: 0, tEnd: titleCardEndMs });\n overlays.push({ kind: 'dip', tStart: titleCardEndMs, tEnd: titleCardEndMs + 400 });\n\n const events = eventByStepRef(log);\n const captioned = steps.filter((s) => {\n const e = events.get(s.stepRef);\n return e && writeCaption(e, specTexts?.get(s.stepRef)) !== null;\n });\n const total = captioned.length;\n let number = 0;\n\n // Chapter labels at each new scene, and an elapsed clock spanning the flow (bug-repro).\n if (kind.chapterCards) {\n const boundaries = sceneBoundaries(steps, sceneTitles);\n let chapter = 0;\n for (const b of boundaries) {\n chapter += 1;\n overlays.push({ kind: 'chapterLabel', title: b.title, ordinal: chapter, tStart: b.outStart, tEnd: b.outStart + CHAPTER_LABEL_MS });\n }\n }\n if (kind.elapsedClock) {\n const firstBeat = captioned[0]?.outBeat ?? titleCardEndMs;\n const last = steps[steps.length - 1];\n overlays.push({ kind: 'elapsedClock', tStart: titleCardEndMs, tEnd: last ? last.outEnd : titleCardEndMs, zeroAtMs: firstBeat });\n }\n\n // `captions: off` renders no caption cards (used for the voice-only cut); the\n // spoken narration still comes from the same text, derived separately in compose.\n for (let i = 0; theme.captionPosition !== 'off' && i < captioned.length; i++) {\n const step = captioned[i]!;\n const event = events.get(step.stepRef)!;\n const base = writeCaption(event, specTexts?.get(step.stepRef))!;\n number += 1;\n const text = kind.captionStyle === 'factual' ? `Step ${number} — ${lowerFirst(base)}` : base;\n\n const fontFor = (px: number) => `${px}px Inter Medium`;\n const showBadge = kind.numberedCaptions && kind.captionStyle !== 'factual';\n const badgeFontPx = 15;\n const badgeText = `${number}/${total}`;\n const badgeW = showBadge ? Math.ceil(measureText(badgeText, `600 ${badgeFontPx}px Inter SemiBold`)) + 20 : 0;\n const badgeGap = showBadge ? BADGE_GAP : 0;\n const maxTextWidth = Math.min(profile.captionMaxWidth, profile.width - 2 * profile.safeArea.left) - CARD_PAD_X * 2 - badgeW - badgeGap;\n\n const wrap = wrapText(text, fontFor, maxTextWidth, theme.captionFontPx, theme.captionMinFontPx, theme.captionMaxLines);\n if (wrap.truncated) diagnostics.overflows.push({ stepRef: step.stepRef, text, action: 'truncated' });\n else if (wrap.shrunk) diagnostics.overflows.push({ stepRef: step.stepRef, text, action: 'shrunk' });\n\n const lineH = Math.round(wrap.fontPx * 1.35);\n const cardW = CARD_PAD_X * 2 + badgeW + badgeGap + Math.ceil(wrap.widest);\n const cardH = CARD_PAD_Y * 2 + wrap.lines.length * lineH;\n const x = (profile.width - cardW) / 2;\n let y =\n theme.captionPosition === 'bottom'\n ? profile.height - CARD_BOTTOM_MARGIN - cardH\n : profile.safeArea.top;\n\n // Collision flip: if the framed subject sits under the caption during the hold, move the\n // caption to the top rather than covering the very thing the step is about.\n if (camera && theme.captionPosition === 'bottom') {\n const rect = step.focusRectVp ?? step.targetRectVp;\n if (rect) {\n const content = stageContent(profile);\n const capPlane: CameraPlane = { vpW: log.meta.viewport.w, vpH: log.meta.viewport.h, outW: content.w, outH: content.h };\n const cam = sampleCamera(camera, Math.min(step.outBeat + 250, step.outEnd));\n const proj = projectRect(rect, cam, capPlane);\n const projFrame: Rect = { x: proj.x + content.x, y: proj.y + content.y, w: proj.w, h: proj.h };\n const capBox: Rect = { x, y, w: cardW, h: cardH };\n if (overlaps(projFrame, capBox)) y = profile.safeArea.top;\n }\n }\n\n // Caption runs slightly INTO the next caption's window so adjacent captions cross-dissolve\n // instead of blinking out to an empty band at every step boundary.\n const next = captioned[i + 1];\n const tEnd = next ? Math.min(step.outEnd, next.outStart + CAPTION_CROSSFADE_MS) : step.outEnd;\n\n const overlay: CaptionOverlay = {\n kind: 'caption',\n stepRef: step.stepRef,\n ordinal: number,\n totalSteps: total,\n showBadge,\n text,\n lines: wrap.lines,\n fontPx: wrap.fontPx,\n box: { x, y, w: cardW, h: cardH },\n tStart: step.outStart,\n tEnd,\n shrunk: wrap.shrunk,\n truncated: wrap.truncated,\n };\n overlays.push(overlay);\n }\n return overlays;\n}\n\n/** First step of each scene, with a human title, for chapter labels. The spec's own\n * `scene.title` wins; deriving from the kebab-case id is only the fallback. */\nfunction sceneBoundaries(\n steps: StepMapEntry[],\n sceneTitles?: Map<string, string>,\n): { title: string; outStart: number }[] {\n const out: { title: string; outStart: number }[] = [];\n let lastScene = '';\n for (const s of steps) {\n if (s.sceneId !== lastScene) {\n lastScene = s.sceneId;\n out.push({ title: sceneTitles?.get(s.sceneId) ?? titleFromSceneId(s.sceneId), outStart: s.outStart });\n }\n }\n return out;\n}\n\nfunction titleFromSceneId(id: string): string {\n const t = id.replace(/-/g, ' ');\n return t.charAt(0).toUpperCase() + t.slice(1);\n}\n\nfunction lowerFirst(s: string): string {\n if (s.length > 1 && s[1] === s[1]!.toUpperCase() && /[A-Z]/.test(s[1]!)) return s;\n return s.charAt(0).toLowerCase() + s.slice(1);\n}\n","import type { SKRSContext2D } from '@napi-rs/canvas';\nimport type { Point } from '../../shared/geometry.js';\nimport type { ClickRipple } from '../types.js';\nimport type { ResolvedTheme } from '../../theme/index.js';\n\nconst RIPPLE_MS = 350;\nconst PRESS_DOWN_MS = 90;\nconst PRESS_UP_MS = 120;\n\nexport type CursorGlyph = 'arrow' | 'ibeam';\n\n/** Draw the vector cursor at an output-space point.\n * `baseScale` (output px per viewport px) keeps the cursor proportioned to the UI it points\n * at — without it the cursor renders 1.5× too small against upscaled content. */\nexport function drawCursor(\n ctx: SKRSContext2D,\n p: Point,\n zoom: number,\n tOut: number,\n ripples: ClickRipple[],\n rippleCenters: Point[],\n theme: ResolvedTheme,\n baseScale = 1,\n glyph: CursorGlyph = 'arrow',\n): void {\n // Press animation: scale dips to 0.85 around each click beat.\n let scale = 1;\n for (const r of ripples) {\n const dt = tOut - r.tOut;\n if (dt >= -PRESS_DOWN_MS && dt < 0) scale = 1 - 0.15 * (1 + dt / PRESS_DOWN_MS);\n else if (dt >= 0 && dt <= PRESS_UP_MS) scale = 0.85 + 0.15 * (dt / PRESS_UP_MS);\n }\n\n // Expanding ring at click points (drawn under the cursor).\n for (let i = 0; i < ripples.length; i++) {\n const r = ripples[i]!;\n const dt = tOut - r.tOut;\n if (dt < 0 || dt > RIPPLE_MS) continue;\n const u = dt / RIPPLE_MS;\n const c = rippleCenters[i]!;\n ctx.save();\n ctx.beginPath();\n ctx.arc(c.x, c.y, (6 + 42 * easeOut(u)) * baseScale, 0, Math.PI * 2);\n ctx.strokeStyle = theme.accent;\n ctx.globalAlpha = 0.6 * (1 - u);\n ctx.lineWidth = 3.5 * baseScale * (1 - u * 0.5);\n ctx.stroke();\n ctx.restore();\n }\n\n const size = 24 * baseScale * (1 + 0.15 * (zoom - 1)) * scale;\n ctx.save();\n ctx.translate(p.x, p.y);\n ctx.scale(size / 24, size / 24);\n ctx.shadowColor = 'rgba(0,0,0,0.35)';\n ctx.shadowBlur = 5;\n ctx.shadowOffsetY = 1.5;\n if (glyph === 'ibeam') {\n // I-beam (text) cursor, hotspot at the beam center.\n ctx.beginPath();\n ctx.moveTo(-4, -9);\n ctx.lineTo(4, -9);\n ctx.moveTo(0, -9);\n ctx.lineTo(0, 9);\n ctx.moveTo(-4, 9);\n ctx.lineTo(4, 9);\n ctx.lineWidth = 2.4;\n ctx.strokeStyle = '#ffffff';\n ctx.stroke();\n ctx.shadowColor = 'transparent';\n ctx.lineWidth = 1;\n ctx.strokeStyle = 'rgba(20,24,34,0.9)';\n ctx.stroke();\n } else {\n // Arrow pointer path (24px design grid, hotspot at 0,0)\n ctx.beginPath();\n ctx.moveTo(0, 0);\n ctx.lineTo(0, 17.5);\n ctx.lineTo(4.2, 13.6);\n ctx.lineTo(7.4, 20.6);\n ctx.lineTo(10.3, 19.2);\n ctx.lineTo(7.2, 12.4);\n ctx.lineTo(12.8, 12.2);\n ctx.closePath();\n ctx.fillStyle = '#ffffff';\n ctx.fill();\n ctx.shadowColor = 'transparent';\n ctx.lineWidth = 1.4;\n ctx.strokeStyle = 'rgba(20,24,34,0.9)';\n ctx.stroke();\n }\n ctx.restore();\n}\n\nfunction easeOut(u: number): number {\n return 1 - (1 - u) * (1 - u);\n}\n","import type { SKRSContext2D } from '@napi-rs/canvas';\nimport type { CaptionOverlay, OutputProfile, OverlayEntry, TitleCardOverlay } from '../types.js';\nimport type { ResolvedTheme } from '../../theme/index.js';\nimport { roundRect, measureText } from './text.js';\nimport { clamp } from '../../shared/geometry.js';\n\nconst FADE_MS = 200;\nconst SCRIM_H = 210;\n\nexport function drawOverlays(\n ctx: SKRSContext2D,\n overlays: OverlayEntry[],\n tOut: number,\n theme: ResolvedTheme,\n profile: OutputProfile,\n): void {\n // Bottom gradient scrim behind the caption band, drawn ONCE at the strongest active caption's\n // alpha (overlapping cross-fading captions must not double-darken it). Keeps caption text off\n // raw UI pixels regardless of what the app renders down there.\n const bottomCaptions = overlays.filter(\n (o): o is CaptionOverlay =>\n o.kind === 'caption' && tOut >= o.tStart && tOut <= o.tEnd && o.box.y > profile.height / 2,\n );\n if (bottomCaptions.length > 0) {\n const a = Math.max(...bottomCaptions.map((o) => captionAlpha(o, tOut)));\n if (a > 0) {\n const g = ctx.createLinearGradient(0, profile.height - SCRIM_H, 0, profile.height);\n g.addColorStop(0, 'rgba(8,10,16,0)');\n g.addColorStop(1, `rgba(8,10,16,${(0.55 * a).toFixed(3)})`);\n ctx.fillStyle = g;\n ctx.fillRect(0, profile.height - SCRIM_H, profile.width, SCRIM_H);\n }\n }\n\n for (const o of overlays) {\n if (tOut < o.tStart || tOut > o.tEnd) continue;\n switch (o.kind) {\n case 'caption':\n drawCaption(ctx, o, tOut, theme);\n break;\n case 'dip': {\n // 'in': fade from theme bg into footage (post-title). 'out': fade footage into the bg\n // (pre-end-card), so the closing card doesn't hard-cut in.\n const u = (tOut - o.tStart) / Math.max(1, o.tEnd - o.tStart);\n ctx.save();\n ctx.globalAlpha = o.direction === 'out' ? u : 1 - u;\n ctx.fillStyle = theme.bg;\n ctx.fillRect(0, 0, profile.width, profile.height);\n ctx.restore();\n break;\n }\n case 'elapsedClock':\n drawElapsedClock(ctx, o.zeroAtMs, tOut, theme, profile);\n break;\n case 'chapterLabel':\n drawChapterLabel(ctx, o, tOut, theme, profile);\n break;\n case 'titleCard':\n case 'failureCard':\n // Painted by the renderer as a full-frame card (not an overlay on footage).\n break;\n }\n }\n}\n\nfunction drawElapsedClock(\n ctx: SKRSContext2D,\n zeroAtMs: number,\n tOut: number,\n theme: ResolvedTheme,\n profile: OutputProfile,\n): void {\n const ms = Math.max(0, tOut - zeroAtMs);\n const s = Math.floor(ms / 1000);\n const label = `${String(Math.floor(s / 60)).padStart(2, '0')}:${String(s % 60).padStart(2, '0')}.${String(Math.floor((ms % 1000) / 100))}`;\n const font = '600 26px Inter SemiBold';\n ctx.save();\n ctx.font = font;\n const textW = ctx.measureText(label).width;\n const padX = 16;\n const w = textW + padX * 2 + 30;\n const h = 44;\n const x = profile.width - profile.safeArea.right - w;\n const y = profile.safeArea.top;\n ctx.fillStyle = 'rgba(18,22,31,0.82)';\n roundRect(ctx, x, y, w, h, 10);\n ctx.fill();\n // A small \"recording\" dot.\n ctx.fillStyle = '#ef4444';\n ctx.beginPath();\n ctx.arc(x + padX + 6, y + h / 2, 6, 0, Math.PI * 2);\n ctx.fill();\n ctx.fillStyle = '#ffffff';\n ctx.textAlign = 'left';\n ctx.textBaseline = 'middle';\n ctx.font = font;\n ctx.fillText(label, x + padX + 24, y + h / 2 + 1);\n ctx.restore();\n}\n\nfunction drawChapterLabel(\n ctx: SKRSContext2D,\n o: { title: string; ordinal: number; tStart: number; tEnd: number },\n tOut: number,\n theme: ResolvedTheme,\n profile: OutputProfile,\n): void {\n const alpha = clamp(Math.min((tOut - o.tStart) / 260, (o.tEnd - tOut) / 320), 0, 1);\n if (alpha <= 0) return;\n ctx.save();\n ctx.globalAlpha = alpha;\n const font = '700 30px Inter Bold';\n ctx.font = font;\n const textW = ctx.measureText(o.title).width;\n const barW = textW + 96;\n const barH = 56;\n const x = (profile.width - barW) / 2;\n // Below the stage's chrome bar (never over the URL pill); safe-area top otherwise.\n const y = profile.stage ? profile.stage.content.y + 14 : profile.safeArea.top + 8;\n ctx.fillStyle = theme.accent;\n roundRect(ctx, x, y, barW, barH, 12);\n ctx.fill();\n ctx.fillStyle = '#ffffff';\n ctx.font = '600 16px Inter SemiBold';\n ctx.textAlign = 'left';\n ctx.textBaseline = 'middle';\n ctx.fillText(String(o.ordinal), x + 22, y + barH / 2 + 1);\n ctx.font = font;\n ctx.fillText(o.title, x + 48, y + barH / 2 + 1);\n ctx.restore();\n}\n\nfunction captionAlpha(o: CaptionOverlay, tOut: number): number {\n return clamp(Math.min((tOut - o.tStart) / FADE_MS, (o.tEnd - tOut) / FADE_MS), 0, 1);\n}\n\nfunction drawCaption(ctx: SKRSContext2D, o: CaptionOverlay, tOut: number, theme: ResolvedTheme): void {\n const alpha = captionAlpha(o, tOut);\n if (alpha <= 0) return;\n ctx.save();\n ctx.globalAlpha = alpha;\n\n // Card\n ctx.shadowColor = 'rgba(0,0,0,0.30)';\n ctx.shadowBlur = 18;\n ctx.shadowOffsetY = 4;\n ctx.fillStyle = theme.surface;\n roundRect(ctx, o.box.x, o.box.y, o.box.w, o.box.h, theme.radius);\n ctx.fill();\n ctx.shadowColor = 'transparent';\n\n // Step badge chip (omitted for styles that don't number captions)\n let badgeW = 0;\n const bx = o.box.x + 26;\n if (o.showBadge) {\n const badgeText = `${o.ordinal}/${o.totalSteps}`;\n const badgeFont = `600 15px Inter SemiBold`;\n badgeW = Math.ceil(measureText(badgeText, badgeFont)) + 20;\n const badgeH = 26;\n const by = o.box.y + o.box.h / 2 - badgeH / 2;\n ctx.fillStyle = theme.accent;\n roundRect(ctx, bx, by, badgeW, badgeH, 13);\n ctx.fill();\n ctx.fillStyle = '#ffffff';\n ctx.font = badgeFont;\n ctx.textBaseline = 'middle';\n ctx.textAlign = 'center';\n ctx.fillText(badgeText, bx + badgeW / 2, by + badgeH / 2 + 1);\n }\n\n // Caption text\n const lineH = Math.round(o.fontPx * 1.35);\n const textX = o.showBadge ? bx + badgeW + 14 : bx;\n const textTop = o.box.y + (o.box.h - o.lines.length * lineH) / 2;\n ctx.fillStyle = theme.onSurface;\n ctx.font = `${o.fontPx}px Inter Medium`;\n ctx.textAlign = 'left';\n ctx.textBaseline = 'middle';\n o.lines.forEach((line, i) => {\n ctx.fillText(line, textX, textTop + i * lineH + lineH / 2 + 1);\n });\n ctx.restore();\n}\n\n/** The failure clip's closing card: what step broke and why, in evidence red. */\nexport function drawFailureCard(\n ctx: SKRSContext2D,\n card: { stepRef: string; message: string; tStart: number },\n tOut: number,\n theme: ResolvedTheme,\n profile: OutputProfile,\n): void {\n const { width, height } = profile;\n const g = ctx.createLinearGradient(0, 0, 0, height);\n g.addColorStop(0, '#1c1114');\n g.addColorStop(1, '#12090b');\n ctx.fillStyle = g;\n ctx.fillRect(0, 0, width, height);\n\n const t = tOut - card.tStart;\n const a = clamp(t / 300, 0, 1);\n ctx.save();\n ctx.globalAlpha = a;\n\n ctx.fillStyle = '#ef4444';\n roundRect(ctx, width / 2 - 32, height / 2 - 150, 64, 8, 4);\n ctx.fill();\n\n ctx.fillStyle = '#ffffff';\n ctx.font = `52px Inter Bold`;\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n ctx.fillText('Flow failed', width / 2, height / 2 - 70);\n\n ctx.fillStyle = '#fca5a5';\n ctx.font = `600 30px Inter SemiBold`;\n ctx.fillText(`at step ${card.stepRef}`, width / 2, height / 2 - 12);\n\n // Error message, wrapped to a readable measure.\n ctx.fillStyle = 'rgba(255,255,255,0.75)';\n ctx.font = `24px Inter`;\n const maxW = Math.min(1200, width - 200);\n const words = card.message.replace(/\\s+/g, ' ').split(' ');\n const lines: string[] = [];\n let line = '';\n for (const w of words) {\n const probe = line ? `${line} ${w}` : w;\n if (ctx.measureText(probe).width > maxW && line) {\n lines.push(line);\n line = w;\n if (lines.length >= 3) break;\n } else line = probe;\n }\n if (lines.length < 3 && line) lines.push(line);\n else if (line && lines.length >= 3) lines[2] = `${lines[2]!.slice(0, -1)}…`;\n lines.forEach((l, i) => ctx.fillText(l, width / 2, height / 2 + 48 + i * 36));\n ctx.restore();\n}\n\nexport function drawTitleCard(\n ctx: SKRSContext2D,\n card: TitleCardOverlay,\n tOut: number,\n theme: ResolvedTheme,\n profile: OutputProfile,\n): void {\n const { width, height } = profile;\n // Ground with the same gradient the stage uses, so the dip into footage feels continuous.\n const g = ctx.createLinearGradient(0, 0, 0, height);\n g.addColorStop(0, theme.bgSubtle);\n g.addColorStop(1, theme.bg);\n ctx.fillStyle = g;\n ctx.fillRect(0, 0, width, height);\n\n // Staggered entrance: bar → title → subtitle, each rising 16px as it fades in. A group fade\n // with zero motion reads as a slide; a 200ms stagger reads as designed.\n const t = tOut - card.tStart;\n const enter = (delay: number) => {\n const u = clamp((t - delay) / 380, 0, 1);\n const e = 1 - (1 - u) * (1 - u) * (1 - u); // easeOutCubic\n return { alpha: u, rise: 16 * (1 - e) };\n };\n const bar = enter(0);\n const title = enter(130);\n const sub = enter(240);\n\n ctx.save();\n ctx.globalAlpha = bar.alpha;\n ctx.fillStyle = theme.accent;\n roundRect(ctx, width / 2 - 32, height / 2 - 110 + bar.rise, 64, 8, 4);\n ctx.fill();\n\n ctx.globalAlpha = title.alpha;\n ctx.fillStyle = '#ffffff';\n ctx.font = `56px Inter Bold`;\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n ctx.fillText(card.title, width / 2, height / 2 - 20 + title.rise);\n\n if (card.subtitle) {\n ctx.globalAlpha = sub.alpha;\n ctx.fillStyle = theme.onSurfaceDim;\n ctx.font = `26px Inter`;\n ctx.fillText(card.subtitle, width / 2, height / 2 + 44 + sub.rise);\n }\n ctx.restore();\n}\n","import sharp from 'sharp';\nimport { createCanvas, ImageData, type Canvas } from '@napi-rs/canvas';\nimport type { BundleData } from '../../bundle/types.js';\nimport { frameIndexForTime, framePath } from '../../bundle/reader.js';\n\nconst LRU_SIZE = 6;\n\n/**\n * Timestamp-indexed source-frame store with an LRU of decoded frames and one-ahead\n * prefetch. Access during a render is monotonic in time, so a small cache wins.\n */\nexport class FrameStore {\n private cache = new Map<number, Promise<Canvas>>();\n\n constructor(private readonly bundle: BundleData) {}\n\n /** Decoded canvas for the frame that should be on screen at capture-relative tMs. */\n async frameForTime(tMs: number): Promise<Canvas> {\n const idx = frameIndexForTime(this.bundle.frames, tMs);\n const canvas = await this.get(idx);\n // Prefetch the next distinct frame while this one is being drawn.\n if (idx + 1 < this.bundle.frames.length) void this.get(idx + 1);\n return canvas;\n }\n\n /**\n * The frame at tMs plus its successor with a blend factor: the capture is ~20fps but output\n * is 30fps, so nearest-frame playback holds each source frame in a 2-1-2-1 judder pattern.\n * Blending adjacent frames during real motion smooths it without optical flow.\n */\n async framePairForTime(tMs: number): Promise<{ a: Canvas; b: Canvas | null; mix: number; gapMs: number }> {\n const idx = frameIndexForTime(this.bundle.frames, tMs);\n const a = await this.get(idx);\n if (idx + 1 >= this.bundle.frames.length) return { a, b: null, mix: 0, gapMs: Infinity };\n const t0 = this.bundle.frames[idx]!.t;\n const t1 = this.bundle.frames[idx + 1]!.t;\n const gapMs = t1 - t0;\n const mix = gapMs > 0 ? Math.min(1, Math.max(0, (tMs - t0) / gapMs)) : 0;\n const b = await this.get(idx + 1);\n return { a, b, mix, gapMs };\n }\n\n private get(idx: number): Promise<Canvas> {\n const hit = this.cache.get(idx);\n if (hit) {\n // refresh recency\n this.cache.delete(idx);\n this.cache.set(idx, hit);\n return hit;\n }\n const promise = this.decode(idx);\n this.cache.set(idx, promise);\n while (this.cache.size > LRU_SIZE) {\n const oldest = this.cache.keys().next().value as number;\n this.cache.delete(oldest);\n }\n return promise;\n }\n\n private async decode(idx: number): Promise<Canvas> {\n const { data, info } = await sharp(framePath(this.bundle, idx))\n .ensureAlpha()\n .raw()\n .toBuffer({ resolveWithObject: true });\n const canvas = createCanvas(info.width, info.height);\n const ctx = canvas.getContext('2d');\n ctx.putImageData(new ImageData(new Uint8ClampedArray(data.buffer, data.byteOffset, data.byteLength), info.width, info.height), 0, 0);\n return canvas;\n }\n}\n","import { spawn } from 'node:child_process';\nimport { createRequire } from 'node:module';\n\nconst require = createRequire(import.meta.url);\n\n/** Resolve the ffmpeg binary: $PLAYHEAD_FFMPEG override, else the bundled ffmpeg-static build. */\nexport function ffmpegPath(): string {\n if (process.env.PLAYHEAD_FFMPEG) return process.env.PLAYHEAD_FFMPEG;\n const p = require('ffmpeg-static') as string | null;\n if (!p) throw new Error('ffmpeg-static did not provide a binary; set PLAYHEAD_FFMPEG');\n return p;\n}\n\nexport function ffprobePath(): string {\n if (process.env.PLAYHEAD_FFPROBE) return process.env.PLAYHEAD_FFPROBE;\n const mod = require('ffprobe-static') as { path: string };\n return mod.path;\n}\n\nexport interface RunResult {\n code: number;\n stdout: string;\n stderr: string;\n}\n\n/** Run ffmpeg/ffprobe to completion, capturing output. For the streaming encoder see compose/render/encoder.ts. */\nexport function runBinary(bin: string, args: string[], stdin?: Buffer): Promise<RunResult> {\n return new Promise((resolve, reject) => {\n const child = spawn(bin, args, { stdio: ['pipe', 'pipe', 'pipe'] });\n const out: Buffer[] = [];\n const err: Buffer[] = [];\n child.stdout.on('data', (d) => out.push(d));\n child.stderr.on('data', (d) => err.push(d));\n child.on('error', reject);\n child.on('close', (code) => {\n resolve({\n code: code ?? -1,\n stdout: Buffer.concat(out).toString('utf8'),\n stderr: Buffer.concat(err).toString('utf8'),\n });\n });\n if (stdin) child.stdin.end(stdin);\n else child.stdin.end();\n });\n}\n\n/** Losslessly concatenate H.264 MP4s (same codec/params) into one file via the concat demuxer. */\nexport async function concatVideos(inputs: string[], outPath: string): Promise<void> {\n const { writeFile, mkdtemp, rm } = await import('node:fs/promises');\n const { join } = await import('node:path');\n const { tmpdir } = await import('node:os');\n const dir = await mkdtemp(join(tmpdir(), 'playhead-concat-'));\n const listPath = join(dir, 'list.txt');\n await writeFile(listPath, inputs.map((p) => `file '${p.replace(/'/g, \"'\\\\''\")}'`).join('\\n'));\n try {\n const res = await runBinary(ffmpegPath(), [\n '-hide_banner', '-loglevel', 'error',\n '-f', 'concat', '-safe', '0',\n '-i', listPath,\n '-c', 'copy',\n '-movflags', '+faststart',\n '-y', outPath,\n ]);\n if (res.code !== 0) throw new Error(`concat failed: ${res.stderr}`);\n } finally {\n await rm(dir, { recursive: true, force: true }).catch(() => {});\n }\n}\n\n/** Run ffmpeg, returning raw stdout bytes (for image2pipe extraction). */\nexport function runBinaryRaw(bin: string, args: string[]): Promise<{ code: number; stdout: Buffer; stderr: string }> {\n return new Promise((resolve, reject) => {\n const child = spawn(bin, args, { stdio: ['ignore', 'pipe', 'pipe'] });\n const out: Buffer[] = [];\n const err: Buffer[] = [];\n child.stdout.on('data', (d) => out.push(d));\n child.stderr.on('data', (d) => err.push(d));\n child.on('error', reject);\n child.on('close', (code) => {\n resolve({ code: code ?? -1, stdout: Buffer.concat(out), stderr: Buffer.concat(err).toString('utf8') });\n });\n });\n}\n","import { spawn, type ChildProcess } from 'node:child_process';\nimport { once } from 'node:events';\nimport { ffmpegPath } from '../../shared/ffmpeg.js';\n\n/**\n * Streaming H.264 encoder: raw RGBA frames in on stdin, MP4 out. Backpressure is\n * respected — write() resolves only when the pipe can take more.\n */\nexport class Encoder {\n private child: ChildProcess;\n private stderrTail: string[] = [];\n private exit: Promise<number>;\n\n constructor(outPath: string, width: number, height: number, fps: number) {\n this.child = spawn(\n ffmpegPath(),\n [\n '-hide_banner',\n '-loglevel', 'error',\n '-f', 'rawvideo',\n '-pix_fmt', 'rgba',\n '-s', `${width}x${height}`,\n '-r', String(fps),\n '-i', 'pipe:0',\n // A silent AAC track: some players/galleries refuse an audio-less MP4.\n '-f', 'lavfi',\n '-i', 'anullsrc=channel_layout=stereo:sample_rate=44100',\n '-c:v', 'libx264',\n '-preset', 'medium',\n '-crf', '18',\n '-pix_fmt', 'yuv420p',\n '-profile:v', 'high',\n '-c:a', 'aac',\n '-b:a', '96k',\n '-shortest',\n '-movflags', '+faststart',\n '-y',\n outPath,\n ],\n { stdio: ['pipe', 'ignore', 'pipe'] },\n );\n this.child.stderr!.on('data', (d: Buffer) => {\n this.stderrTail.push(d.toString('utf8'));\n if (this.stderrTail.length > 40) this.stderrTail.shift();\n });\n this.exit = new Promise((resolve, reject) => {\n this.child.on('error', reject);\n this.child.on('close', (code) => resolve(code ?? -1));\n });\n }\n\n async write(rgba: Buffer): Promise<void> {\n const stdin = this.child.stdin!;\n if (!stdin.writable) throw new Error(`ffmpeg closed early: ${this.stderrTail.join('')}`);\n if (!stdin.write(rgba)) {\n await once(stdin, 'drain');\n }\n }\n\n async finish(): Promise<void> {\n this.child.stdin!.end();\n const code = await this.exit;\n if (code !== 0) {\n throw new Error(`ffmpeg exited with code ${code}: ${this.stderrTail.join('')}`);\n }\n }\n}\n","import { createCanvas, type Canvas, type SKRSContext2D } from '@napi-rs/canvas';\nimport type { BundleData } from '../../bundle/types.js';\nimport type { ComposeManifest, TitleCardOverlay, StepMapEntry } from '../types.js';\nimport { stageContent } from '../types.js';\nimport { sampleSource } from '../timeline/pacing.js';\nimport { sampleCamera } from '../camera/interpolate.js';\nimport { sampleCursor, type CursorPlan } from '../cursor/path.js';\nimport { drawCursor, type CursorGlyph } from '../cursor/render.js';\nimport { drawOverlays, drawTitleCard, drawFailureCard } from '../overlays/draw.js';\nimport { roundRect } from '../overlays/text.js';\nimport { visibleRect, projectPoint, projectRect, clamp, type CameraPlane, type Rect } from '../../shared/geometry.js';\nimport { FrameStore } from './frameStore.js';\nimport { Encoder } from './encoder.js';\nimport { registerFonts } from '../../theme/index.js';\nimport { log } from '../../shared/log.js';\n\nconst SPOTLIGHT_KINDS = new Set(['click', 'dblclick', 'select']);\nconst SPOTLIGHT_LEAD_MS = 200;\nconst SPOTLIGHT_TAIL_MS = 650;\nconst SPOTLIGHT_MAX_DIM = 0.34;\n\n/** Render the full output from a bundle + compose manifest. Pure playback of the plan. */\nexport async function renderVideo(\n bundle: BundleData,\n manifest: ComposeManifest,\n outPath: string,\n): Promise<void> {\n registerFonts();\n const { profile, theme } = manifest;\n const { width, height, fps } = profile;\n // All camera math runs in stage-content space (the same space the planner and verifier use);\n // the renderer's only extra job is translating that space onto the frame at `content.x/y`.\n const content = stageContent(profile);\n const plane: CameraPlane = {\n vpW: manifest.viewport.w,\n vpH: manifest.viewport.h,\n outW: content.w,\n outH: content.h,\n };\n const frameScale = bundle.manifest.frameW / manifest.viewport.w;\n\n const store = new FrameStore(bundle);\n const encoder = new Encoder(outPath, width, height, fps);\n const canvas = createCanvas(width, height);\n const ctx = canvas.getContext('2d');\n ctx.imageSmoothingEnabled = true;\n ctx.imageSmoothingQuality = 'high';\n // Offscreen scratch for the spotlight (dim layer with a feathered punch-out).\n const spotCanvas = createCanvas(content.w, content.h);\n const spotCtx = spotCanvas.getContext('2d');\n\n const cursorPlan: CursorPlan = {\n segments: manifest.cursor,\n ripples: manifest.ripples,\n restStart:\n manifest.cursor.length > 0\n ? manifest.cursor[0]!.path[0]!\n : { x: manifest.viewport.w / 2, y: manifest.viewport.h * 0.6 },\n };\n const cards = new Map(\n manifest.overlays\n .filter((o): o is TitleCardOverlay => o.kind === 'titleCard')\n .map((c) => [c.cardId, c]),\n );\n const transitions = manifest.transitions ?? [];\n const spotlightSteps = manifest.steps.filter(\n (s) => SPOTLIGHT_KINDS.has(s.kind) && (s.focusRectVp ?? s.targetRectVp),\n );\n\n const start = Date.now();\n for (let i = 0; i < manifest.totalFrames; i++) {\n const tOut = (i * 1000) / fps;\n const { srcAt, segment } = sampleSource(manifest.segments, tOut);\n\n if (srcAt === null) {\n const failCard =\n segment.kind === 'card' && segment.cardId === 'failure'\n ? manifest.overlays.find((o) => o.kind === 'failureCard')\n : undefined;\n const card = segment.kind === 'card' ? cards.get(segment.cardId) : undefined;\n if (failCard && failCard.kind === 'failureCard') drawFailureCard(ctx, failCard, tOut, theme, profile);\n else if (card) drawTitleCard(ctx, card, tOut, theme, profile);\n else {\n ctx.fillStyle = theme.bg;\n ctx.fillRect(0, 0, width, height);\n }\n } else {\n const cam = sampleCamera(manifest.camera, tOut);\n const vis = visibleRect(cam, plane);\n\n // ---- the stage: matte background + card (chrome bar + footage) ----\n paintStageBackdrop(ctx, profile, theme);\n ctx.save();\n if (profile.stage) {\n paintStageCard(ctx, profile, theme, bundle.manifest.appUrl);\n roundRect(ctx, content.x, content.y, content.w, content.h, 0); // content area (card carries the radius)\n ctx.clip();\n }\n\n // ---- footage: frame blending kills 20→30fps judder during real motion ----\n const drawSrc = (img: Canvas, alpha: number) => {\n ctx.globalAlpha = alpha;\n ctx.drawImage(\n img,\n vis.x * frameScale, vis.y * frameScale, vis.w * frameScale, vis.h * frameScale,\n content.x, content.y, content.w, content.h,\n );\n ctx.globalAlpha = 1;\n };\n const pair = await store.framePairForTime(srcAt);\n // Blend only inside `source` segments (real motion): blending across a freeze would ghost\n // the NEXT action into a deliberate hold.\n if (segment.kind === 'source' && pair.b && pair.mix > 0.12 && pair.gapMs < 400) {\n drawSrc(pair.a, 1);\n drawSrc(pair.b, pair.mix);\n } else {\n drawSrc(pair.a, 1);\n }\n\n // ---- scene-boundary cross-dissolve: old footage fades into the new scene ----\n const tr = transitions.find((w) => tOut >= w.tStart && tOut <= w.tEnd);\n if (tr) {\n const u = clamp((tOut - tr.tStart) / Math.max(1, tr.tEnd - tr.tStart), 0, 1);\n if (u < 1) {\n const from = await store.frameForTime(tr.srcFrom);\n drawSrc(from, 1 - u);\n }\n }\n\n // ---- click spotlight: dim the surroundings, feather-punch the target ----\n const spot = activeSpotlight(spotlightSteps, tOut);\n if (spot) {\n const rect = spot.step.focusRectVp ?? spot.step.targetRectVp!;\n const proj = projectRect(rect, cam, plane);\n drawSpotlight(spotCtx, content, proj, spot.alpha);\n ctx.drawImage(spotCanvas, content.x, content.y);\n }\n\n // Cursor + ripples live on the source plane; project through the camera, then translate\n // into frame space by the stage origin.\n const cursorVp = sampleCursor(cursorPlan, tOut);\n const cursorOut = projectPoint(cursorVp, cam, plane);\n const rippleCenters = manifest.ripples.map((r) => {\n const p = projectPoint({ x: r.x, y: r.y }, cam, plane);\n return { x: p.x + content.x, y: p.y + content.y };\n });\n const glyph = cursorGlyphAt(manifest.steps, tOut);\n drawCursor(\n ctx,\n { x: cursorOut.x + content.x, y: cursorOut.y + content.y },\n cam.zoom,\n tOut,\n manifest.ripples,\n rippleCenters,\n theme,\n plane.outW / plane.vpW,\n glyph,\n );\n ctx.restore();\n }\n\n drawOverlays(ctx, manifest.overlays, tOut, theme, profile);\n await encoder.write(Buffer.from(ctx.getImageData(0, 0, width, height).data.buffer));\n\n if (i > 0 && i % 300 === 0) {\n const fpsNow = i / ((Date.now() - start) / 1000);\n log.debug(`rendered ${i}/${manifest.totalFrames} frames (${fpsNow.toFixed(0)} fps)`);\n }\n }\n await encoder.finish();\n const elapsed = (Date.now() - start) / 1000;\n log.ok(\n `rendered ${manifest.totalFrames} frames in ${elapsed.toFixed(1)}s (${(manifest.totalFrames / elapsed).toFixed(0)} fps) → ${outPath}`,\n );\n}\n\n/** Soft vertical gradient behind the stage, derived from the theme. */\nfunction paintStageBackdrop(ctx: SKRSContext2D, profile: { width: number; height: number }, theme: { bg: string; bgSubtle: string }): void {\n const g = ctx.createLinearGradient(0, 0, 0, profile.height);\n g.addColorStop(0, theme.bgSubtle);\n g.addColorStop(1, theme.bg);\n ctx.fillStyle = g;\n ctx.fillRect(0, 0, profile.width, profile.height);\n}\n\n/** The card: shadow, rounded body, browser-chrome bar (traffic dots + URL pill). */\nfunction paintStageCard(\n ctx: SKRSContext2D,\n profile: { stage?: { content: Rect; chromeH: number; radius: number }; width: number },\n theme: { surface: string; onSurfaceDim: string },\n appUrl: string,\n): void {\n const s = profile.stage!;\n const c = s.content;\n const cardX = c.x;\n const cardY = c.y - s.chromeH;\n const cardW = c.w;\n const cardH = c.h + s.chromeH;\n\n ctx.save();\n ctx.shadowColor = 'rgba(0,0,0,0.45)';\n ctx.shadowBlur = 42;\n ctx.shadowOffsetY = 14;\n ctx.fillStyle = '#20242e';\n roundRect(ctx, cardX, cardY, cardW, cardH, s.radius);\n ctx.fill();\n ctx.restore();\n\n if (s.chromeH > 0) {\n // Traffic dots\n const dotY = cardY + s.chromeH / 2;\n const dotR = Math.max(5, Math.round(s.chromeH * 0.14));\n const colors = ['#ff5f57', '#febc2e', '#28c840'];\n colors.forEach((col, i) => {\n ctx.fillStyle = col;\n ctx.beginPath();\n ctx.arc(cardX + 24 + i * (dotR * 2 + 9), dotY, dotR, 0, Math.PI * 2);\n ctx.fill();\n });\n // URL pill\n const url = displayUrl(appUrl);\n const pillH = Math.round(s.chromeH * 0.62);\n ctx.font = `500 ${Math.round(pillH * 0.52)}px Inter Medium`;\n const textW = ctx.measureText(url).width;\n const pillW = Math.min(cardW * 0.5, textW + 36);\n const pillX = cardX + (cardW - pillW) / 2;\n const pillY = cardY + (s.chromeH - pillH) / 2;\n ctx.fillStyle = 'rgba(255,255,255,0.08)';\n roundRect(ctx, pillX, pillY, pillW, pillH, pillH / 2);\n ctx.fill();\n ctx.fillStyle = 'rgba(255,255,255,0.55)';\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n ctx.fillText(url, pillX + pillW / 2, pillY + pillH / 2 + 1, pillW - 24);\n }\n}\n\nfunction displayUrl(appUrl: string): string {\n try {\n const u = new URL(appUrl);\n return u.host + (u.pathname !== '/' ? u.pathname : '');\n } catch {\n return appUrl;\n }\n}\n\n/** Which spotlight (if any) is active at tOut, with its ramped alpha. */\nfunction activeSpotlight(\n steps: StepMapEntry[],\n tOut: number,\n): { step: StepMapEntry; alpha: number } | null {\n for (const step of steps) {\n const from = step.outBeat - SPOTLIGHT_LEAD_MS;\n const to = step.outBeat + SPOTLIGHT_TAIL_MS;\n if (tOut < from || tOut > to) continue;\n const rampIn = clamp((tOut - from) / 180, 0, 1);\n const rampOut = clamp((to - tOut) / 250, 0, 1);\n return { step, alpha: SPOTLIGHT_MAX_DIM * Math.min(rampIn, rampOut) };\n }\n return null;\n}\n\n/** Dim layer with a feathered punch-out around the target, built on the scratch canvas. */\nfunction drawSpotlight(sctx: SKRSContext2D, content: Rect, proj: Rect, alpha: number): void {\n sctx.clearRect(0, 0, content.w, content.h);\n sctx.fillStyle = `rgba(6,8,14,${alpha.toFixed(3)})`;\n sctx.fillRect(0, 0, content.w, content.h);\n const pad = 14;\n sctx.save();\n sctx.globalCompositeOperation = 'destination-out';\n sctx.shadowColor = '#ffffff';\n sctx.shadowBlur = 30;\n sctx.fillStyle = '#ffffff';\n roundRect(sctx, proj.x - pad, proj.y - pad, proj.w + pad * 2, proj.h + pad * 2, 10);\n sctx.fill();\n sctx.restore();\n}\n\n/** Glyph for the active step: I-beam while typing, arrow otherwise. */\nfunction cursorGlyphAt(steps: StepMapEntry[], tOut: number): CursorGlyph {\n for (const s of steps) {\n if (s.kind === 'type' && tOut >= s.outStart && tOut <= s.outEnd) return 'ibeam';\n }\n return 'arrow';\n}\n","import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { createHash } from 'node:crypto';\nimport { createRequire } from 'node:module';\n\nconst require = createRequire(import.meta.url);\nconst ffprobePath: string = require('ffprobe-static').path;\nconst exec = promisify(execFile);\n\nexport interface NarrationOptions {\n /** 'say' — macOS built-in (zero deps, Mac-only). 'kokoro' — natural neural voice, offline,\n * cross-platform, via the optional kokoro-js package. */\n provider: 'say' | 'kokoro';\n /** say: a macOS voice name (Samantha). kokoro: a voice id (af_heart, am_michael, …). */\n voice?: string;\n /** say: words per minute. kokoro: playback speed × 100 (100 = 1.0×). */\n rate?: number;\n}\n\nexport interface NarrationLine {\n stepRef: string;\n text: string;\n}\n\nexport interface NarrationClip {\n stepRef: string;\n file: string;\n durationMs: number;\n}\n\n/** A text-to-speech backend: text → an audio file on disk. */\ninterface TtsProvider {\n readonly name: string;\n synth(text: string, outFile: string): Promise<void>;\n}\n\nclass SayProvider implements TtsProvider {\n readonly name = 'say';\n constructor(private voice: string, private rate: number) {}\n async synth(text: string, outFile: string): Promise<void> {\n // Pass the text via a file so em-dashes / quotes / apostrophes survive shell escaping.\n const txt = `${outFile}.txt`;\n await writeFile(txt, text);\n await exec('say', ['-v', this.voice, '-r', String(this.rate), '-f', txt, '-o', outFile]);\n }\n}\n\n/**\n * Kokoro — a natural, offline neural voice (the Kokoro-82M model) via the optional pure-Node\n * `kokoro-js` package. The model (~90MB q8) loads ONCE on the first line and is reused for the\n * rest, so a multi-line narration pays the load cost a single time. Output is WAV.\n *\n * kokoro-js is NOT a hard dependency (it pulls onnxruntime, ~400MB) — it is lazily imported and,\n * if absent, produces an actionable error. On networks that intercept TLS (corporate proxies),\n * set NODE_EXTRA_CA_CERTS so the one-time model download from Hugging Face can verify.\n */\nclass KokoroProvider implements TtsProvider {\n readonly name = 'kokoro';\n private tts: Promise<{ generate: (t: string, o: { voice: string; speed: number }) => Promise<{ save: (p: string) => Promise<void> }> }> | null = null;\n constructor(private voice: string, private speed: number) {}\n\n private load() {\n if (this.tts) return this.tts;\n this.tts = (async () => {\n let mod: { KokoroTTS: { from_pretrained: (id: string, o: object) => Promise<unknown> } };\n try {\n mod = (await import('kokoro-js' as string)) as typeof mod;\n } catch {\n throw new Error(\n \"the 'kokoro' voice needs the optional kokoro-js package — install it with `npm i -g kokoro-js` \" +\n '(or add it to your project). It bundles the neural model runtime (~400MB); the base playhead-cli stays lean.',\n );\n }\n return (await mod.KokoroTTS.from_pretrained('onnx-community/Kokoro-82M-v1.0-ONNX', {\n dtype: 'q8',\n device: 'cpu',\n })) as Awaited<NonNullable<KokoroProvider['tts']>>;\n })();\n return this.tts;\n }\n\n async synth(text: string, outFile: string): Promise<void> {\n const tts = await this.load();\n const audio = await tts.generate(text, { voice: this.voice, speed: this.speed });\n await audio.save(outFile); // WAV\n }\n}\n\nfunction providerFor(opts: NarrationOptions): { provider: TtsProvider; voice: string; rate: number } {\n switch (opts.provider) {\n case 'say': {\n const voice = opts.voice ?? 'Samantha';\n const rate = opts.rate ?? 178;\n return { provider: new SayProvider(voice, rate), voice, rate };\n }\n case 'kokoro': {\n // Two curated voices only — Heart (default) and Michael. Friendly aliases map to the ids.\n const KOKORO_VOICES: Record<string, string> = {\n heart: 'af_heart',\n af_heart: 'af_heart',\n michael: 'am_michael',\n am_michael: 'am_michael',\n };\n const requested = opts.voice ?? 'heart';\n const voice = KOKORO_VOICES[requested];\n if (!voice) throw new Error(`kokoro voice must be 'heart' (default) or 'michael', got '${requested}'`);\n const rate = opts.rate ?? 100; // ×100 → 1.0 playback speed\n return { provider: new KokoroProvider(voice, rate / 100), voice, rate };\n }\n default:\n throw new Error(`unknown TTS provider: ${(opts as { provider: string }).provider}`);\n }\n}\n\nasync function probeDurationMs(file: string): Promise<number> {\n const { stdout } = await exec(ffprobePath, [\n '-v', 'error', '-show_entries', 'format=duration', '-of', 'csv=p=0', file,\n ]);\n return Math.round(parseFloat(stdout.trim()) * 1000);\n}\n\n/**\n * Synthesize one clip per line. Clips are cached by a content hash of\n * (provider, voice, rate, text) so re-renders reuse them — keeping compose offline\n * and deterministic (same text+voice → same audio → same timing).\n */\nexport async function synthesizeNarration(\n lines: NarrationLine[],\n opts: NarrationOptions,\n cacheDir: string,\n): Promise<Map<string, NarrationClip>> {\n await mkdir(cacheDir, { recursive: true });\n const { provider, voice, rate } = providerFor(opts);\n const ext = provider.name === 'kokoro' ? 'wav' : 'aiff';\n const out = new Map<string, NarrationClip>();\n for (const { stepRef, text } of lines) {\n const key = createHash('sha256').update(`${provider.name}|${voice}|${rate}|${text}`).digest('hex').slice(0, 16);\n const file = join(cacheDir, `${key}.${ext}`);\n if (!existsSync(file)) await provider.synth(text, file);\n out.set(stepRef, { stepRef, file, durationMs: await probeDurationMs(file) });\n }\n return out;\n}\n","import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { rename, mkdir } from 'node:fs/promises';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { createRequire } from 'node:module';\nimport type { StepMapEntry, ClickRipple } from '../compose/types.js';\nimport type { NarrationClip } from './tts.js';\nimport { AUDIO_LEAD_MS } from './timing.js';\n\nconst require = createRequire(import.meta.url);\nconst ffmpegPath: string = require('ffmpeg-static');\nconst exec = promisify(execFile);\n\nexport interface PlacedClip {\n stepRef: string;\n /** Output-clock ms the clip starts playing. */\n tStart: number;\n durMs: number;\n}\n\nexport interface AudioBedOptions {\n /** Narration clips per stepRef (absent = no narration). */\n narration?: Map<string, NarrationClip>;\n /** Click-beat times (output clock) that get a soft synthesized tick. */\n sfxBeats?: ClickRipple[];\n /** User-supplied music bed (no asset is bundled). */\n music?: { file: string; gainDb: number };\n /** Directory for the synthesized click sample (cached). */\n cacheDir: string;\n}\n\n/**\n * Build the full audio track — narration clips at their step starts, click ticks at ripple\n * beats, an optional music bed ducked under narration — normalize loudness (EBU R128, I=-16),\n * and mux it onto the rendered MP4. Returns where each narration clip landed so verification\n * can reason about voice windows.\n */\nexport async function mixAudio(\n videoPath: string,\n steps: StepMapEntry[],\n durationMs: number,\n opts: AudioBedOptions,\n): Promise<PlacedClip[]> {\n const placed = (opts.narration ? steps : [])\n .map((s) => ({ start: Math.round(s.outStart + AUDIO_LEAD_MS), clip: opts.narration!.get(s.stepRef) }))\n .filter((p): p is { start: number; clip: NarrationClip } => p.clip !== undefined);\n const beats = opts.sfxBeats ?? [];\n const hasMusic = !!opts.music;\n if (placed.length === 0 && beats.length === 0 && !hasMusic) return [];\n\n const durSec = (durationMs / 1000).toFixed(3);\n const args = ['-y', '-loglevel', 'error', '-i', videoPath];\n const inputs: string[] = []; // filter labels for the final mix\n const filters: string[] = [];\n let inputIdx = 1;\n\n // Silent full-length base keeps the mix spanning the whole video.\n args.push('-f', 'lavfi', '-t', durSec, '-i', 'anullsrc=r=44100:cl=stereo');\n const baseIdx = inputIdx++;\n inputs.push(`[${baseIdx}]`);\n\n // Narration clips, delayed to their step starts, pre-mixed into one voice bus.\n let voiceBus: string | null = null;\n if (placed.length > 0) {\n const labels: string[] = [];\n placed.forEach((p, i) => {\n args.push('-i', p.clip.file);\n const idx = inputIdx++;\n filters.push(\n `[${idx}]aformat=sample_rates=44100:channel_layouts=stereo,adelay=${p.start}|${p.start}[v${i}]`,\n );\n labels.push(`[v${i}]`);\n });\n filters.push(`${labels.join('')}amix=inputs=${labels.length}:normalize=0:duration=longest[voice]`);\n voiceBus = '[voice]';\n }\n\n // Click SFX: one synthesized sample, split and delayed to each beat.\n if (beats.length > 0) {\n const click = await ensureClickSample(opts.cacheDir);\n args.push('-i', click);\n const idx = inputIdx++;\n const splits = beats.map((_, i) => `[c${i}]`).join('');\n filters.push(`[${idx}]aformat=sample_rates=44100:channel_layouts=stereo,asplit=${beats.length}${splits}`);\n const labels: string[] = [];\n beats.forEach((b, i) => {\n const at = Math.max(0, Math.round(b.tOut));\n filters.push(`[c${i}]adelay=${at}|${at}[ck${i}]`);\n labels.push(`[ck${i}]`);\n });\n filters.push(`${labels.join('')}amix=inputs=${labels.length}:normalize=0:duration=longest[sfx]`);\n inputs.push('[sfx]');\n }\n\n // Music bed: looped to length, faded out, gained down — and DUCKED under narration.\n if (opts.music) {\n args.push('-stream_loop', '-1', '-i', opts.music.file);\n const idx = inputIdx++;\n const fadeStart = Math.max(0, durationMs / 1000 - 1.8).toFixed(2);\n filters.push(\n `[${idx}]aformat=sample_rates=44100:channel_layouts=stereo,atrim=0:${durSec},` +\n `volume=${opts.music.gainDb}dB,afade=t=out:st=${fadeStart}:d=1.8[mraw]`,\n );\n if (voiceBus) {\n // Duplicate the voice bus: one copy keys the compressor, one goes to the mix.\n filters.push(`${voiceBus}asplit=2[vmain][vkey]`);\n filters.push(`[mraw][vkey]sidechaincompress=threshold=0.02:ratio=8:attack=40:release=400[mduck]`);\n inputs.push('[mduck]', '[vmain]');\n voiceBus = null;\n } else {\n inputs.push('[mraw]');\n }\n }\n if (voiceBus) inputs.push(voiceBus);\n\n filters.push(\n `${inputs.join('')}amix=inputs=${inputs.length}:normalize=0:duration=longest,` +\n `loudnorm=I=-16:TP=-1.5:LRA=11[mix]`,\n );\n\n const tmp = videoPath.replace(/\\.mp4$/, '.audio.tmp.mp4');\n args.push(\n '-filter_complex', filters.join(';'),\n '-map', '0:v:0', '-map', '[mix]',\n '-c:v', 'copy', '-c:a', 'aac', '-b:a', '160k',\n '-shortest', '-movflags', '+faststart',\n tmp,\n );\n await exec(ffmpegPath, args, { maxBuffer: 1 << 24 });\n await rename(tmp, videoPath);\n return placed.map((p) => ({ stepRef: p.clip.stepRef, tStart: p.start, durMs: p.clip.durationMs }));\n}\n\n/** Synthesize the click sample once: a soft 2-tone tick with a fast decay (no bundled assets). */\nasync function ensureClickSample(cacheDir: string): Promise<string> {\n await mkdir(cacheDir, { recursive: true });\n const file = join(cacheDir, 'click.wav');\n if (existsSync(file)) return file;\n await exec(ffmpegPath, [\n '-y', '-loglevel', 'error',\n '-f', 'lavfi', '-i', 'sine=frequency=1250:duration=0.05',\n '-f', 'lavfi', '-i', 'sine=frequency=2500:duration=0.03',\n '-filter_complex',\n '[0]volume=0.5[a];[1]volume=0.22[b];[a][b]amix=inputs=2:normalize=0,afade=t=in:d=0.004,afade=t=out:st=0.014:d=0.036,aformat=sample_rates=44100:channel_layouts=stereo',\n file,\n ]);\n return file;\n}\n","import { join } from 'node:path';\nimport { writeFile } from 'node:fs/promises';\nimport type { BundleData } from '../bundle/types.js';\nimport type { Spec } from '../spec/schema.js';\nimport { resolveResolution } from '../spec/schema.js';\nimport { resolveTheme, type ResolvedTheme } from '../theme/index.js';\nimport type { ComposeDiagnostics, ComposeManifest, OutputProfile } from './types.js';\nimport { profileForAspect, withStage } from './types.js';\nimport { kindProfile } from './kinds.js';\nimport { buildTimeline, pacingConfig } from './timeline/pacing.js';\nimport { planCamera } from './camera/planner.js';\nimport { planCursor } from './cursor/path.js';\nimport { buildOverlays } from './overlays/build.js';\nimport { renderVideo } from './render/renderer.js';\nimport { registerFonts } from '../theme/index.js';\nimport { sha256File } from '../bundle/hash.js';\nimport { log } from '../shared/log.js';\nimport { actionEvents } from '../capture/events.js';\nimport { writeCaption, writeNarration, type StepTexts } from './captions.js';\nimport { flattenSteps } from '../spec/schema.js';\nimport { synthesizeNarration, type NarrationClip } from '../audio/tts.js';\nimport { mixAudio } from '../audio/mux.js';\n\nexport interface ComposeResult {\n videoPath: string;\n manifestPath: string;\n manifest: ComposeManifest;\n}\n\n/** Pure planning: bundle + spec + theme → compose manifest. No rendering. */\n/** Per-step caption/narration text from the LIVE spec, keyed by stepRef — so text edits are a\n * re-compose, never a re-capture. */\nexport function specStepTexts(spec: Spec): Map<string, StepTexts> {\n const map = new Map<string, StepTexts>();\n for (const a of flattenSteps(spec)) {\n const s = a.step;\n if (s.caption || s.narration) {\n map.set(`${a.sceneId}/${a.stepIndex}`, {\n ...(s.caption ? { caption: s.caption } : {}),\n ...(s.narration ? { narration: s.narration } : {}),\n });\n }\n }\n return map;\n}\n\nexport function plan(\n bundle: BundleData,\n spec: Spec,\n theme?: ResolvedTheme,\n profile?: OutputProfile,\n audioMs?: Map<string, number>,\n): ComposeManifest {\n registerFonts();\n const resolvedTheme = theme ?? resolveTheme(spec);\n const kind = kindProfile(spec.output.kind);\n let prof: OutputProfile =\n profile ?? profileForAspect(spec.output.aspect, resolveResolution(spec), spec.output.fps);\n // The stage (matte + card + browser chrome) is the produced look; bug-repro stays literal.\n if (kind.stage && !prof.stage) prof = withStage(prof, true);\n const diagnostics: ComposeDiagnostics = { overflows: [], cameraFallbacks: [], clockWarnings: [] };\n const cfg = pacingConfig(spec.output.pacing ?? kind.pacing, kind);\n // Long-form teaching dwell: stretch the min-step, per-action holds, and outro so\n // each screen lingers. Idle-gap trimming and title card stay fixed (they're not dwell).\n const dwell = spec.output.dwellScale;\n if (dwell && dwell !== 1) {\n cfg.minStepMs *= dwell;\n cfg.outroMs *= dwell;\n for (const k of Object.keys(cfg.holds) as (keyof typeof cfg.holds)[]) cfg.holds[k] *= dwell;\n }\n const timeline = buildTimeline(bundle.events, cfg, audioMs);\n\n // Closing card: a title-card-styled segment appended after the outro.\n const END_CARD_MS = 2400;\n if (spec.output.endCard) {\n const endStart = timeline.durationMs;\n timeline.segments.push({ kind: 'card', outStart: endStart, outEnd: endStart + END_CARD_MS, cardId: 'end' });\n timeline.durationMs += END_CARD_MS;\n }\n // FAILURE CLIP: a partial bundle (capture died mid-run) composes into a diagnosis — the\n // captured footage plays through, then holds on a red card naming the step and the error.\n // This is the artifact a red CI run hands the developer: watch what happened, not a stack line.\n const FAILURE_CARD_MS = 3200;\n if (bundle.manifest.partial && bundle.manifest.failure) {\n const failStart = timeline.durationMs;\n timeline.segments.push({ kind: 'card', outStart: failStart, outEnd: failStart + FAILURE_CARD_MS, cardId: 'failure' });\n timeline.durationMs += FAILURE_CARD_MS;\n }\n\n // Clock sanity: warn when the action beat has no frame within 150ms after it.\n for (const step of timeline.steps) {\n const hasFrame = bundle.frames.some((f) => f.t >= step.srcAction && f.t <= step.srcAction + 150);\n if (!hasFrame && step.kind !== 'wait' && step.kind !== 'expect') {\n diagnostics.clockWarnings.push(`${step.stepRef}: no source frame within 150ms after the action`);\n }\n }\n\n const camera = planCamera(timeline.steps, bundle.events, prof, timeline.durationMs, {\n emphasis: kind.cameraEmphasis,\n });\n diagnostics.cameraFallbacks.push(...camera.fallbacks);\n const cursor = planCursor(timeline.steps, bundle.events);\n\n // Cross-dissolve at scene boundaries: the old footage (held at its last frame) fades into the\n // new scene instead of a hard cut.\n const transitions: { tStart: number; tEnd: number; srcFrom: number }[] = [];\n for (let i = 1; i < timeline.steps.length; i++) {\n const prev = timeline.steps[i - 1]!;\n const cur = timeline.steps[i]!;\n if (cur.sceneId !== prev.sceneId) {\n const tStart = cur.outStart;\n transitions.push({ tStart, tEnd: tStart + 280, srcFrom: Math.max(0, prev.srcSettled - 1) });\n }\n }\n\n const subtitle = spec.subtitle ?? safeHost(bundle.manifest.appUrl);\n const sceneTitles = new Map(\n spec.scenes.filter((s) => s.title).map((s) => [s.id, s.title as string]),\n );\n const overlays = buildOverlays(\n timeline.steps,\n bundle.events,\n resolvedTheme,\n prof,\n spec.title,\n subtitle,\n cfg.titleCardMs,\n diagnostics,\n kind,\n sceneTitles,\n camera.keyframes,\n specStepTexts(spec),\n );\n if (spec.output.endCard && !bundle.manifest.partial) {\n const endStart = timeline.durationMs - END_CARD_MS;\n overlays.push({ kind: 'dip', tStart: endStart - 350, tEnd: endStart, direction: 'out' });\n overlays.push({\n kind: 'titleCard',\n cardId: 'end',\n title: spec.output.endCard.title,\n ...(spec.output.endCard.subtitle ? { subtitle: spec.output.endCard.subtitle } : {}),\n tStart: endStart,\n tEnd: timeline.durationMs,\n });\n }\n if (bundle.manifest.partial && bundle.manifest.failure) {\n const failStart = timeline.durationMs - FAILURE_CARD_MS;\n overlays.push({ kind: 'dip', tStart: failStart - 300, tEnd: failStart, direction: 'out' });\n overlays.push({\n kind: 'failureCard',\n stepRef: bundle.manifest.failure.stepRef,\n message: bundle.manifest.failure.message,\n tStart: failStart,\n tEnd: timeline.durationMs,\n });\n }\n\n const totalFrames = Math.ceil((timeline.durationMs / 1000) * prof.fps);\n return {\n schema: 'playhead/compose@1',\n profile: prof,\n viewport: bundle.manifest.viewport,\n durationMs: timeline.durationMs,\n totalFrames,\n segments: timeline.segments,\n camera: camera.keyframes,\n cursor: cursor.segments,\n ripples: cursor.ripples,\n overlays,\n ...(transitions.length > 0 ? { transitions } : {}),\n steps: timeline.steps,\n theme: resolvedTheme,\n diagnostics,\n bundleHashes: bundle.manifest.hashes,\n };\n}\n\nexport interface ComposeOptions {\n outDir: string;\n fileName?: string;\n theme?: ResolvedTheme;\n profile?: OutputProfile;\n}\n\n/** Full composition: plan + render + write manifest. Never touches the live app. */\nexport async function compose(bundle: BundleData, spec: Spec, opts: ComposeOptions): Promise<ComposeResult> {\n // Voice narration (optional): synthesize each step's spoken line first, so pacing\n // can grow every step to fit it. TTS is local (macOS `say`) and cached in the bundle.\n const audioCfg = spec.output.audio;\n let narration: Map<string, NarrationClip> | undefined;\n let audioMs: Map<string, number> | undefined;\n if (audioCfg && audioCfg.narration === 'tts') {\n const texts = specStepTexts(spec);\n const lines = actionEvents(bundle.events)\n .map((e) => {\n const ref = `${e.sceneId}/${e.stepIndex}`;\n return { stepRef: ref, text: writeNarration(e, texts.get(ref)) };\n })\n .filter((l): l is { stepRef: string; text: string } => typeof l.text === 'string' && l.text.length > 0);\n log.info(`synthesizing narration: ${lines.length} lines (${audioCfg.provider}, voice ${audioCfg.voice ?? 'Samantha'})`);\n try {\n narration = await synthesizeNarration(lines, audioCfg, join(opts.outDir, 'narration'));\n audioMs = new Map([...narration].map(([k, v]) => [k, v.durationMs]));\n } catch (e) {\n // A host without the TTS binary (e.g. Linux CI with provider `say`) must not kill the\n // render — degrade to a silent video LOUDLY. `playhead doctor --ci` reports this upfront.\n log.warn(`narration unavailable on this host (${(e as Error).message.split('\\n')[0]}) — rendering WITHOUT voice`);\n narration = undefined;\n audioMs = undefined;\n }\n }\n\n const manifest = plan(bundle, spec, opts.theme, opts.profile, audioMs);\n for (const w of manifest.diagnostics.clockWarnings) log.warn(w);\n for (const f of manifest.diagnostics.cameraFallbacks) log.warn(f);\n\n const videoPath = join(opts.outDir, opts.fileName ?? 'out.mp4');\n log.info(\n `composing ${(manifest.durationMs / 1000).toFixed(1)}s (${manifest.totalFrames} frames @ ${manifest.profile.fps}fps, ${manifest.profile.width}x${manifest.profile.height})`,\n );\n await renderVideo(bundle, manifest, videoPath);\n\n // Audio bed: narration + click SFX + (user-supplied) music, ducked and loudness-normalized.\n if (audioCfg && (narration || audioCfg.sfx || audioCfg.music)) {\n const clips = await mixAudio(videoPath, manifest.steps, manifest.durationMs, {\n ...(narration ? { narration } : {}),\n ...(audioCfg.sfx ? { sfxBeats: manifest.ripples } : {}),\n ...(audioCfg.music ? { music: audioCfg.music } : {}),\n cacheDir: join(opts.outDir, 'narration'),\n });\n if (narration) {\n manifest.audio = {\n narrated: true,\n provider: audioCfg.provider,\n voice: audioCfg.voice ?? 'Samantha',\n lines: clips.length,\n clips,\n };\n }\n log.info(\n `✓ audio: ${clips.length} narration line(s)` +\n `${audioCfg.sfx ? `, ${manifest.ripples.length} click(s)` : ''}` +\n `${audioCfg.music ? ', music bed' : ''} → ${videoPath}`,\n );\n }\n\n manifest.videoSha256 = await sha256File(videoPath);\n const manifestPath = join(opts.outDir, 'compose-manifest.json');\n await writeFile(manifestPath, JSON.stringify(manifest, null, 2));\n return { videoPath, manifestPath, manifest };\n}\n\nexport async function renderFromManifest(bundle: BundleData, manifest: ComposeManifest, videoPath: string): Promise<void> {\n await renderVideo(bundle, manifest, videoPath);\n}\n\nfunction safeHost(url: string): string {\n try {\n return new URL(url).host;\n } catch {\n return url;\n }\n}\n","import sharp from 'sharp';\nimport { ffmpegPath, ffprobePath, runBinaryRaw, runBinary } from '../shared/ffmpeg.js';\nimport type { BundleData } from '../bundle/types.js';\nimport { frameIndexForTime, framePath } from '../bundle/reader.js';\n\n/** Extract grayscale frames from the output video at a fixed rate. */\nexport async function extractGrayFrames(\n videoPath: string,\n fps: number,\n w: number,\n h: number,\n): Promise<{ frames: Buffer[]; intervalMs: number }> {\n const res = await runBinaryRaw(ffmpegPath(), [\n '-hide_banner', '-loglevel', 'error',\n '-i', videoPath,\n '-vf', `fps=${fps},scale=${w}:${h}`,\n '-f', 'rawvideo',\n '-pix_fmt', 'gray',\n 'pipe:1',\n ]);\n if (res.code !== 0) throw new Error(`frame extraction failed: ${res.stderr}`);\n const frameSize = w * h;\n const frames: Buffer[] = [];\n for (let off = 0; off + frameSize <= res.stdout.length; off += frameSize) {\n frames.push(res.stdout.subarray(off, off + frameSize));\n }\n return { frames, intervalMs: 1000 / fps };\n}\n\n/** Extract one PNG frame from the output video at a timestamp (ms). */\nexport async function extractFrameAt(videoPath: string, tMs: number): Promise<Buffer> {\n const res = await runBinaryRaw(ffmpegPath(), [\n '-hide_banner', '-loglevel', 'error',\n '-ss', (Math.max(0, tMs) / 1000).toFixed(3),\n '-i', videoPath,\n '-frames:v', '1',\n '-f', 'image2pipe',\n '-vcodec', 'png',\n 'pipe:1',\n ]);\n if (res.code !== 0 || res.stdout.length === 0) {\n throw new Error(`could not extract frame at ${tMs}ms: ${res.stderr}`);\n }\n return res.stdout;\n}\n\nexport interface ProbeInfo {\n codec: string;\n width: number;\n height: number;\n durationSec: number;\n fps: number;\n}\n\nexport async function probeVideo(videoPath: string): Promise<ProbeInfo> {\n const res = await runBinary(ffprobePath(), [\n '-v', 'error',\n '-print_format', 'json',\n '-show_format',\n '-show_streams',\n videoPath,\n ]);\n if (res.code !== 0) throw new Error(`ffprobe failed: ${res.stderr}`);\n const json = JSON.parse(res.stdout) as {\n streams?: { codec_type: string; codec_name: string; width: number; height: number; avg_frame_rate: string }[];\n format?: { duration?: string };\n };\n const v = json.streams?.find((s) => s.codec_type === 'video');\n if (!v) throw new Error('no video stream found');\n const [num, den] = v.avg_frame_rate.split('/').map(Number);\n return {\n codec: v.codec_name,\n width: v.width,\n height: v.height,\n durationSec: Number(json.format?.duration ?? 0),\n fps: den ? num! / den : 0,\n };\n}\n\nexport function meanAbsDiff(a: Buffer, b: Buffer): number {\n const n = Math.min(a.length, b.length);\n let sum = 0;\n for (let i = 0; i < n; i++) sum += Math.abs(a[i]! - b[i]!);\n return sum / n;\n}\n\nexport function variance(a: Buffer): number {\n let sum = 0;\n for (let i = 0; i < a.length; i++) sum += a[i]!;\n const mean = sum / a.length;\n let v = 0;\n for (let i = 0; i < a.length; i++) v += (a[i]! - mean) ** 2;\n return v / a.length;\n}\n\n/** Decode a capture-bundle source frame to grayscale at reduced width. */\nexport async function sourceFrameGray(\n bundle: BundleData,\n tMs: number,\n width: number,\n): Promise<{ data: Buffer; w: number; h: number; frameT: number }> {\n const idx = frameIndexForTime(bundle.frames, tMs);\n const { data, info } = await sharp(framePath(bundle, idx))\n .resize({ width })\n .grayscale()\n .raw()\n .toBuffer({ resolveWithObject: true });\n return { data, w: info.width, h: info.height, frameT: bundle.frames[idx]!.t };\n}\n\n/** Decode a region of a source frame (frame px) to grayscale raw. */\nexport async function sourceRegionGray(\n bundle: BundleData,\n tMs: number,\n region: { x: number; y: number; w: number; h: number },\n preferAfter = false,\n color = false,\n): Promise<Buffer | null> {\n let idx = frameIndexForTime(bundle.frames, tMs);\n if (preferAfter && idx + 1 < bundle.frames.length && bundle.frames[idx]!.t < tMs) idx += 1;\n const meta = await sharp(framePath(bundle, idx)).metadata();\n const fw = meta.width ?? 0;\n const fh = meta.height ?? 0;\n const x = Math.max(0, Math.round(region.x));\n const y = Math.max(0, Math.round(region.y));\n const w = Math.min(Math.round(region.w), fw - x);\n const h = Math.min(Math.round(region.h), fh - y);\n if (w < 4 || h < 4) return null;\n // Grayscale by default (cheap); color on request — a pastel hue swap (blue→red badge) is\n // nearly luminance-neutral and INVISIBLE to a grayscale diff.\n let img = sharp(framePath(bundle, idx)).extract({ left: x, top: y, width: w, height: h });\n if (!color) img = img.grayscale();\n const { data } = await img.raw().toBuffer({ resolveWithObject: true });\n return data;\n}\n\n/** Crop a region from PNG bytes (or an image file), grayscale, resize to 48x48 raw. */\nexport async function regionGray48(input: Buffer | string, rect: { x: number; y: number; w: number; h: number }): Promise<Buffer | null> {\n try {\n const img = sharp(input);\n const meta = await img.metadata();\n const W = meta.width ?? 0;\n const H = meta.height ?? 0;\n const left = Math.max(0, Math.round(rect.x));\n const top = Math.max(0, Math.round(rect.y));\n const width = Math.min(W - left, Math.round(rect.w));\n const height = Math.min(H - top, Math.round(rect.h));\n if (width < 8 || height < 8) return null;\n return await sharp(input).extract({ left, top, width, height }).grayscale().resize(48, 48, { fit: 'fill' }).raw().toBuffer();\n } catch {\n return null;\n }\n}\n\n/** Normalized cross-correlation of two equal-length gray buffers, in [-1, 1]. */\nexport function normalizedCorrelation(a: Buffer, b: Buffer): number {\n const n = Math.min(a.length, b.length);\n let ma = 0;\n let mb = 0;\n for (let i = 0; i < n; i++) {\n ma += a[i]!;\n mb += b[i]!;\n }\n ma /= n;\n mb /= n;\n let num = 0;\n let da = 0;\n let db = 0;\n for (let i = 0; i < n; i++) {\n const xa = a[i]! - ma;\n const xb = b[i]! - mb;\n num += xa * xb;\n da += xa * xa;\n db += xb * xb;\n }\n // Two flat regions (zero variance) are \"the same\" for our purposes.\n if (da < 1e-6 || db < 1e-6) return da < 1e-6 && db < 1e-6 ? 1 : 0;\n return num / Math.sqrt(da * db);\n}\n","import type { VerifyContext, CheckResult, CheckEvidence } from './types.js';\nimport { stageContent, actReactWindows } from '../compose/types.js';\nimport { sampleCamera } from '../compose/camera/interpolate.js';\nimport { sampleCursor, type CursorPlan } from '../compose/cursor/path.js';\nimport { segmentAt, sampleSource } from '../compose/timeline/pacing.js';\nimport { actionEvents } from '../capture/events.js';\nimport { projectRect, rectContains, type CameraPlane, type Rect } from '../shared/geometry.js';\nimport {\n extractFrameAt,\n extractGrayFrames,\n meanAbsDiff,\n normalizedCorrelation,\n probeVideo,\n regionGray48,\n sourceFrameGray,\n sourceRegionGray,\n variance,\n} from './media.js';\nimport { framePath, frameIndexForTime } from '../bundle/reader.js';\nimport { ffmpegPath, ffprobePath, runBinary } from '../shared/ffmpeg.js';\n\nconst EFFECT_KINDS = new Set(['click', 'dblclick', 'type', 'select', 'goto']);\nconst CLICK_KINDS = new Set(['click', 'dblclick', 'select']);\n\n/** The camera projects into STAGE-CONTENT space (same space the planner and renderer use). */\nfunction plane(ctx: VerifyContext): CameraPlane {\n const content = stageContent(ctx.manifest.profile);\n return {\n vpW: ctx.manifest.viewport.w,\n vpH: ctx.manifest.viewport.h,\n outW: content.w,\n outH: content.h,\n };\n}\n\n/** 1. Every target legibly in frame around its action beat. */\nexport async function checkTargetInFrame(ctx: VerifyContext): Promise<CheckResult> {\n const p = plane(ctx);\n const frame: Rect = { x: 0, y: 0, w: p.outW, h: p.outH };\n const evidence: CheckEvidence[] = [];\n let checked = 0;\n let minHeight = Infinity;\n\n // Captions that are visible during a step's hold — the target must not hide behind them.\n const captions = ctx.manifest.overlays.filter((o) => o.kind === 'caption');\n for (const step of ctx.manifest.steps) {\n // The framing promise mirrors the planner exactly (same shared helper): an act→react step\n // promises the action target around the beat and the focused payoff during the settled\n // hold; otherwise the focused rect (or target) across the whole hold. The camera's travel\n // between act and react windows is unchecked by design.\n const handoff = actReactWindows(step);\n const rect = step.focusRectVp ?? step.targetRectVp;\n const windows = handoff\n ? [handoff.act, handoff.react]\n : rect\n ? [{ rect, from: Math.max(step.outStart, step.outBeat - 60), to: step.outEnd }]\n : [];\n if (windows.length === 0) continue;\n checked += 1;\n for (const w of windows)\n for (let t = w.from; t <= w.to; t += 100) {\n const rect = w.rect;\n const cam = sampleCamera(ctx.manifest.camera, t);\n const proj = projectRect(rect, cam, p);\n minHeight = Math.min(minHeight, proj.h);\n if (!rectContains(frame, proj, 2)) {\n evidence.push({ stepRef: step.stepRef, t, note: `target cropped by frame edge (projected ${fmtRect(proj)})` });\n break;\n }\n // A scroll's anchor element is just where we scrolled to — the viewer watches the list\n // move, not that element, so it need only be in frame, not meet the legibility floor.\n // Same for an explicit `focus: wide`: the author chose context over close-up, so the\n // target must be visible but is exempt from the close-up legibility floor.\n if (step.kind !== 'scroll' && step.focus !== 'wide' && proj.h < 28) {\n evidence.push({ stepRef: step.stepRef, t, note: `target renders too small (${proj.h.toFixed(0)}px high)` });\n break;\n }\n // Captions live in FRAME space; the projection is in stage-content space — translate\n // before comparing (the stage origin is (0,0) when no stage is set).\n const content = stageContent(ctx.manifest.profile);\n const projFrame: Rect = { x: proj.x + content.x, y: proj.y + content.y, w: proj.w, h: proj.h };\n const cap = captions.find((c) => t >= c.tStart + 150 && t <= c.tEnd - 150 && rectsOverlap(c.box, projFrame));\n if (cap) {\n evidence.push({ stepRef: step.stepRef, t, note: `caption \"${cap.text}\" overlaps the target` });\n break;\n }\n }\n }\n if (checked === 0) return { id: 'target-in-frame', status: 'skip', details: 'no steps with targets' };\n return evidence.length > 0\n ? { id: 'target-in-frame', status: 'fail', details: `${evidence.length}/${checked} targets violate framing`, evidence }\n : {\n id: 'target-in-frame',\n status: 'pass',\n details: `${checked}/${checked} targets fully framed, min rendered height ${minHeight === Infinity ? '—' : minHeight.toFixed(0) + 'px'}`,\n };\n}\n\n/** 2. Rendered cursor sits on the target at each click beat. */\nexport async function checkCursorOnTarget(ctx: VerifyContext): Promise<CheckResult> {\n const cursorPlan: CursorPlan = {\n segments: ctx.manifest.cursor,\n ripples: ctx.manifest.ripples,\n restStart: { x: ctx.manifest.viewport.w / 2, y: ctx.manifest.viewport.h * 0.6 },\n };\n const evidence: CheckEvidence[] = [];\n let checked = 0;\n for (const step of ctx.manifest.steps) {\n if (!CLICK_KINDS.has(step.kind) || !step.targetRectVp) continue;\n checked += 1;\n const pos = sampleCursor(cursorPlan, step.outBeat);\n const r = step.targetRectVp;\n const pad = 4;\n const inside =\n pos.x >= r.x - pad && pos.x <= r.x + r.w + pad && pos.y >= r.y - pad && pos.y <= r.y + r.h + pad;\n if (!inside) {\n evidence.push({\n stepRef: step.stepRef,\n t: step.outBeat,\n note: `cursor at (${pos.x.toFixed(0)},${pos.y.toFixed(0)}) missed target ${fmtRect(r)}`,\n });\n }\n }\n if (checked === 0) return { id: 'cursor-on-target', status: 'skip', details: 'no click steps' };\n return evidence.length > 0\n ? { id: 'cursor-on-target', status: 'fail', details: `${evidence.length}/${checked} clicks miss their target`, evidence }\n : { id: 'cursor-on-target', status: 'pass', details: `${checked}/${checked} clicks land on target` };\n}\n\n/** 3. Every action visibly changed the UI (dead-click detection). */\nexport async function checkActionEffect(ctx: VerifyContext): Promise<CheckResult> {\n const evidence: CheckEvidence[] = [];\n const inconclusive: CheckEvidence[] = [];\n let checked = 0;\n const frameScale = ctx.bundle.manifest.frameW / ctx.manifest.viewport.w;\n\n const lastFrameT = ctx.bundle.frames[ctx.bundle.frames.length - 1]!.t;\n const steps = ctx.manifest.steps;\n let skippedMasked = 0;\n for (let i = 0; i < steps.length; i++) {\n const step = steps[i]!;\n if (!EFFECT_KINDS.has(step.kind)) continue;\n // A masked field intentionally hides its own change — its effect is unverifiable by design.\n if (step.masked) {\n skippedMasked += 1;\n continue;\n }\n checked += 1;\n // Sample the \"after\" state at this step's settled hold, just before the next action — for an\n // instant hash-route navigation the settle timestamp itself can precede the first post-nav\n // frame, so compare against the fully-settled view instead.\n const nextAction = i + 1 < steps.length ? steps[i + 1]!.srcAction : lastFrameT;\n const afterT = Math.max(step.srcSettled, nextAction - 60);\n const before = await sourceFrameGray(ctx.bundle, step.srcAction - 40, 320);\n const after = await sourceFrameGray(ctx.bundle, afterT, 320);\n if (after.frameT <= before.frameT) {\n // No distinct post-action frame was captured (a capture-loop gap, e.g. under CPU load).\n // Absence of frames can't prove absence of effect, so this is inconclusive, not a failure.\n inconclusive.push({ stepRef: step.stepRef, note: 'no post-action frame captured to compare' });\n continue;\n }\n if (before.frameT >= step.srcAction) {\n // The \"before\" sample clamped to a frame AT/AFTER the action (no pre-action footage —\n // e.g. the first grabs stalled during initial load). Comparing post to post proves\n // nothing either way.\n inconclusive.push({ stepRef: step.stepRef, note: 'no pre-action frame captured to compare' });\n continue;\n }\n const overall = meanAbsDiff(before.data, after.data);\n let regionDiff = 0;\n // Measure where the effect is EXPECTED: the action target, and — for act→react steps —\n // the focused payoff (changing a select recolors the badge ELSEWHERE; the payoff region\n // is where the change actually lands). Take the strongest signal.\n const regions = [step.targetRectVp, step.focusRectVp].filter((r): r is Rect => !!r);\n for (const r of regions) {\n const region = scaleRect(r, frameScale);\n const [ra, rb] = await Promise.all([\n sourceRegionGray(ctx.bundle, step.srcAction - 40, region, false, true),\n sourceRegionGray(ctx.bundle, afterT, region, true, true),\n ]);\n if (ra && rb && ra.length === rb.length) regionDiff = Math.max(regionDiff, meanAbsDiff(ra, rb));\n }\n // Typing changes only a few pixels page-wide, so the local target region is the real signal.\n if (overall < 0.5 && regionDiff < 2) {\n evidence.push({\n stepRef: step.stepRef,\n t: step.outBeat,\n note: `no visible effect (frame diff ${overall.toFixed(2)}, target diff ${regionDiff.toFixed(2)})`,\n });\n }\n }\n if (checked === 0) {\n return {\n id: 'action-effect',\n status: 'skip',\n details: skippedMasked > 0 ? `no verifiable actions (${skippedMasked} masked)` : 'no effectful actions',\n };\n }\n const maskedNote = skippedMasked > 0 ? ` (${skippedMasked} masked skipped)` : '';\n const inconcNote = inconclusive.length > 0 ? `, ${inconclusive.length} inconclusive (capture gap)` : '';\n if (evidence.length > 0) {\n return {\n id: 'action-effect',\n status: 'fail',\n details: `${evidence.length}/${checked} actions show no visible effect${maskedNote}${inconcNote}`,\n evidence: [...evidence, ...inconclusive],\n };\n }\n if (inconclusive.length > 0) {\n return {\n id: 'action-effect',\n status: 'warn',\n details: `${checked - inconclusive.length}/${checked} actions visibly effective; ${inconclusive.length} unverified (capture gap)${maskedNote}`,\n evidence: inconclusive,\n };\n }\n return { id: 'action-effect', status: 'pass', details: `${checked}/${checked} actions visibly effective${maskedNote}` };\n}\n\n/** 4. No unplanned frozen footage, no blank frames, in the delivered video. */\nexport async function checkFrozenBlank(ctx: VerifyContext): Promise<CheckResult> {\n const { frames, intervalMs } = await extractGrayFrames(ctx.videoPath, 2, 320, 180);\n if (frames.length < 2) return { id: 'frozen-blank', status: 'fail', details: 'could not decode output frames' };\n const evidence: CheckEvidence[] = [];\n\n // Intentional near-uniform frames: title cards, and the dip-to-background fades around them\n // (which momentarily paint mostly theme background). These are design, not dead footage.\n const dips = ctx.manifest.overlays.filter((o) => o.kind === 'dip');\n const inTransition = (t: number) =>\n segmentAt(ctx.manifest.segments, t).kind === 'card' || dips.some((d) => t >= d.tStart - 60 && t <= d.tEnd + 60);\n\n // Blank frames.\n for (let i = 0; i < frames.length; i++) {\n const t = i * intervalMs;\n if (inTransition(t)) continue;\n if (variance(frames[i]!) < 2) {\n evidence.push({ t, note: `blank frame at ${(t / 1000).toFixed(1)}s` });\n }\n }\n\n // Frozen runs: identical stretches that cross more than one step beat, or absurdly long.\n // A masked step is intentionally static on screen (the overlay hides the typing), so its\n // window is legitimately \"frozen\" — exclude it, as action-effect does.\n const maskedWindows = ctx.manifest.steps\n .filter((s) => s.masked)\n .map((s) => ({ start: s.outStart, end: s.outEnd }));\n const inMaskedWindow = (t0: number, t1: number) =>\n maskedWindows.some((w) => t1 >= w.start - 200 && t0 <= w.end + 200);\n\n // The final section (last action through the outro) is an intended hold on the result — a\n // walkthrough often ends held on its final state — so static footage there is not a stall.\n const lastBeat = ctx.manifest.steps.reduce((m, s) => Math.max(m, s.outBeat), 0);\n\n // A narrated video legitimately holds on a static screen WHILE ITS SPOKEN LINE PLAYS — the\n // voice carries it. But that must never blanket-disable stall detection: a frozen run is only\n // exempt when a narration clip actually covers it. (Manifests from before clip windows were\n // recorded fall back to the blanket exemption rather than mis-failing old renders.)\n const narrated = !!ctx.manifest.audio?.narrated;\n const clipWindows = (ctx.manifest.audio?.clips ?? []).map((c) => ({\n start: c.tStart - 300,\n end: c.tStart + c.durMs + 1200, // clip + the tail-and-extend hold pacing grants it\n }));\n const voiceCovers = (t0: number, t1: number) =>\n clipWindows.length === 0\n ? narrated // legacy manifests: no window data — keep the old blanket behavior\n : clipWindows.some((w) => t0 >= w.start && t1 <= w.end);\n\n let runStart = 0;\n for (let i = 1; i <= frames.length; i++) {\n const identical = i < frames.length && meanAbsDiff(frames[i]!, frames[i - 1]!) < 0.15;\n if (!identical) {\n const runMs = (i - 1 - runStart) * intervalMs;\n const t0 = runStart * intervalMs;\n const t1 = (i - 1) * intervalMs;\n const inFinalHold = t0 >= lastBeat - 800;\n if (runMs > 2000 && !inMaskedWindow(t0, t1) && !inFinalHold && !(narrated && voiceCovers(t0, t1))) {\n const beatsInside = ctx.manifest.steps.filter((s) => s.outBeat > t0 + 200 && s.outBeat < t1 - 200);\n if (beatsInside.length >= 1 && runMs > 2500) {\n evidence.push({\n t: t0,\n note: `frozen footage ${(runMs / 1000).toFixed(1)}s spanning ${beatsInside.length} action beat(s)`,\n });\n } else if (runMs > 8000) {\n evidence.push({ t: t0, note: `frozen footage for ${(runMs / 1000).toFixed(1)}s` });\n }\n }\n runStart = i;\n }\n }\n return evidence.length > 0\n ? { id: 'frozen-blank', status: 'fail', details: `${evidence.length} frozen/blank issue(s)`, evidence }\n : { id: 'frozen-blank', status: 'pass', details: `${frames.length} sampled output frames live and non-blank` };\n}\n\n/** 5. Captions legible: no truncation, font floor respected, inside safe bounds. */\nexport async function checkCaptions(ctx: VerifyContext): Promise<CheckResult> {\n const evidence: CheckEvidence[] = [];\n let warned = 0;\n let count = 0;\n const out: Rect = { x: 0, y: 0, w: ctx.manifest.profile.width, h: ctx.manifest.profile.height };\n for (const o of ctx.manifest.overlays) {\n if (o.kind !== 'caption') continue;\n count += 1;\n if (o.truncated) evidence.push({ stepRef: o.stepRef, note: `caption truncated: \"${o.text}\"` });\n if (o.fontPx < ctx.manifest.theme.captionMinFontPx)\n evidence.push({ stepRef: o.stepRef, note: `caption font ${o.fontPx}px below minimum` });\n if (!rectContains(out, o.box, 24)) evidence.push({ stepRef: o.stepRef, note: 'caption box outside safe bounds' });\n if (o.shrunk && !o.truncated) warned += 1;\n }\n if (count === 0) return { id: 'captions', status: 'skip', details: 'no captions' };\n if (evidence.length > 0)\n return { id: 'captions', status: 'fail', details: `${evidence.length} caption problem(s)`, evidence };\n return warned > 0\n ? { id: 'captions', status: 'warn', details: `${count} captions ok, ${warned} auto-shrunk to fit` }\n : { id: 'captions', status: 'pass', details: `${count} captions fit at full size` };\n}\n\n/** 6. Pacing sanity: steps get readable screen time; total duration sane. */\nexport async function checkPacing(ctx: VerifyContext): Promise<CheckResult> {\n const evidence: CheckEvidence[] = [];\n for (const step of ctx.manifest.steps) {\n const dur = step.outEnd - step.outStart;\n if (step.kind !== 'wait' && dur < 1200) {\n evidence.push({ stepRef: step.stepRef, note: `step on screen only ${(dur / 1000).toFixed(1)}s` });\n }\n }\n const total = ctx.manifest.durationMs;\n if (total < 3000) evidence.push({ note: `video too short (${(total / 1000).toFixed(1)}s)` });\n if (total > 15 * 60_000) evidence.push({ note: `video too long (${(total / 60000).toFixed(1)}min)` });\n return evidence.length > 0\n ? { id: 'pacing', status: 'fail', details: `${evidence.length} pacing violation(s)`, evidence }\n : { id: 'pacing', status: 'pass', details: `${ctx.manifest.steps.length} steps paced ≥1.2s, total ${(total / 1000).toFixed(1)}s` };\n}\n\n/** 7. The MP4 itself is intact and matches the manifest. */\n/** 9. Narration audio: when the video was narrated, the track must exist, be audible, and span the video. */\nexport async function checkAudio(ctx: VerifyContext): Promise<CheckResult> {\n if (!ctx.manifest.audio?.narrated) return { id: 'audio', status: 'skip', details: 'no narration' };\n const evidence: CheckEvidence[] = [];\n\n const probe = await runBinary(ffprobePath(), [\n '-v', 'error', '-select_streams', 'a', '-show_entries', 'stream=codec_name,duration', '-of', 'json', ctx.videoPath,\n ]);\n const stream = (JSON.parse(probe.stdout) as { streams?: { codec_name: string; duration?: string }[] }).streams?.[0];\n if (!stream) return { id: 'audio', status: 'fail', details: 'narration requested but the output has no audio stream' };\n\n // Non-silent? volumedetect reports mean/peak levels on stderr.\n const vd = await runBinary(ffmpegPath(), ['-hide_banner', '-nostats', '-i', ctx.videoPath, '-af', 'volumedetect', '-f', 'null', '-']);\n const mean = Number(/mean_volume:\\s*(-?[\\d.]+) dB/.exec(vd.stderr)?.[1] ?? '0');\n if (mean <= -70) evidence.push({ note: `narration track is effectively silent (mean ${mean} dB)` });\n\n const expectSec = ctx.manifest.durationMs / 1000;\n const aDur = Number(stream.duration ?? 0);\n if (aDur > 0 && Math.abs(aDur - expectSec) > Math.max(0.5, expectSec * 0.05))\n evidence.push({ note: `audio ${aDur.toFixed(1)}s vs video ${expectSec.toFixed(1)}s` });\n\n // A/V SYNC: every narration clip must be AUDIBLE inside its own window. Pacing predicts and\n // mux places independently — a drift bug would otherwise ship a voice describing the\n // previous screen with a passing verdict.\n const clips = ctx.manifest.audio.clips ?? [];\n let loudness: number | null = null;\n if (clips.length > 0) {\n const det = await runBinary(ffmpegPath(), [\n '-hide_banner', '-nostats',\n '-i', ctx.videoPath,\n '-af', 'silencedetect=noise=-40dB:d=0.35,ebur128',\n '-f', 'null', '-',\n ]);\n const silences: { start: number; end: number }[] = [];\n let open: number | null = null;\n for (const m of det.stderr.matchAll(/silence_(start|end): ([\\d.]+)/g)) {\n if (m[1] === 'start') open = parseFloat(m[2]!) * 1000;\n else if (open !== null) {\n silences.push({ start: open, end: parseFloat(m[2]!) * 1000 });\n open = null;\n }\n }\n if (open !== null) silences.push({ start: open, end: ctx.manifest.durationMs });\n for (const clip of clips) {\n const w0 = clip.tStart;\n const w1 = clip.tStart + clip.durMs;\n let silent = 0;\n for (const s of silences) {\n silent += Math.max(0, Math.min(w1, s.end) - Math.max(w0, s.start));\n }\n const voiced = (w1 - w0 - silent) / Math.max(1, w1 - w0);\n if (voiced < 0.45) {\n evidence.push({\n stepRef: clip.stepRef,\n t: clip.tStart,\n note: `narration line is mostly silent in its own window (${(voiced * 100).toFixed(0)}% voiced) — audio/video drift`,\n });\n }\n }\n // Loudness: the mix normalizes to I=-16 LUFS; a big miss means the loudnorm stage broke.\n // ebur128 prints PERIODIC \"I:\" readouts (starting at -70 before audio plays) and a final\n // summary — the integrated value is the LAST match, never the first.\n const lus = [...det.stderr.matchAll(/I:\\s+(-?[\\d.]+)\\s+LUFS/g)];\n const lu = lus[lus.length - 1];\n if (lu) {\n loudness = parseFloat(lu[1]!);\n if (loudness < -20 || loudness > -12) {\n evidence.push({ note: `integrated loudness ${loudness.toFixed(1)} LUFS is outside the -16±4 target` });\n }\n }\n }\n\n return evidence.length\n ? { id: 'audio', status: 'fail', details: `${evidence.length} narration problem(s)`, evidence }\n : {\n id: 'audio',\n status: 'pass',\n details: `${ctx.manifest.audio.lines} lines audible in their windows, ${stream.codec_name}${loudness !== null ? `, ${loudness.toFixed(1)} LUFS` : `, mean ${mean.toFixed(0)} dB`}`,\n };\n}\n\nexport async function checkEncode(ctx: VerifyContext): Promise<CheckResult> {\n let info;\n try {\n info = await probeVideo(ctx.videoPath);\n } catch (e) {\n return { id: 'encode', status: 'fail', details: `unreadable video: ${(e as Error).message}` };\n }\n const problems: string[] = [];\n if (info.codec !== 'h264') problems.push(`codec ${info.codec}`);\n if (info.width !== ctx.manifest.profile.width || info.height !== ctx.manifest.profile.height)\n problems.push(`resolution ${info.width}x${info.height}`);\n const expectSec = ctx.manifest.durationMs / 1000;\n if (Math.abs(info.durationSec - expectSec) > Math.max(0.5, expectSec * 0.03))\n problems.push(`duration ${info.durationSec.toFixed(1)}s vs planned ${expectSec.toFixed(1)}s`);\n if (Math.abs(info.fps - ctx.manifest.profile.fps) > 0.5) problems.push(`fps ${info.fps.toFixed(2)}`);\n return problems.length > 0\n ? { id: 'encode', status: 'fail', details: problems.join('; ') }\n : {\n id: 'encode',\n status: 'pass',\n details: `h264 ${info.width}x${info.height} @ ${info.fps.toFixed(0)}fps, ${info.durationSec.toFixed(1)}s`,\n };\n}\n\n/** 8. Masking held: masked regions are covered in footage, secrets absent from the log. */\nexport async function checkMasks(ctx: VerifyContext): Promise<CheckResult> {\n const evidence: CheckEvidence[] = [];\n const frameScale = ctx.bundle.manifest.frameW / ctx.manifest.viewport.w;\n\n // A mask region can be legitimately occluded by later UI (a dialog opening over a banner),\n // which raises its variance without exposing the sensitive pixels. So group samples by\n // position and require that each masked element reads as covered in its BEST sample —\n // if masking failed entirely, no sample of that element would ever be uniform.\n const buckets = new Map<string, { rect: { x: number; y: number; w: number; h: number }; minSd: number; t: number }>();\n const blurKeys = new Set<string>();\n for (const sample of ctx.bundle.maskSamples) {\n for (const rect of sample.rects) {\n const posKey = `${Math.round(rect.x / 24)}:${Math.round(rect.y / 24)}:${Math.round(rect.w / 24)}:${Math.round(rect.h / 24)}`;\n if (rect.style === 'blur') {\n blurKeys.add(posKey);\n continue; // a blurred region has no reference to compare against; leave it to --vision\n }\n const inset = scaleRect(shrinkRect(rect, Math.min(6, rect.w / 8, rect.h / 8)), frameScale);\n const region = await sourceRegionGray(ctx.bundle, sample.t + 60, inset, true);\n if (!region) continue;\n const sd = Math.sqrt(variance(region));\n const key = posKey;\n const prev = buckets.get(key);\n if (!prev || sd < prev.minSd) buckets.set(key, { rect, minSd: sd, t: sample.t });\n }\n }\n for (const b of buckets.values()) {\n if (b.minSd > 16) {\n evidence.push({ t: b.t, note: `solid mask at ${fmtRect(b.rect)} never verified opaque (best σ=${b.minSd.toFixed(1)})` });\n }\n }\n\n for (const e of actionEvents(ctx.bundle.events)) {\n if (e.masked && e.typedText && /[^•]/.test(e.typedText)) {\n evidence.push({ stepRef: `${e.sceneId}/${e.stepIndex}`, note: 'masked step leaked typed text into the event log' });\n }\n }\n\n if (ctx.bundle.maskSamples.length === 0) {\n return { id: 'masks', status: 'skip', details: 'no masking rules' };\n }\n if (evidence.length > 0) {\n return { id: 'masks', status: 'fail', details: `${evidence.length} mask violation(s)`, evidence };\n }\n const parts: string[] = [];\n if (buckets.size > 0) parts.push(`${buckets.size} solid region(s) verified opaque`);\n if (blurKeys.size > 0) parts.push(`${blurKeys.size} blurred region(s) applied`);\n return { id: 'masks', status: 'pass', details: `${parts.join(', ')}; log clean` };\n}\n\nfunction scaleRect(r: Rect, s: number): Rect {\n return { x: r.x * s, y: r.y * s, w: r.w * s, h: r.h * s };\n}\n\nfunction rectsOverlap(a: Rect, b: Rect): boolean {\n return a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y;\n}\n\nfunction shrinkRect(r: { x: number; y: number; w: number; h: number }, by: number): Rect {\n return { x: r.x + by, y: r.y + by, w: Math.max(1, r.w - 2 * by), h: Math.max(1, r.h - 2 * by) };\n}\n\nfunction fmtRect(r: Rect): string {\n return `[${r.x.toFixed(0)},${r.y.toFixed(0)} ${r.w.toFixed(0)}x${r.h.toFixed(0)}]`;\n}\n\n/**\n * 10. The DELIVERED pixels match the plan: for sampled steps, the region of the output MP4\n * where the subject should be must correlate with the same region of the source bundle frame.\n * Every geometry check above re-runs the planner's math — this one closes the plan-vs-pixels\n * hole: a renderer drawing the wrong frame or the wrong crop fails HERE.\n */\nexport async function checkOutputPixels(ctx: VerifyContext): Promise<CheckResult> {\n const p = plane(ctx);\n const content = stageContent(ctx.manifest.profile);\n const frameScale = ctx.bundle.manifest.frameW / ctx.manifest.viewport.w;\n const captions = ctx.manifest.overlays.filter((o) => o.kind === 'caption');\n\n const candidates = ctx.manifest.steps.filter((s) => !s.masked && (s.focusRectVp ?? s.targetRectVp));\n // Sample evenly, capped for speed — this decodes output frames.\n const stride = Math.max(1, Math.floor(candidates.length / 6));\n const sampled = candidates.filter((_, i) => i % stride === 0).slice(0, 6);\n if (sampled.length === 0) return { id: 'output-pixels', status: 'skip', details: 'no steps with targets' };\n\n const evidence: CheckEvidence[] = [];\n let checked = 0;\n for (const step of sampled) {\n const rect = step.focusRectVp ?? step.targetRectVp!;\n const tOut = Math.max(step.outBeat + 100, step.outEnd - 250);\n const cam = sampleCamera(ctx.manifest.camera, tOut);\n const proj = projectRect(rect, cam, p);\n const projFrame: Rect = { x: proj.x + content.x, y: proj.y + content.y, w: proj.w, h: proj.h };\n // A caption overlapping the region would pollute the comparison — skip those samples.\n if (captions.some((c) => tOut >= c.tStart && tOut <= c.tEnd && rectsOverlap(c.box, projFrame))) continue;\n const { srcAt } = sampleSource(ctx.manifest.segments, tOut);\n if (srcAt === null) continue;\n\n const outPng = await extractFrameAt(ctx.videoPath, tOut).catch(() => null);\n if (!outPng) continue;\n const outRegion = await regionGray48(outPng, projFrame);\n const srcFile = framePath(ctx.bundle, frameIndexForTime(ctx.bundle.frames, srcAt));\n const srcRegion = await regionGray48(srcFile, {\n x: rect.x * frameScale,\n y: rect.y * frameScale,\n w: rect.w * frameScale,\n h: rect.h * frameScale,\n });\n if (!outRegion || !srcRegion) continue;\n // A flat (zero-variance) region proves nothing: it can be a legitimately blank area, a mask\n // overlay, or a transition frame — and correlation against flatness is undefined. Only a\n // TEXTURED-vs-TEXTURED mismatch demonstrates a wrong frame or wrong crop.\n if (variance(outRegion) < 4 || variance(srcRegion) < 4) continue;\n checked += 1;\n const corr = normalizedCorrelation(outRegion, srcRegion);\n // Loose threshold: JPEG, rescaling, frame blending, and the spotlight all perturb pixels;\n // a WRONG frame or crop scores near zero, a right-but-processed one scores high.\n if (corr < 0.5) {\n evidence.push({\n stepRef: step.stepRef,\n t: tOut,\n note: `output region does not match the planned source region (correlation ${corr.toFixed(2)})`,\n });\n }\n }\n if (checked === 0) return { id: 'output-pixels', status: 'skip', details: 'no comparable samples (captions overlapped or frames unavailable)' };\n return evidence.length > 0\n ? { id: 'output-pixels', status: 'fail', details: `${evidence.length}/${checked} sampled regions diverge from the plan`, evidence }\n : { id: 'output-pixels', status: 'pass', details: `${checked} sampled output regions match their planned source` };\n}\n","import { writeFile } from 'node:fs/promises';\nimport { createCanvas, loadImage } from '@napi-rs/canvas';\nimport type { ComposeManifest } from '../compose/types.js';\nimport { extractFrameAt } from './media.js';\nimport { registerFonts } from '../theme/index.js';\nimport { roundRect } from '../compose/overlays/text.js';\n\nconst TILE_W = 480;\nconst LABEL_H = 42;\nconst GUTTER = 16;\nconst COLS = 3;\n\n/**\n * Contact sheet: one tile per step at its action beat (decoded from the OUTPUT video —\n * what viewers actually see) plus first and last frames, annotated with captions.\n */\nexport async function renderContactSheet(\n manifest: ComposeManifest,\n videoPath: string,\n outPath: string,\n): Promise<string> {\n registerFonts();\n const tileH = Math.round((TILE_W * manifest.profile.height) / manifest.profile.width);\n const captionsByStep = new Map(\n manifest.overlays.filter((o) => o.kind === 'caption').map((o) => [o.stepRef, o]),\n );\n\n const moments: { t: number; label: string }[] = [\n { t: manifest.overlays.find((o) => o.kind === 'titleCard')!.tEnd / 2, label: 'Title' },\n ];\n for (const step of manifest.steps) {\n const caption = captionsByStep.get(step.stepRef);\n // Sample the SETTLED hold, not the beat: at the beat (+150ms) a slow effect — a navigation,\n // a fetch, a modal — hasn't painted yet, so the tile labelled \"Click Save\" would show the\n // screen from *before* Save was clicked. Sampling near the end of the step's hold shows the\n // effect the caption claims. (Clamped to stay after the beat for very short steps.)\n const label = caption ? `${caption.ordinal}. ${caption.text}` : `${step.kind} (${step.stepRef})`;\n const settled = Math.max(step.outBeat + 150, step.outEnd - 400);\n moments.push({ t: Math.min(settled, step.outEnd - 50), label });\n }\n moments.push({ t: manifest.durationMs - 200, label: 'Final state' });\n\n const rows = Math.ceil(moments.length / COLS);\n const width = GUTTER + COLS * (TILE_W + GUTTER);\n const height = GUTTER + rows * (tileH + LABEL_H + GUTTER);\n const canvas = createCanvas(width, height);\n const ctx = canvas.getContext('2d');\n ctx.fillStyle = '#14161d';\n ctx.fillRect(0, 0, width, height);\n\n for (let i = 0; i < moments.length; i++) {\n const m = moments[i]!;\n const col = i % COLS;\n const row = Math.floor(i / COLS);\n const x = GUTTER + col * (TILE_W + GUTTER);\n const y = GUTTER + row * (tileH + LABEL_H + GUTTER);\n try {\n const png = await extractFrameAt(videoPath, m.t);\n const img = await loadImage(png);\n ctx.drawImage(img, x, y, TILE_W, tileH);\n } catch {\n ctx.fillStyle = '#3a2030';\n ctx.fillRect(x, y, TILE_W, tileH);\n ctx.fillStyle = '#ffffff';\n ctx.font = '16px Inter Medium';\n ctx.textAlign = 'center';\n ctx.fillText('frame unavailable', x + TILE_W / 2, y + tileH / 2);\n }\n // Label bar\n ctx.fillStyle = '#1e222c';\n roundRect(ctx, x, y + tileH + 4, TILE_W, LABEL_H - 8, 6);\n ctx.fill();\n ctx.fillStyle = 'rgba(255,255,255,0.92)';\n ctx.font = '15px Inter Medium';\n ctx.textAlign = 'left';\n ctx.textBaseline = 'middle';\n ctx.fillText(truncate(m.label, 58), x + 12, y + tileH + 4 + (LABEL_H - 8) / 2 + 1);\n ctx.fillStyle = 'rgba(255,255,255,0.45)';\n ctx.font = '13px Inter';\n ctx.textAlign = 'right';\n ctx.fillText(`${(m.t / 1000).toFixed(1)}s`, x + TILE_W - 12, y + tileH + 4 + (LABEL_H - 8) / 2 + 1);\n }\n\n await writeFile(outPath, await canvas.encode('png'));\n return outPath;\n}\n\nfunction truncate(s: string, n: number): string {\n return s.length <= n ? s : s.slice(0, n - 1) + '…';\n}\n","import { readFile } from 'node:fs/promises';\nimport type { CheckResult } from './types.js';\nimport type { ComposeManifest } from '../compose/types.js';\nimport { log } from '../shared/log.js';\n\nconst DEFAULT_MODEL = process.env.PLAYHEAD_VISION_MODEL ?? 'claude-opus-5';\n\nexport interface VisionReview {\n model: string;\n findings: { severity: string; note: string }[];\n}\n\n/**\n * Optional AI review: sends the contact sheet to Claude for a judgment call the\n * deterministic checks can't make (\"does this read as a coherent, professional\n * walkthrough?\"). Advisory only — findings become warn-level check entries.\n */\nexport async function visionReview(\n contactSheetPath: string,\n manifest: ComposeManifest,\n): Promise<{ check: CheckResult; review: VisionReview | null }> {\n if (!process.env.ANTHROPIC_API_KEY) {\n return {\n check: { id: 'vision-review', status: 'skip', details: 'ANTHROPIC_API_KEY not set' },\n review: null,\n };\n }\n try {\n const { default: Anthropic } = await import('@anthropic-ai/sdk');\n const client = new Anthropic();\n const png = await readFile(contactSheetPath);\n const captions = manifest.overlays\n .filter((o) => o.kind === 'caption')\n .map((o) => `${o.ordinal}. ${o.text}`)\n .join('\\n');\n\n const response = await client.messages.create({\n model: DEFAULT_MODEL,\n max_tokens: 1200,\n messages: [\n {\n role: 'user',\n content: [\n {\n type: 'image',\n source: { type: 'base64', media_type: 'image/png', data: png.toString('base64') },\n },\n {\n type: 'text',\n text: [\n 'This is a contact sheet of key moments from an automatically produced product walkthrough video.',\n 'Each tile shows the output frame at one step, labeled with its instruction caption. The steps are:',\n captions,\n '',\n 'Review it as a demanding video editor. Report only real problems a viewer would notice:',\n 'illegible or clipped UI, captions that do not match what is on screen, awkward framing,',\n 'visual glitches, or anything unprofessional. Ignore the tile borders and labels themselves.',\n 'Respond with strict JSON: {\"findings\": [{\"severity\": \"warn\", \"note\": \"...\"}]} —',\n 'an empty findings array if the video looks publishable.',\n ].join('\\n'),\n },\n ],\n },\n ],\n });\n const text = response.content\n .map((b) => (b.type === 'text' ? b.text : ''))\n .join('');\n const parsed = extractJson(text);\n const findings = Array.isArray(parsed?.findings)\n ? parsed.findings\n .filter((f): f is { severity?: string; note?: string } => !!f && typeof f === 'object')\n .map((f) => ({ severity: String(f.severity ?? 'warn'), note: String(f.note ?? '') }))\n : [];\n const review: VisionReview = { model: DEFAULT_MODEL, findings };\n return {\n check: {\n id: 'vision-review',\n status: findings.length > 0 ? 'warn' : 'pass',\n details:\n findings.length > 0\n ? `${findings.length} advisory finding(s) from ${DEFAULT_MODEL}`\n : `no issues flagged by ${DEFAULT_MODEL}`,\n ...(findings.length > 0 ? { evidence: findings.map((f) => ({ note: f.note })) } : {}),\n },\n review,\n };\n } catch (e) {\n log.warn(`vision review failed: ${(e as Error).message}`);\n return {\n check: { id: 'vision-review', status: 'skip', details: `vision review errored: ${(e as Error).message}` },\n review: null,\n };\n }\n}\n\nfunction extractJson(text: string): { findings?: unknown[] } | null {\n const start = text.indexOf('{');\n const end = text.lastIndexOf('}');\n if (start === -1 || end <= start) return null;\n try {\n return JSON.parse(text.slice(start, end + 1)) as { findings?: unknown[] };\n } catch {\n return null;\n }\n}\n","import { createHmac } from 'node:crypto';\nimport type { Verdict } from './types.js';\n\n/**\n * The canonical signable payload: everything that makes the verdict a CLAIM (result, artifact\n * hashes, provenance, per-check outcomes), in a fixed key order. Paths are excluded — moving\n * files doesn't change what was proven.\n */\nexport function signablePayload(v: Omit<Verdict, 'signature'>): string {\n return JSON.stringify({\n schema: v.schema,\n verdict: v.verdict,\n videoSha256: v.video.sha256,\n bundleHashes: { events: v.bundleHashes.events, framesIndex: v.bundleHashes.framesIndex },\n provenance: {\n playheadVersion: v.provenance.playheadVersion,\n specHash: v.provenance.specHash,\n appUrl: v.provenance.appUrl,\n capturedAt: v.provenance.capturedAt,\n verifiedAt: v.provenance.verifiedAt,\n checkSuiteVersion: v.provenance.checkSuiteVersion,\n host: v.provenance.host,\n partial: v.provenance.partial ?? false,\n },\n checks: v.checks.map((c) => ({ id: c.id, status: c.status })),\n });\n}\n\n/** HMAC-SHA256 signature over the canonical payload; null when no key is configured. */\nexport function signVerdict(v: Omit<Verdict, 'signature'>, key = process.env.PLAYHEAD_SIGNING_KEY): string | null {\n if (!key) return null;\n return createHmac('sha256', key).update(signablePayload(v)).digest('hex');\n}\n\n/** JUnit XML: one testsuite per verdict, one testcase per check — the shape every CI ingests. */\nexport function toJUnit(v: Verdict, suiteName = 'playhead'): string {\n const failures = v.checks.filter((c) => c.status === 'fail').length;\n const skipped = v.checks.filter((c) => c.status === 'skip').length;\n const esc = (s: string) =>\n s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"');\n const cases = v.checks\n .map((c) => {\n const body =\n c.status === 'fail'\n ? `\\n <failure message=\"${esc(c.details)}\">${esc(\n (c.evidence ?? []).map((e) => `${e.stepRef ?? ''}${e.t !== undefined ? ` @${(e.t / 1000).toFixed(1)}s` : ''} — ${e.note}`).join('\\n'),\n )}</failure>\\n `\n : c.status === 'skip'\n ? `\\n <skipped message=\"${esc(c.details)}\"/>\\n `\n : '';\n return ` <testcase classname=\"${esc(suiteName)}\" name=\"${esc(c.id)}\">${body}</testcase>`;\n })\n .join('\\n');\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<testsuite name=\"${esc(suiteName)}\" tests=\"${v.checks.length}\" failures=\"${failures}\" skipped=\"${skipped}\">\n${cases}\n</testsuite>\n`;\n}\n","import { join } from 'node:path';\nimport { mkdir, writeFile, readFile } from 'node:fs/promises';\nimport type { BundleData } from '../bundle/types.js';\nimport type { ComposeManifest } from '../compose/types.js';\nimport type { CheckResult, Verdict, VerifyContext } from './types.js';\nimport {\n checkActionEffect,\n checkAudio,\n checkCaptions,\n checkCursorOnTarget,\n checkEncode,\n checkFrozenBlank,\n checkMasks,\n checkOutputPixels,\n checkPacing,\n checkTargetInFrame,\n} from './checks.js';\nimport { renderContactSheet } from './contact-sheet.js';\nimport { visionReview } from './vision.js';\nimport { sha256File } from '../bundle/hash.js';\nimport { signVerdict } from './report.js';\nimport { PLAYHEAD_VERSION } from '../shared/version.js';\nimport { log } from '../shared/log.js';\nimport { platform, arch } from 'node:os';\nimport pc from 'picocolors';\n\n/** Bumped whenever a check is added or its semantics change — part of provenance. */\nexport const CHECK_SUITE_VERSION = 'playhead/checks@2';\n\nexport interface VerifyOptions {\n outDir: string;\n vision?: boolean;\n}\n\nexport async function verify(\n bundle: BundleData,\n manifest: ComposeManifest,\n videoPath: string,\n opts: VerifyOptions,\n): Promise<Verdict> {\n const verifyDir = join(opts.outDir, 'verify');\n await mkdir(verifyDir, { recursive: true });\n const ctx: VerifyContext = { bundle, manifest, videoPath, outDir: verifyDir };\n\n log.info('verifying output');\n const checks: CheckResult[] = [];\n const suite = [\n checkEncode, // fail fast on a broken file before decoding frames from it\n checkTargetInFrame,\n checkCursorOnTarget,\n checkActionEffect,\n checkOutputPixels, // the delivered MP4, not the plan\n checkFrozenBlank,\n checkCaptions,\n checkPacing,\n checkMasks,\n checkAudio,\n ];\n for (const check of suite) {\n const result = await check(ctx);\n checks.push(result);\n report(result);\n }\n\n const contactSheet = join(verifyDir, 'contact-sheet.png');\n await renderContactSheet(manifest, videoPath, contactSheet);\n log.ok(`contact sheet → ${contactSheet}`);\n\n let vision: Verdict['vision'] = null;\n if (opts.vision) {\n const { check, review } = await visionReview(contactSheet, manifest);\n checks.push(check);\n report(check);\n vision = review;\n }\n\n const failed = checks.some((c) => c.status === 'fail');\n const unsigned: Omit<Verdict, 'signature'> = {\n schema: 'playhead/verdict@2',\n verdict: failed ? 'not-publishable' : 'publishable',\n video: { path: videoPath, sha256: manifest.videoSha256 ?? (await sha256File(videoPath)) },\n bundleHashes: manifest.bundleHashes,\n provenance: {\n playheadVersion: PLAYHEAD_VERSION,\n specHash: bundle.manifest.specHash,\n appUrl: bundle.manifest.appUrl,\n capturedAt: bundle.manifest.createdAtIso,\n verifiedAt: new Date().toISOString(),\n checkSuiteVersion: CHECK_SUITE_VERSION,\n host: `${platform()}-${arch()}`,\n ...(bundle.manifest.partial ? { partial: true } : {}),\n ...(bundle.manifest.failure ? { failure: bundle.manifest.failure } : {}),\n },\n checks,\n contactSheet,\n vision,\n };\n const verdict: Verdict = { ...unsigned, signature: signVerdict(unsigned) };\n if (!verdict.signature) log.debug('verdict unsigned — set PLAYHEAD_SIGNING_KEY to sign');\n await writeFile(join(verifyDir, 'verdict.json'), JSON.stringify(verdict, null, 2));\n\n if (failed) log.error(`verdict: NOT PUBLISHABLE`);\n else log.ok(`verdict: publishable`);\n return verdict;\n}\n\n/** Re-load a compose manifest from disk (for `playhead verify <bundle> <mp4>`). */\nexport async function loadComposeManifest(path: string): Promise<ComposeManifest> {\n const manifest = JSON.parse(await readFile(path, 'utf8')) as ComposeManifest;\n if (manifest.schema !== 'playhead/compose@1') {\n throw new Error(`Unsupported compose manifest schema in ${path}`);\n }\n return manifest;\n}\n\nfunction report(c: CheckResult): void {\n const label =\n c.status === 'pass'\n ? pc.green('pass')\n : c.status === 'fail'\n ? pc.red('FAIL')\n : c.status === 'warn'\n ? pc.yellow('warn')\n : pc.dim('skip');\n console.error(` ${label} ${c.id}: ${c.details}`);\n for (const e of c.evidence ?? []) {\n console.error(pc.dim(` ${e.stepRef ?? ''}${e.t !== undefined ? ` @${(e.t / 1000).toFixed(1)}s` : ''} — ${e.note}`));\n }\n}\n","import { join } from 'node:path';\nimport { mkdir } from 'node:fs/promises';\nimport type { Spec } from './spec/schema.js';\nimport { capture } from './capture/executor.js';\nimport { openBundle } from './bundle/reader.js';\nimport { compose } from './compose/index.js';\nimport { verify } from './verify/runner.js';\nimport type { Verdict } from './verify/types.js';\nimport { concatVideos } from './shared/ffmpeg.js';\nimport { log } from './shared/log.js';\n\nexport interface BeforeAfterResult {\n videoPath: string;\n before: { videoPath: string; verdict: Verdict };\n after: { videoPath: string; verdict: Verdict };\n verdict: 'publishable' | 'not-publishable';\n}\n\n/**\n * Render a before/after comparison: run the SAME spec against two versions of the app\n * (app.compareUrl = before, app.url = after), compose each with the full pipeline, verify both,\n * and stitch them into one titled clip. Publishable only if both halves are.\n */\nexport async function renderBeforeAfter(\n spec: Spec,\n opts: { outDir: string; headless?: boolean; vision?: boolean },\n): Promise<BeforeAfterResult> {\n if (!spec.app.compareUrl) {\n throw new Error('before-after needs app.compareUrl (the \"before\" version) alongside app.url (the \"after\")');\n }\n const side = async (label: string, url: string): Promise<{ videoPath: string; verdict: Verdict }> => {\n const dir = join(opts.outDir, label);\n await mkdir(dir, { recursive: true });\n const sideSpec: Spec = {\n ...spec,\n title: `${spec.title} — ${cap(label)}`,\n app: { ...spec.app, url },\n };\n log.info(`before/after: capturing \"${label}\" (${url})`);\n const { bundleDir } = await capture(sideSpec, { outDir: dir, headless: opts.headless ?? true });\n const bundle = await openBundle(bundleDir);\n const composed = await compose(bundle, sideSpec, { outDir: dir });\n const verdict = await verify(bundle, composed.manifest, composed.videoPath, { outDir: dir, vision: opts.vision ?? false });\n return { videoPath: composed.videoPath, verdict };\n };\n\n // \"Before\" plays first, then \"After\".\n const before = await side('before', spec.app.compareUrl);\n const after = await side('after', spec.app.url);\n\n const videoPath = join(opts.outDir, 'before-after.mp4');\n await concatVideos([before.videoPath, after.videoPath], videoPath);\n\n const publishable = before.verdict.verdict === 'publishable' && after.verdict.verdict === 'publishable';\n log.info(`before/after → ${videoPath}`);\n if (publishable) log.ok('verdict: publishable (both halves)');\n else log.error('verdict: NOT PUBLISHABLE (a half failed)');\n\n return { videoPath, before, after, verdict: publishable ? 'publishable' : 'not-publishable' };\n}\n\nfunction cap(s: string): string {\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n","import { readFile, stat } from 'node:fs/promises';\nimport { join, basename } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport type { Verdict } from '../verify/types.js';\nimport { log } from '../shared/log.js';\nimport { InfraError } from '../shared/exit.js';\n\n/**\n * Jira integration: attach a render's evidence to an EXISTING issue and post a verdict comment.\n * v1 deliberately never creates issues — \"attach proof to the ticket a human opened\" is the\n * tester workflow; auto-filing is ticket noise.\n *\n * Auth is an API token in env vars — Playhead never handles a password:\n * JIRA_BASE_URL e.g. https://yourorg.atlassian.net\n * JIRA_EMAIL the token owner's email\n * JIRA_API_TOKEN from id.atlassian.com/manage-profile/security/api-tokens\n */\n\nexport interface JiraConfig {\n baseUrl: string;\n email: string;\n token: string;\n}\n\nexport function jiraConfigFromEnv(): JiraConfig {\n const baseUrl = process.env.JIRA_BASE_URL;\n const email = process.env.JIRA_EMAIL;\n const token = process.env.JIRA_API_TOKEN;\n if (!baseUrl || !email || !token) {\n throw new InfraError(\n 'Jira is not configured — set JIRA_BASE_URL (https://yourorg.atlassian.net), JIRA_EMAIL, and JIRA_API_TOKEN (create one at id.atlassian.com → Security → API tokens)',\n );\n }\n return { baseUrl: baseUrl.replace(/\\/+$/, ''), email, token };\n}\n\nfunction authHeader(cfg: JiraConfig): string {\n return `Basic ${Buffer.from(`${cfg.email}:${cfg.token}`).toString('base64')}`;\n}\n\nasync function jiraFetch(cfg: JiraConfig, path: string, init?: RequestInit): Promise<Response> {\n const res = await fetch(`${cfg.baseUrl}${path}`, {\n ...init,\n headers: {\n Authorization: authHeader(cfg),\n Accept: 'application/json',\n ...(init?.headers ?? {}),\n },\n });\n return res;\n}\n\n/** Fail fast with a readable message when the issue doesn't exist or auth is wrong. */\nexport async function assertIssue(cfg: JiraConfig, issueKey: string): Promise<{ key: string; summary: string }> {\n const res = await jiraFetch(cfg, `/rest/api/3/issue/${encodeURIComponent(issueKey)}?fields=summary`);\n if (res.status === 404) throw new InfraError(`Jira issue ${issueKey} not found on ${cfg.baseUrl}`);\n if (res.status === 401 || res.status === 403) {\n throw new InfraError(`Jira rejected the credentials for ${cfg.email} (HTTP ${res.status}) — check JIRA_API_TOKEN`);\n }\n if (!res.ok) throw new InfraError(`Jira issue lookup failed: HTTP ${res.status}`);\n const body = (await res.json()) as { key: string; fields?: { summary?: string } };\n return { key: body.key, summary: body.fields?.summary ?? '' };\n}\n\n/** Attach one file. Jira requires multipart/form-data with the XSRF check disabled. */\nexport async function attachFile(cfg: JiraConfig, issueKey: string, filePath: string): Promise<string> {\n const data = await readFile(filePath);\n const form = new FormData();\n form.append('file', new Blob([new Uint8Array(data)]), basename(filePath));\n const res = await jiraFetch(cfg, `/rest/api/3/issue/${encodeURIComponent(issueKey)}/attachments`, {\n method: 'POST',\n headers: { 'X-Atlassian-Token': 'no-check' },\n body: form,\n });\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw new InfraError(`attaching ${basename(filePath)} failed: HTTP ${res.status} ${text.slice(0, 200)}`);\n }\n return basename(filePath);\n}\n\n/** Post an ADF comment. */\nexport async function addComment(cfg: JiraConfig, issueKey: string, adfBody: unknown): Promise<void> {\n const res = await jiraFetch(cfg, `/rest/api/3/issue/${encodeURIComponent(issueKey)}/comment`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ body: adfBody }),\n });\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw new InfraError(`posting the comment failed: HTTP ${res.status} ${text.slice(0, 200)}`);\n }\n}\n\n// ---------- evidence discovery + comment building ----------\n\nexport interface RenderEvidence {\n /** 'publishable' | 'not-publishable' | 'flow-failed' */\n outcome: string;\n verdict?: Verdict;\n failure?: { stepRef: string; message: string; url?: string };\n files: string[];\n}\n\n/** Find whatever evidence a render (successful or failed) left in an out dir. */\nexport async function collectEvidence(outDir: string): Promise<RenderEvidence> {\n const candidates = [\n join(outDir, 'out.mp4'),\n join(outDir, 'failure.mp4'),\n join(outDir, 'verify', 'verdict.json'),\n join(outDir, 'verify', 'contact-sheet.png'),\n join(outDir, 'junit.xml'),\n join(outDir, 'capture', 'failure.json'),\n join(outDir, 'capture', 'console.json'),\n ];\n const files: string[] = [];\n for (const f of candidates) {\n if (!existsSync(f)) continue;\n const s = await stat(f);\n if (s.size > 95 * 1024 * 1024) {\n log.warn(`skipping ${basename(f)} (${(s.size / 1e6).toFixed(0)}MB — larger than Jira's usual attachment ceiling)`);\n continue;\n }\n files.push(f);\n }\n if (files.length === 0) {\n throw new InfraError(`no Playhead artifacts found under ${outDir} — expected out.mp4/failure.mp4, verify/verdict.json, …`);\n }\n\n let verdict: Verdict | undefined;\n const verdictPath = join(outDir, 'verify', 'verdict.json');\n if (existsSync(verdictPath)) verdict = JSON.parse(await readFile(verdictPath, 'utf8')) as Verdict;\n\n let failure: RenderEvidence['failure'];\n const failurePath = join(outDir, 'capture', 'failure.json');\n if (existsSync(failurePath)) failure = JSON.parse(await readFile(failurePath, 'utf8')) as RenderEvidence['failure'];\n\n const outcome = failure ? 'flow-failed' : (verdict?.verdict ?? 'unknown');\n return { outcome, ...(verdict ? { verdict } : {}), ...(failure ? { failure } : {}), files };\n}\n\n/** The verdict comment, as an Atlassian Document Format doc. Kept to simple, universal nodes. */\nexport function buildComment(ev: RenderEvidence, attached: string[]): unknown {\n const text = (t: string, strong = false) => ({\n type: 'text',\n text: t,\n ...(strong ? { marks: [{ type: 'strong' }] } : {}),\n });\n const para = (...content: unknown[]) => ({ type: 'paragraph', content });\n const bullet = (items: string[]) => ({\n type: 'bulletList',\n content: items.map((i) => ({ type: 'listItem', content: [para(text(i))] })),\n });\n\n const content: unknown[] = [];\n if (ev.outcome === 'flow-failed' && ev.failure) {\n content.push(para(text('Playhead: flow FAILED', true), text(` at step ${ev.failure.stepRef}`)));\n content.push(para(text(ev.failure.message.split('\\n')[0] ?? '')));\n if (ev.failure.url) content.push(para(text(`Page at failure: ${ev.failure.url}`)));\n content.push(para(text('The failure clip shows the flow up to the break — watch failure.mp4.')));\n } else if (ev.verdict) {\n const v = ev.verdict;\n content.push(\n para(text(`Playhead verdict: ${v.verdict === 'publishable' ? 'PUBLISHABLE ✅' : 'NOT PUBLISHABLE ❌'}`, true)),\n );\n content.push(\n bullet(\n v.checks.map((c) => `${c.status === 'pass' ? '✓' : c.status === 'fail' ? '✗' : '·'} ${c.id}: ${c.details}`),\n ),\n );\n content.push(\n para(\n text(\n `Provenance: playhead ${v.provenance.playheadVersion} · spec ${v.provenance.specHash.slice(0, 12)}… · captured ${v.provenance.capturedAt} · ${v.provenance.host}${v.signature ? ' · signed' : ' · unsigned'}`,\n ),\n ),\n );\n } else {\n content.push(para(text('Playhead render evidence attached.', true)));\n }\n content.push(para(text(`Attached: ${attached.join(', ')}`)));\n return { type: 'doc', version: 1, content };\n}\n\n/** The whole flow: validate the issue, attach every artifact, post the verdict comment. */\nexport async function reportToJira(issueKey: string, outDir: string, cfg = jiraConfigFromEnv()): Promise<void> {\n const issue = await assertIssue(cfg, issueKey);\n log.info(`reporting to ${issue.key} (“${issue.summary}”) on ${cfg.baseUrl}`);\n const ev = await collectEvidence(outDir);\n const attached: string[] = [];\n for (const f of ev.files) {\n attached.push(await attachFile(cfg, issueKey, f));\n log.ok(`attached ${basename(f)}`);\n }\n await addComment(cfg, issueKey, buildComment(ev, attached));\n log.ok(`verdict comment posted to ${issue.key}`);\n}\n","import type { RawInteractable } from '../capture/driver-api.js';\n\nexport type CatalogKind = 'button' | 'link' | 'input' | 'select' | 'toggle' | 'heading' | 'other';\n\nexport interface CatalogEntry {\n kind: CatalogKind;\n role: string | null;\n name: string | null;\n /** The chosen, validated Playhead locator string. */\n locator: string;\n /** Whether `locator` resolves to exactly one element. */\n unique: boolean;\n /** How likely the locator survives app changes: testid/role+name high, label medium, text low. */\n stability: 'high' | 'medium' | 'low';\n /** Landmark region: nav | header | sidebar | main | dialog | footer | page. */\n region: string;\n bbox: { x: number; y: number; w: number; h: number };\n visible: boolean;\n options?: string[];\n}\n\n/** Stability of a locator string by its engine — a maintenance signal for authors. */\nexport function stabilityOf(locatorRaw: string): 'high' | 'medium' | 'low' {\n const locator = locatorRaw.replace(/^(frame=[^>]+>>\\s*)+/, '').trim();\n if (locator.startsWith('testid=')) return 'high';\n if (locator.startsWith('role=')) return 'high';\n if (locator.startsWith('label=') || locator.startsWith('placeholder=')) return 'medium';\n return 'low'; // text=, css=\n}\n\nconst NAMED_ROLES = new Set(['button', 'link', 'tab', 'switch', 'menuitem', 'heading', 'checkbox', 'radio', 'option']);\nconst FIELD_ROLES = new Set(['textbox', 'searchbox', 'combobox', 'spinbutton']);\n\n/** Ordered locator candidates for an element, best (most resilient/readable) first. */\nexport function candidateLocators(el: RawInteractable): string[] {\n const out: string[] = [];\n const push = (s: string) => {\n if (s && !out.includes(s)) out.push(s);\n };\n const name = el.accessibleName;\n\n if (el.testId) push(`testid=${el.testId}`);\n // Form fields read best by their label.\n if ((FIELD_ROLES.has(el.role ?? '') || el.inputType === 'select') && el.label) push(`label=${quote(el.label)}`);\n if (el.role && name && NAMED_ROLES.has(el.role)) push(`role=${el.role}[name=${quote(name)}]`);\n if (el.label) push(`label=${quote(el.label)}`);\n if (el.placeholder) push(`placeholder=${quote(el.placeholder)}`);\n if (el.role && name && !NAMED_ROLES.has(el.role)) push(`role=${el.role}[name=${quote(name)}]`);\n if (name) push(`text=${quote(name)}`);\n // Elements inside an iframe are only addressable through it.\n if (el.framePrefix) return out.map((l) => `${el.framePrefix} >> ${l}`);\n return out;\n}\n\nexport function kindOf(el: RawInteractable): CatalogKind {\n if (el.inputType === 'select') return 'select';\n if (el.role === 'switch' || el.role === 'checkbox' || el.role === 'radio') return 'toggle';\n if (FIELD_ROLES.has(el.role ?? '')) return 'input';\n if (el.role === 'button') return 'button';\n if (el.role === 'link') return 'link';\n if (el.role === 'heading') return 'heading';\n return 'other';\n}\n\n/** Quote for an EXACT locator match; fall back to a regex when the text has awkward characters. */\nexport function quote(s: string): string {\n const clean = s.replace(/\\s+/g, ' ').trim();\n if (clean.includes('\"')) {\n return `/${escapeRegex(clean).replace(/\\//g, '\\\\/')}/`;\n }\n return `\"${clean}\"`;\n}\n\nfunction escapeRegex(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n","import type { Driver } from '../capture/driver-api.js';\nimport { PlaywrightDriver } from '../capture/playwright-driver.js';\nimport { parseLocator } from '../spec/locators.js';\nimport { candidateLocators, kindOf, stabilityOf, type CatalogEntry } from './catalog.js';\n\nexport interface PageSnapshot {\n url: string;\n title: string;\n aria: string;\n catalog: CatalogEntry[];\n}\n\n/**\n * Explore the app in its current state: read every interactable, choose the first locator\n * candidate that resolves uniquely against the live DOM, and return a grounded catalog.\n * This is what makes authored specs correct by construction — locators are validated here,\n * not discovered to be wrong at render time.\n */\nexport async function snapshotPage(driver: Driver): Promise<PageSnapshot> {\n const [raw, aria, title] = await Promise.all([\n driver.collectInteractables(),\n driver.ariaSnapshot(),\n driver.currentTitle(),\n ]);\n\n const catalog: CatalogEntry[] = [];\n for (const el of raw) {\n if (!el.visible) continue;\n if (el.bbox.w < 2 || el.bbox.h < 2) continue;\n const candidates = candidateLocators(el);\n if (candidates.length === 0) continue;\n\n let chosen: string | null = null;\n let unique = false;\n let ambiguous: string | null = null;\n for (const cand of candidates) {\n const count = await driver.countMatches(parseLocator(cand)).catch(() => 0);\n if (count === 1) {\n chosen = cand;\n unique = true;\n break;\n }\n // Candidates are ordered BEST-first, so the fallback must keep the FIRST ambiguous\n // match, not overwrite with each worse one.\n if (count > 1 && ambiguous === null) ambiguous = cand;\n }\n chosen = chosen ?? ambiguous ?? candidates[0]!;\n catalog.push({\n kind: kindOf(el),\n role: el.role,\n name: el.accessibleName,\n locator: chosen,\n unique,\n stability: stabilityOf(chosen),\n region: el.region ?? 'page',\n bbox: el.bbox,\n visible: el.visible,\n ...(el.options ? { options: el.options } : {}),\n });\n }\n // De-duplicate by locator, keeping the first (top-most) occurrence.\n const byLocator = new Map<string, CatalogEntry>();\n for (const e of catalog) if (!byLocator.has(e.locator)) byLocator.set(e.locator, e);\n\n return { url: driver.currentUrl(), title, aria, catalog: [...byLocator.values()] };\n}\n\n/** One-shot exploration: launch, navigate, snapshot, close. Used by `playhead explore`. */\nexport async function exploreUrl(\n url: string,\n opts?: {\n viewport?: { w: number; h: number };\n headless?: boolean;\n driver?: Driver;\n /** storageState JSON (from `playhead login`) so authed screens are exploreable. */\n storageStatePath?: string;\n },\n): Promise<PageSnapshot> {\n const driver = opts?.driver ?? new PlaywrightDriver();\n const owned = !opts?.driver;\n if (owned) {\n await driver.launch({\n viewport: opts?.viewport ?? { w: 1280, h: 720 },\n dpr: 2,\n headless: opts?.headless ?? true,\n ...(opts?.storageStatePath ? { storageStatePath: opts.storageStatePath } : {}),\n });\n }\n try {\n await driver.goto(url);\n await driver.settle({ idleMs: 300, capMs: 5000 });\n return await snapshotPage(driver);\n } finally {\n if (owned) await driver.close();\n }\n}\n\n/** Render a catalog as a compact, human/agent-readable table: grouped by page REGION (where\n * the element lives), then by kind, with a stability signal per locator. */\nexport function formatCatalog(snap: PageSnapshot): string {\n const lines: string[] = [];\n lines.push(`# ${snap.title || '(untitled)'} — ${snap.url}`);\n lines.push(`# ${snap.catalog.length} interactable elements (stability: ● high · ◐ medium · ○ low)\\n`);\n const regions: Record<string, CatalogEntry[]> = {};\n for (const e of snap.catalog) (regions[e.region] ??= []).push(e);\n const stabMark = { high: '●', medium: '◐', low: '○' } as const;\n for (const region of ['dialog', 'main', 'nav', 'sidebar', 'header', 'footer', 'page']) {\n const items = regions[region];\n if (!items || items.length === 0) continue;\n lines.push(`## ${region}`);\n const groups: Record<string, CatalogEntry[]> = {};\n for (const e of items) (groups[e.kind] ??= []).push(e);\n for (const kind of ['heading', 'link', 'button', 'input', 'select', 'toggle', 'other']) {\n const kindItems = groups[kind];\n if (!kindItems || kindItems.length === 0) continue;\n for (const e of kindItems) {\n const flag = e.unique ? '' : ' ⚠ ambiguous';\n const opts = e.options ? ` options: [${e.options.join(', ')}]` : '';\n lines.push(` ${stabMark[e.stability]} [${kind}] ${e.locator}${flag}${opts}`);\n }\n }\n lines.push('');\n }\n return lines.join('\\n');\n}\n","import type { Spec } from '../spec/schema.js';\nimport { flattenSteps, resolveViewport } from '../spec/schema.js';\nimport { parseLocator } from '../spec/locators.js';\nimport type { Driver } from '../capture/driver-api.js';\nimport { PlaywrightDriver } from '../capture/playwright-driver.js';\nimport { editDistance } from '../spec/schema.js';\nimport { snapshotPage } from './explore.js';\nimport { rectCenter } from '../shared/geometry.js';\n\nexport interface ValidateIssue {\n stepRef: string;\n step: string;\n locator: string;\n severity: 'error' | 'warn';\n message: string;\n suggestions: string[];\n}\n\nexport interface ValidateResult {\n ok: boolean;\n checked: number;\n issues: ValidateIssue[];\n}\n\n/**\n * Live preflight: walk the spec against the running app in ONE browser pass, checking every\n * locator (the action target, the focus hint, waits, expects) *before* any frame is ever\n * captured — and report ALL problems at once with nearest-candidate suggestions from the\n * current screen. Steps are executed fast (no cursor choreography, no filming) so later\n * locators are checked against the state they'll actually meet.\n *\n * This collapses \"one bad locator = one full capture run\" into a single cheap pass.\n */\nexport async function validateLive(\n spec: Spec,\n opts?: { headless?: boolean; driver?: Driver },\n): Promise<ValidateResult> {\n const driver = opts?.driver ?? new PlaywrightDriver();\n const owned = !opts?.driver;\n const issues: ValidateIssue[] = [];\n let checked = 0;\n let stateDiverged = false;\n\n if (owned) {\n await driver.launch({\n viewport: resolveViewport(spec),\n dpr: 1,\n headless: opts?.headless ?? true,\n ...(spec.app.storageState ? { storageStatePath: spec.app.storageState } : {}),\n });\n }\n try {\n await driver.goto(spec.app.url);\n await driver.settle({ idleMs: 300, capMs: 5000 });\n\n for (const a of flattenSteps(spec)) {\n const stepRef = `${a.sceneId}/${a.stepIndex}`;\n const step = a.step;\n const push = async (locator: string, severity: 'error' | 'warn', message: string) => {\n issues.push({\n stepRef,\n step: step.action,\n locator,\n severity,\n message: stateDiverged ? `${message} (after an earlier failure — state may have diverged)` : message,\n suggestions: severity === 'error' ? await suggestFor(driver, locator) : [],\n });\n };\n\n // 1) Check every locator the step names.\n const locators: { value: string; kind: 'target' | 'focus' | 'wait' }[] = [];\n if ('target' in step && step.target) locators.push({ value: step.target, kind: 'target' });\n if (step.action === 'wait' && step.for) locators.push({ value: step.for, kind: 'wait' });\n if (step.focus && step.focus !== 'target' && step.focus !== 'wide') {\n locators.push({ value: step.focus, kind: 'focus' });\n }\n for (const l of locators) {\n checked += 1;\n const count = await driver.countMatches(parseLocator(l.value)).catch(() => 0);\n if (count === 0 && l.kind === 'target') {\n await push(l.value, 'error', 'no matching element on the current screen');\n } else if (count === 0 && l.kind !== 'target') {\n // Focus/wait locators often name a PAYOFF that only exists after the action — not\n // an error before the action runs, but worth confirming after.\n await push(l.value, 'warn', `${l.kind} locator matches nothing yet (may appear after the action)`);\n } else if (count > 1 && !l.value.includes('>> nth=')) {\n await push(l.value, 'warn', `ambiguous: ${count} matches — add '>> nth=N' to pick one`);\n }\n }\n\n // 2) Execute the step fast so downstream locators meet real state.\n try {\n await fastExecute(driver, step);\n } catch (e) {\n if ('target' in step && step.target) {\n const already = issues.some((i) => i.stepRef === stepRef && i.severity === 'error');\n if (!already) await push(step.target ?? '(none)', 'error', `step failed to execute: ${firstLine((e as Error).message)}`);\n }\n stateDiverged = true;\n }\n\n // 3) Post-action: a focus locator that matched nothing must exist NOW.\n const focus = step.focus;\n if (focus && focus !== 'target' && focus !== 'wide') {\n const loc = parseLocator(focus);\n let n = 0;\n for (let i = 0; i < 8 && n === 0; i++) {\n n = await driver.countMatches(loc).catch(() => 0);\n if (n === 0) await sleep(250);\n }\n if (n === 0) await push(focus, 'error', 'focus locator never appeared after the action');\n // Drop the provisional pre-action warn once the payoff shows up.\n if (n > 0) {\n const idx = issues.findIndex((i) => i.stepRef === stepRef && i.locator === focus && i.severity === 'warn');\n if (idx >= 0) issues.splice(idx, 1);\n }\n }\n }\n } finally {\n if (owned) await driver.close();\n }\n return { ok: !issues.some((i) => i.severity === 'error'), checked, issues };\n}\n\n/** Execute a step with no filming, no cursor choreography, minimal waits. */\nasync function fastExecute(driver: Driver, step: import('../spec/schema.js').Step): Promise<void> {\n const FAST_TIMEOUT = step.timeout ?? 8000;\n switch (step.action) {\n case 'goto':\n await driver.goto(step.url);\n break;\n case 'click':\n case 'dblclick': {\n const t = await driver.resolveTarget(parseLocator(step.target), FAST_TIMEOUT);\n await driver.clickAt(rectCenter(t.bbox), { double: step.action === 'dblclick' });\n break;\n }\n case 'hover': {\n const t = await driver.resolveTarget(parseLocator(step.target), FAST_TIMEOUT);\n await driver.moveCursor(rectCenter(t.bbox), 40);\n break;\n }\n case 'type': {\n const t = await driver.resolveTarget(parseLocator(step.target), FAST_TIMEOUT);\n await driver.clickAt(rectCenter(t.bbox));\n await driver.typeText(step.text, 0);\n break;\n }\n case 'press':\n await driver.press(step.keys);\n break;\n case 'select':\n await driver.selectOption(parseLocator(step.target), step.value);\n break;\n case 'scroll':\n if (step.target) await driver.scrollIntoView(parseLocator(step.target));\n else if (step.by) await driver.scrollBy(step.by);\n await driver.waitForScrollSettle(1500);\n break;\n case 'expect':\n await driver.expectState(\n parseLocator(step.target),\n {\n ...(step.visible !== undefined ? { visible: step.visible } : {}),\n ...(step.text !== undefined ? { text: step.text } : {}),\n ...(step.count !== undefined ? { count: step.count } : {}),\n },\n FAST_TIMEOUT,\n );\n break;\n case 'wait':\n if (step.for) {\n await driver.expectState(parseLocator(step.for), { visible: step.state !== 'hidden' }, step.timeout ?? 8000);\n }\n // blind `ms` sleeps are skipped in fast mode\n break;\n }\n await driver.settle({ idleMs: 200, capMs: 2500 });\n}\n\n/** Nearest catalog candidates on the CURRENT screen, by name distance to the broken locator. */\nasync function suggestFor(driver: Driver, locator: string): Promise<string[]> {\n try {\n const snap = await snapshotPage(driver);\n const wanted = displayText(locator).toLowerCase();\n return snap.catalog\n .map((e) => ({ e, d: editDistance(wanted, (e.name ?? displayText(e.locator)).toLowerCase().slice(0, 40)) }))\n .sort((a, b) => a.d - b.d)\n .slice(0, 3)\n .map(({ e }) => `${e.locator}${e.unique ? '' : ' (ambiguous)'}`);\n } catch {\n return [];\n }\n}\n\nfunction displayText(locator: string): string {\n const m = /name=[\"']?([^\\]\"']+)/.exec(locator) ?? /=[\"']?([^\\]\"']+)/.exec(locator);\n return (m?.[1] ?? locator).slice(0, 40);\n}\n\nfunction firstLine(s: string): string {\n return (s.split('\\n')[0] ?? '').slice(0, 160);\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n\n/** Human-readable report for the CLI. */\nexport function formatValidateResult(res: ValidateResult): string {\n const lines: string[] = [];\n for (const i of res.issues) {\n const mark = i.severity === 'error' ? '✗' : '⚠';\n lines.push(`${mark} ${i.stepRef} ${i.step} ${i.locator}`);\n lines.push(` ${i.message}`);\n for (const s of i.suggestions) lines.push(` did you mean: ${s}`);\n }\n const errors = res.issues.filter((i) => i.severity === 'error').length;\n const warns = res.issues.length - errors;\n lines.push('');\n lines.push(\n res.ok\n ? `✓ ${res.checked} locator(s) validated against the live app${warns ? ` (${warns} warning(s))` : ''}`\n : `✗ ${errors} error(s), ${warns} warning(s) across ${res.checked} locator check(s)`,\n );\n return lines.join('\\n');\n}\n","import { stringify } from 'yaml';\n\n/** An action the author loop decided on and (usually) executed to advance the app. */\nexport interface AuthoredStep {\n action: 'goto' | 'click' | 'dblclick' | 'hover' | 'type' | 'press' | 'select' | 'scroll' | 'expect';\n scene: string;\n locator?: string;\n text?: string;\n value?: string;\n keys?: string;\n url?: string;\n visible?: boolean;\n caption?: string;\n mask?: boolean;\n}\n\nexport interface AuthoredSpec {\n title: string;\n url: string;\n viewport: { w: number; h: number };\n kind: string;\n steps: AuthoredStep[];\n}\n\n/** Turn one authored step into the spec's shorthand YAML form. */\nfunction toYamlStep(s: AuthoredStep): Record<string, unknown> {\n const extra: Record<string, unknown> = {};\n if (s.caption) extra.caption = s.caption;\n switch (s.action) {\n case 'goto':\n return { goto: s.url, ...extra };\n case 'press':\n return { press: s.keys, ...extra };\n case 'click':\n case 'dblclick':\n case 'hover':\n return { [s.action]: s.locator, ...extra };\n case 'type':\n return { type: { target: s.locator, text: s.text, ...(s.mask ? { mask: true } : {}) }, ...extra };\n case 'select':\n return { select: { target: s.locator, value: s.value }, ...extra };\n case 'scroll':\n return { scroll: s.locator, ...extra };\n case 'expect':\n return { expect: { target: s.locator, ...(s.visible !== false ? { visible: true } : {}) }, ...extra };\n }\n}\n\nconst kebab = (s: string) =>\n s.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 40) || 'scene';\n\n/** Serialize an authored spec into clean, human-editable Playhead YAML, grouped into scenes. */\nexport function serializeSpec(spec: AuthoredSpec): string {\n const scenes: { id: string; title: string; steps: Record<string, unknown>[] }[] = [];\n const seenIds = new Set<string>();\n for (const step of spec.steps) {\n let scene = scenes[scenes.length - 1];\n if (!scene || scene.title !== step.scene) {\n let id = kebab(step.scene);\n let n = 2;\n while (seenIds.has(id)) id = `${kebab(step.scene)}-${n++}`;\n seenIds.add(id);\n scene = { id, title: step.scene, steps: [] };\n scenes.push(scene);\n }\n scene.steps.push(toYamlStep(step));\n }\n\n const doc = {\n playhead: 1,\n title: spec.title,\n app: { url: spec.url, viewport: `${spec.viewport.w}x${spec.viewport.h}` },\n output: { kind: spec.kind, pacing: 'normal' },\n scenes: scenes.map((s) => ({ id: s.id, title: s.title, steps: s.steps })),\n };\n return (\n '# Authored by `playhead author` — grounded in the live app, every locator validated.\\n' +\n '# Edit freely, then: playhead render this-file.yaml\\n\\n' +\n stringify(doc, { lineWidth: 0 })\n );\n}\n","import { writeFile } from 'node:fs/promises';\nimport { PlaywrightDriver } from '../capture/playwright-driver.js';\nimport type { Driver } from '../capture/driver-api.js';\nimport { parseLocator } from '../spec/locators.js';\nimport { rectCenter } from '../shared/geometry.js';\nimport { snapshotPage, type PageSnapshot } from './explore.js';\nimport { serializeSpec, type AuthoredSpec, type AuthoredStep } from './serialize.js';\nimport { log } from '../shared/log.js';\n\nexport interface StepDecision {\n done: boolean;\n reason?: string;\n scene: string;\n action?: AuthoredStep['action'];\n locator?: string;\n text?: string;\n value?: string;\n keys?: string;\n caption?: string;\n mask?: boolean;\n}\n\n/** Chooses the next step from the current screen. Default is Claude; injectable for tests/policies. */\nexport type Decider = (goal: string, snap: PageSnapshot, soFar: AuthoredStep[]) => Promise<StepDecision>;\n\nexport interface AuthorOptions {\n url: string;\n goal: string;\n outPath: string;\n title?: string;\n viewport: { w: number; h: number };\n maxSteps: number;\n headless: boolean;\n driver?: Driver;\n /** Override the step decider (defaults to the Claude-backed one). */\n decide?: Decider;\n}\n\nconst SETTLE = { idleMs: 300, capMs: 5000 };\n\nconst STEP_TOOL = {\n name: 'emit_step',\n description: 'Emit the single next step of the demo, or finish when the goal is fully shown.',\n input_schema: {\n type: 'object',\n properties: {\n done: { type: 'boolean', description: 'true when the goal has been fully demonstrated' },\n reason: { type: 'string', description: 'one short sentence explaining this choice' },\n scene: { type: 'string', description: 'short human title for the current section, e.g. \"Create a deal\"' },\n action: { type: 'string', enum: ['click', 'dblclick', 'hover', 'type', 'select', 'press', 'scroll', 'expect'] },\n locator: { type: 'string', description: 'a locator copied EXACTLY from the catalog' },\n text: { type: 'string', description: 'text to type (for action=type)' },\n value: { type: 'string', description: 'option to choose (for action=select)' },\n keys: { type: 'string', description: 'key to press, e.g. Enter (for action=press)' },\n caption: { type: 'string', description: 'optional custom caption; omit to auto-write from the label' },\n mask: { type: 'boolean', description: 'true if typing a secret that must be hidden' },\n },\n required: ['done', 'scene'],\n },\n} as const;\n\nconst SYSTEM = `You author Playhead demo specs by walking a REAL running web app toward a goal.\nEach turn you are shown the current screen's catalog of addressable elements — each line is a\nvalidated locator you may use VERBATIM. Rules:\n- Choose the SINGLE next step that best advances the goal, like a person performing the flow once.\n- Use ONLY locators that appear in the current catalog; never invent one. If what you need is not\n visible yet, pick the step that navigates toward it (a nav link, a button that opens a dialog).\n- After you act, the app changes and you will see the next screen's catalog.\n- Prefer role/label locators. Use 'expect' to assert an important result appeared (e.g. a success\n toast or a new row) — it produces no click, just proof.\n- Group steps into scenes with a short 'scene' title; keep the same title across related steps.\n- Set done=true only when the goal is fully shown, then stop.\nKeep the demo tight and legible — a good walkthrough is 6-20 meaningful steps.`;\n\n/** Agent-author a grounded, validated spec by walking the app toward the goal. Needs ANTHROPIC_API_KEY. */\nexport async function authorSpec(opts: AuthorOptions): Promise<{ specPath: string; steps: AuthoredStep[] }> {\n const decide = opts.decide ?? claudeDecider();\n\n const driver = opts.driver ?? new PlaywrightDriver();\n const owned = !opts.driver;\n const steps: AuthoredStep[] = [];\n\n log.info(`authoring \"${opts.goal}\" against ${opts.url}`);\n if (owned) await driver.launch({ viewport: opts.viewport, dpr: 2, headless: opts.headless });\n try {\n await driver.goto(opts.url);\n await driver.settle(SETTLE);\n\n for (let i = 0; i < opts.maxSteps; i++) {\n const snap = await snapshotPage(driver);\n const decision = await decide(opts.goal, snap, steps);\n if (decision.done || !decision.action) {\n log.ok(`agent finished: ${decision.reason ?? 'goal shown'}`);\n break;\n }\n const step = toAuthoredStep(decision);\n log.step(`${steps.length + 1}. ${describe(step)}${decision.reason ? ` — ${decision.reason}` : ''}`);\n try {\n await perform(driver, step);\n await driver.settle(SETTLE);\n steps.push(step);\n } catch (e) {\n log.warn(`step failed (${(e as Error).message}); asking the agent to adjust`);\n // Leave it out of the spec; the next turn re-snapshots the unchanged screen and retries.\n }\n }\n\n if (steps.length === 0) throw new Error('authoring produced no steps — the goal may not be reachable from this URL');\n\n const spec: AuthoredSpec = {\n title: opts.title ?? capitalize(opts.goal),\n url: opts.url,\n viewport: opts.viewport,\n kind: 'walkthrough',\n steps,\n };\n await writeFile(opts.outPath, serializeSpec(spec));\n log.ok(`wrote ${steps.length}-step spec → ${opts.outPath}`);\n log.info(`next: playhead render ${opts.outPath}`);\n return { specPath: opts.outPath, steps };\n } finally {\n if (owned) await driver.close();\n }\n}\n\n/** The default decider: ask Claude for the next step, forcing a structured tool call. */\nexport function claudeDecider(): Decider {\n if (!process.env.ANTHROPIC_API_KEY) {\n throw new Error('playhead author needs ANTHROPIC_API_KEY (the agent that drafts the spec). Set it and retry.');\n }\n const model = process.env.PLAYHEAD_AUTHOR_MODEL ?? 'claude-opus-5';\n let clientPromise: Promise<import('@anthropic-ai/sdk').default> | null = null;\n const getClient = async () => {\n if (!clientPromise) clientPromise = import('@anthropic-ai/sdk').then((m) => new m.default());\n return clientPromise;\n };\n\n return async (goal, snap, soFar) => {\n const client = await getClient();\n const catalog = snap.catalog\n .map((e) => ` ${e.locator}${e.options ? ` (options: ${e.options.join(' | ')})` : ''}${e.unique ? '' : ' [ambiguous]'}`)\n .join('\\n');\n const history = soFar.length ? soFar.map((s, i) => ` ${i + 1}. ${describe(s)}`).join('\\n') : ' (none yet)';\n const userMsg = [\n `GOAL: ${goal}`,\n ``,\n `CURRENT SCREEN: ${snap.title} — ${snap.url}`,\n `ADDRESSABLE ELEMENTS (use these locators verbatim):`,\n catalog || ' (no interactable elements found)',\n ``,\n `STEPS SO FAR:`,\n history,\n ``,\n `Emit the next step (or done=true if the goal is fully shown).`,\n ].join('\\n');\n\n const res = await client.messages.create({\n model,\n max_tokens: 700,\n system: SYSTEM,\n tools: [STEP_TOOL as never],\n tool_choice: { type: 'tool', name: 'emit_step' },\n messages: [{ role: 'user', content: userMsg }],\n });\n const block = res.content.find((b) => b.type === 'tool_use');\n if (!block || block.type !== 'tool_use') return { done: true, scene: 'end', reason: 'no step returned' };\n return block.input as StepDecision;\n };\n}\n\nfunction toAuthoredStep(d: StepDecision): AuthoredStep {\n const s: AuthoredStep = { action: d.action!, scene: d.scene || 'Walkthrough' };\n if (d.locator) s.locator = d.locator;\n if (d.text !== undefined) s.text = d.text;\n if (d.value !== undefined) s.value = d.value;\n if (d.keys !== undefined) s.keys = d.keys;\n if (d.caption) s.caption = d.caption;\n if (d.mask) s.mask = true;\n if (d.action === 'expect') s.visible = true;\n return s;\n}\n\n/** Execute an authored step to advance the live app (no capture; just drives the flow forward). */\nasync function perform(driver: Driver, step: AuthoredStep): Promise<void> {\n const timeout = 10_000;\n switch (step.action) {\n case 'expect':\n // An assertion only — confirm it resolves so the authored spec won't fail at render time.\n if (step.locator) await driver.resolveTarget(parseLocator(step.locator), timeout);\n return;\n case 'press':\n if (step.keys) await driver.press(step.keys);\n return;\n case 'scroll':\n if (step.locator) {\n await driver.scrollIntoView(parseLocator(step.locator));\n await driver.waitForScrollSettle(2500);\n }\n return;\n case 'select':\n if (step.locator && step.value) await driver.selectOption(parseLocator(step.locator), step.value);\n return;\n }\n if (!step.locator) return;\n const loc = parseLocator(step.locator);\n const target = await driver.resolveTarget(loc, timeout);\n const center = rectCenter(target.bbox);\n if (step.action === 'hover') {\n await driver.moveCursor(center, 400);\n return;\n }\n await driver.moveCursor(center, 400);\n await driver.clickAt(center, step.action === 'dblclick' ? { double: true } : undefined);\n if (step.action === 'type' && step.text) {\n await driver.typeText(step.text, 40);\n }\n}\n\nfunction describe(s: AuthoredStep): string {\n switch (s.action) {\n case 'type':\n return `type \"${s.mask ? '••••' : s.text}\" into ${s.locator}`;\n case 'select':\n return `select \"${s.value}\" in ${s.locator}`;\n case 'press':\n return `press ${s.keys}`;\n case 'expect':\n return `expect ${s.locator}`;\n default:\n return `${s.action} ${s.locator}`;\n }\n}\n\nfunction capitalize(s: string): string {\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n","import { mkdtemp, writeFile, mkdir, readFile } from 'node:fs/promises';\nimport { PLAYHEAD_VERSION } from '../shared/version.js';\nimport { tmpdir } from 'node:os';\nimport { join, resolve, isAbsolute } from 'node:path';\nimport { z } from 'zod';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { exploreUrl, formatCatalog } from '../authoring/explore.js';\nimport { authorSpec } from '../authoring/author.js';\nimport { parseSpec, loadSpec } from '../spec/parse.js';\nimport { capture } from '../capture/executor.js';\nimport { openBundle } from '../bundle/reader.js';\nimport { compose } from '../compose/index.js';\nimport { verify } from '../verify/runner.js';\nimport type { Verdict } from '../verify/types.js';\n\n/**\n * Playhead as a set of tools any coding agent can call. The agent grounds its spec with\n * `playhead_explore`, renders with `playhead_render`, and iterates on the returned verdict —\n * the whole author → verify → fix loop, inside the agent's own workspace.\n */\nexport function buildServer(): McpServer {\n const server = new McpServer(\n { name: 'playhead', version: PLAYHEAD_VERSION },\n {\n instructions:\n 'Playhead turns a spec + a live web app into a verified walkthrough video. ' +\n 'To make a demo: (1) call playhead_explore on the running app to get validated locators, ' +\n '(2) write a spec (or call playhead_author), (3) call playhead_render and read the verdict — ' +\n 'fix the spec if it is not publishable. Every locator you use MUST come from an explore catalog. ' +\n 'To attach the result to a ticket, call playhead_jira with the same outDir after rendering.',\n },\n );\n\n const dims = z.string().regex(/^\\d+x\\d+$/).default('1280x720');\n const parseDims = (s: string) => {\n const [w, h] = s.split('x').map(Number);\n return { w: w!, h: h! };\n };\n\n server.registerTool(\n 'playhead_explore',\n {\n title: 'Explore a live app',\n description:\n 'Launch the running web app and return a grounded catalog of addressable elements — each ' +\n 'line is a Playhead locator validated to resolve uniquely against the real DOM. Use these ' +\n 'locators verbatim when writing a spec. Only shows the CURRENT screen; call again after a ' +\n 'navigation to see later screens.',\n inputSchema: {\n url: z.string().describe('the running app URL, e.g. http://localhost:3000'),\n viewport: dims.describe('viewport WxH'),\n },\n },\n async ({ url, viewport }) => {\n const snap = await exploreUrl(url, { viewport: parseDims(viewport), headless: true });\n return { content: [{ type: 'text', text: formatCatalog(snap) }] };\n },\n );\n\n server.registerTool(\n 'playhead_author',\n {\n title: 'Auto-author a spec',\n description:\n 'Walk the app toward a natural-language goal and write a grounded, validated spec file. ' +\n 'Needs ANTHROPIC_API_KEY. Returns the spec path and its YAML. Prefer this for a quick draft; ' +\n 'use explore + your own spec-writing for fine control.',\n inputSchema: {\n url: z.string(),\n goal: z.string().describe('what flow to demo, e.g. \"create a new deal for Globex\"'),\n outPath: z.string().default('playhead.yaml').describe('where to write the spec'),\n viewport: dims,\n },\n },\n async ({ url, goal, outPath, viewport }) => {\n const path = isAbsolute(outPath) ? outPath : resolve(outPath);\n const { steps } = await authorSpec({\n url,\n goal,\n outPath: path,\n viewport: parseDims(viewport),\n maxSteps: 40,\n headless: true,\n });\n const yaml = await readFile(path, 'utf8');\n return { content: [{ type: 'text', text: `Wrote ${steps.length}-step spec to ${path}\\n\\n${yaml}` }] };\n },\n );\n\n server.registerTool(\n 'playhead_validate_spec',\n {\n title: 'Validate a spec',\n description:\n 'Parse a spec (path or inline YAML) and report schema errors. With live: true, ALSO walk ' +\n 'the spec against the running app in one fast browser pass — every locator is checked in ' +\n 'order with nearest-candidate suggestions, before any frame is captured. Run this before ' +\n 'playhead_render: it turns N capture-time failures into one cheap preflight.',\n inputSchema: {\n specPath: z.string().optional().describe('path to a spec file'),\n spec: z.string().optional().describe('inline spec YAML (use instead of specPath)'),\n live: z.boolean().default(false).describe('dry-run every locator against the live app'),\n },\n },\n async ({ specPath, spec, live }) => {\n try {\n const yaml = spec ?? (await readFile(resolve(specPath!), 'utf8'));\n const parsed = parseSpec(yaml);\n const steps = parsed.scenes.reduce((n, s) => n + s.steps.length, 0);\n const header = `✓ Valid spec \"${parsed.title}\" — ${parsed.scenes.length} scenes, ${steps} steps.`;\n if (!live) return { content: [{ type: 'text', text: header }] };\n const { validateLive, formatValidateResult } = await import('../authoring/validate.js');\n const res = await validateLive(parsed);\n return {\n content: [{ type: 'text', text: `${header}\\n\\n${formatValidateResult(res)}` }],\n ...(res.ok ? {} : { isError: true }),\n };\n } catch (e) {\n return { content: [{ type: 'text', text: `✗ ${(e as Error).message}` }], isError: true };\n }\n },\n );\n\n server.registerTool(\n 'playhead_render',\n {\n title: 'Render a verified video',\n description:\n 'Capture the live app per the spec, compose the walkthrough video, and verify it. Returns the ' +\n 'publishable/not-publishable verdict with per-check reasons, plus paths to the MP4, the ' +\n 'compose manifest, and the contact sheet. If not publishable, fix the spec and render again.',\n inputSchema: {\n specPath: z.string().optional(),\n spec: z.string().optional().describe('inline spec YAML (use instead of specPath)'),\n outDir: z.string().default('playhead-out').describe('where to write artifacts'),\n vision: z.boolean().default(false).describe('also run the Claude vision review (needs ANTHROPIC_API_KEY)'),\n },\n },\n async ({ specPath, spec, outDir, vision }) => {\n const out = resolve(outDir);\n await mkdir(out, { recursive: true });\n let parsedSpec;\n if (spec) {\n const tmp = await mkdtemp(join(tmpdir(), 'playhead-spec-'));\n const p = join(tmp, 'spec.yaml');\n await writeFile(p, spec);\n parsedSpec = parseSpec(spec);\n } else {\n parsedSpec = await loadSpec(resolve(specPath!));\n }\n const { bundleDir } = await capture(parsedSpec, { outDir: out, headless: true });\n const bundle = await openBundle(bundleDir);\n const composed = await compose(bundle, parsedSpec, { outDir: out });\n const verdict = await verify(bundle, composed.manifest, composed.videoPath, { outDir: out, vision });\n return {\n content: [{ type: 'text', text: renderVerdictReport(verdict, composed.videoPath, composed.manifestPath) }],\n isError: verdict.verdict !== 'publishable',\n };\n },\n );\n\n server.registerTool(\n 'playhead_jira',\n {\n title: 'Post render evidence to Jira',\n description:\n 'Attach a render\\'s evidence to an EXISTING Jira issue and post a verdict comment — the ' +\n 'video (or failure clip), verdict.json, contact sheet, JUnit, and console log, plus a ' +\n 'comment carrying the per-check table (or the failing step + error for a flow failure). ' +\n 'Run this AFTER playhead_render, pointing outDir at the same directory. Reports to ' +\n 'existing issues only (never creates them). Requires JIRA_BASE_URL, JIRA_EMAIL, and ' +\n 'JIRA_API_TOKEN in the environment — Playhead never handles a password.',\n inputSchema: {\n issueKey: z.string().describe('the existing Jira issue key, e.g. PROJ-123'),\n outDir: z.string().default('playhead-out').describe('the render output directory (same one passed to playhead_render)'),\n },\n },\n async ({ issueKey, outDir }) => {\n try {\n const { reportToJira, collectEvidence } = await import('../integrations/jira.js');\n const out = resolve(outDir);\n await reportToJira(issueKey, out);\n const ev = await collectEvidence(out);\n return {\n content: [\n {\n type: 'text',\n text: `Posted to ${issueKey}: attached ${ev.files.length} artifact(s) [${ev.files\n .map((f) => f.split('/').pop())\n .join(', ')}] and a ${ev.outcome} verdict comment.`,\n },\n ],\n };\n } catch (e) {\n return { content: [{ type: 'text', text: `✗ Jira report failed: ${(e as Error).message}` }], isError: true };\n }\n },\n );\n\n return server;\n}\n\nfunction renderVerdictReport(verdict: Verdict, videoPath: string, manifestPath: string): string {\n const lines: string[] = [];\n lines.push(`VERDICT: ${verdict.verdict.toUpperCase()}`);\n lines.push('');\n for (const c of verdict.checks) {\n const mark = c.status === 'pass' ? '✓' : c.status === 'fail' ? '✗' : c.status === 'warn' ? '⚠' : '·';\n lines.push(`${mark} ${c.id}: ${c.details}`);\n for (const e of c.evidence ?? []) {\n lines.push(` ${e.stepRef ?? ''}${e.t !== undefined ? ` @${(e.t / 1000).toFixed(1)}s` : ''} — ${e.note}`);\n }\n }\n lines.push('');\n lines.push(`video: ${videoPath}`);\n lines.push(`manifest: ${manifestPath}`);\n lines.push(`contact sheet:${verdict.contactSheet}`);\n if (verdict.verdict !== 'publishable') lines.push('\\nFix the flagged steps in the spec and render again.');\n return lines.join('\\n');\n}\n\n/** Start the stdio MCP server (called by `playhead mcp`). */\nexport async function startMcpServer(): Promise<void> {\n const server = buildServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n","#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { mkdir, writeFile, access } from 'node:fs/promises';\nimport { join, resolve } from 'node:path';\nimport pc from 'picocolors';\nimport { loadSpec } from '../spec/parse.js';\nimport { capture } from '../capture/executor.js';\nimport { openBundle } from '../bundle/reader.js';\nimport { compose } from '../compose/index.js';\nimport { verify, loadComposeManifest } from '../verify/runner.js';\nimport { resolveTheme } from '../theme/index.js';\nimport { ffmpegPath, ffprobePath, runBinary } from '../shared/ffmpeg.js';\nimport { log, setVerbose } from '../shared/log.js';\nimport { sha256Json, sha256File } from '../bundle/hash.js';\nimport { EXIT, exitCodeFor, FlowError } from '../shared/exit.js';\nimport { PLAYHEAD_VERSION } from '../shared/version.js';\nimport type { Verdict } from '../verify/types.js';\n\n/** Emit machine-readable outputs for a verdict (stdout JSON and/or a JUnit file). */\nasync function emitReports(verdict: Verdict, opts: { json?: boolean; junit?: string }): Promise<void> {\n if (opts.json) console.log(JSON.stringify(verdict, null, 2));\n if (opts.junit) {\n const { toJUnit } = await import('../verify/report.js');\n await writeFile(resolve(opts.junit), toJUnit(verdict));\n log.ok(`junit → ${opts.junit}`);\n }\n}\n\nconst program = new Command();\n\nprogram\n .name('playhead')\n .description('Product video as a build artifact: spec + live product → finished, verified video.')\n .version(PLAYHEAD_VERSION)\n .option('--verbose', 'debug logging');\n\nprogram.hook('preAction', (cmd) => {\n if (cmd.opts().verbose) setVerbose(true);\n});\n\nprogram\n .command('render')\n .description('capture → compose → verify; exit 0 only if every spec is publishable')\n .argument('<specs...>', 'spec YAML path(s) — multiple files render as a pool')\n .option('-o, --out <dir>', 'output directory (per-spec subdirs when rendering several)', 'out')\n .option('-w, --workers <n>', 'concurrent renders when given multiple specs', '2')\n .option('--vision', 'run the Claude vision review (needs ANTHROPIC_API_KEY)')\n .option('--json', 'print the verdict JSON to stdout (human logs go to stderr)')\n .option('--junit <path>', 'write a JUnit XML report (one testcase per check)')\n .option('--jira <issueKey>', 'report the outcome (evidence + verdict comment) to an existing Jira issue — success OR flow failure')\n .option('--headed', 'show the browser while capturing')\n .action(async (specPaths: string[], opts: { out: string; workers: string; vision?: boolean; json?: boolean; junit?: string; jira?: string; headed?: boolean }) => {\n // Exit contract: 0 pass · 1 flow failure (app broke; failure clip rendered) ·\n // 2 quality failure (not publishable) · 3 infra · 4 usage.\n const renderOne = async (specPath: string, outDir: string): Promise<number> => {\n const spec = await loadSpec(specPath);\n await mkdir(outDir, { recursive: true });\n if (spec.output.kind === 'before-after') {\n const { renderBeforeAfter } = await import('../beforeafter.js');\n const res = await renderBeforeAfter(spec, { outDir, headless: !opts.headed, vision: opts.vision ?? false });\n return res.verdict === 'publishable' ? EXIT.OK : EXIT.QUALITY;\n }\n try {\n const { bundleDir } = await capture(spec, { outDir, headless: !opts.headed });\n const bundle = await openBundle(bundleDir);\n const result = await compose(bundle, spec, { outDir });\n const verdict = await verify(bundle, result.manifest, result.videoPath, {\n outDir,\n vision: opts.vision ?? false,\n });\n await emitReports(verdict, opts);\n return verdict.verdict === 'publishable' ? EXIT.OK : EXIT.QUALITY;\n } catch (e) {\n if (e instanceof FlowError) {\n log.error(e.message);\n // FAILURE CLIP: compose the partial bundle so the red run hands the developer\n // something to WATCH — the flow up to the break, ending on a card naming it.\n try {\n const bundle = await openBundle(join(outDir, 'capture'));\n const result = await compose(bundle, spec, { outDir, fileName: 'failure.mp4' });\n log.ok(`failure clip → ${result.videoPath}`);\n } catch (clipErr) {\n log.warn(`could not render the failure clip: ${(clipErr as Error).message}`);\n }\n return EXIT.FLOW;\n }\n throw e;\n }\n };\n\n if (specPaths.length === 1) {\n const code = await renderOne(specPaths[0]!, resolve(opts.out));\n // Report the outcome to Jira EITHER way: a publishable video is fix-verification\n // evidence; a flow failure attaches the failure clip + diagnosis. Reporting problems\n // never mask the render's own exit code.\n if (opts.jira && code !== EXIT.INFRA && code !== EXIT.USAGE) {\n try {\n const { reportToJira } = await import('../integrations/jira.js');\n await reportToJira(opts.jira, resolve(opts.out));\n } catch (e) {\n log.error(`jira report failed: ${(e as Error).message}`);\n }\n }\n process.exitCode = code;\n return;\n }\n if (opts.jira) log.warn('--jira is single-spec only for now — skipping the report for this multi-spec pool');\n\n // Pool: N specs render concurrently, each in its own browser and its own out subdir.\n // Compose/verify are pure functions of the bundle, so parallelism is safe by construction.\n const workers = Math.max(1, Number(opts.workers) || 2);\n log.info(`rendering ${specPaths.length} specs with ${workers} worker(s)`);\n const queue = [...specPaths];\n const results = new Map<string, number | Error>();\n await Promise.all(\n Array.from({ length: Math.min(workers, queue.length) }, async () => {\n for (let path = queue.shift(); path !== undefined; path = queue.shift()) {\n const name = path.replace(/\\.ya?ml$/, '').split('/').pop()!;\n try {\n results.set(path, await renderOne(path, resolve(join(opts.out, name))));\n } catch (e) {\n results.set(path, e as Error);\n }\n }\n }),\n );\n // Pool exit code: the worst individual outcome.\n let worst = EXIT.OK as number;\n for (const [path, res] of results) {\n if (res === EXIT.OK) log.ok(path);\n else if (typeof res === 'number') {\n worst = Math.max(worst, res);\n log.error(`${path} — ${res === EXIT.FLOW ? 'flow failed' : 'not publishable'}`);\n } else {\n worst = Math.max(worst, exitCodeFor(res));\n log.error(`${path} — ${res.message.split('\\n')[0]}`);\n }\n }\n process.exitCode = worst;\n });\n\nprogram\n .command('capture')\n .description('capture a live app into a re-renderable bundle')\n .argument('<spec>', 'path to spec YAML')\n .option('-o, --out <dir>', 'output directory', 'out')\n .option('--from-scene <id>', 'fast-forward earlier steps (state only, unfilmed) and film from this scene — for iterating on one scene')\n .option('--headed', 'show the browser while capturing')\n .action(async (specPath: string, opts: { out: string; headed?: boolean; fromScene?: string }) => {\n const spec = await loadSpec(specPath);\n await mkdir(resolve(opts.out), { recursive: true });\n await capture(spec, { outDir: resolve(opts.out), headless: !opts.headed, ...(opts.fromScene ? { fromScene: opts.fromScene } : {}) });\n });\n\nprogram\n .command('compose')\n .description('re-render video from a capture bundle — no live app needed')\n .argument('<bundle>', 'path to a capture bundle directory')\n .option('-o, --out <dir>', 'output directory (default: bundle parent)')\n .option(\n '--spec <file>',\n 'compose with a LIVE spec file instead of the bundled snapshot — captions, narration, theme, audio, pacing all come from it, so text edits are a re-compose, never a re-capture',\n )\n .option('--expect-sha <hex>', 'assert the rendered MP4 hashes to this sha256 (determinism check: same bundle + spec → same video)')\n .action(async (bundleDir: string, opts: { out?: string; spec?: string; expectSha?: string }) => {\n const bundle = await openBundle(resolve(bundleDir));\n const spec = opts.spec\n ? await loadSpec(resolve(opts.spec))\n : JSON.parse(\n await (await import('node:fs/promises')).readFile(join(resolve(bundleDir), 'spec.resolved.json'), 'utf8'),\n );\n if (opts.spec && sha256Json(spec.scenes.map((s: { id: string }) => s.id)) !== sha256Json(\n (JSON.parse(await (await import('node:fs/promises')).readFile(join(resolve(bundleDir), 'spec.resolved.json'), 'utf8')) as { scenes: { id: string }[] }).scenes.map((s) => s.id),\n )) {\n log.warn('--spec scene ids differ from the captured spec — steps that moved will keep their captured footage positions');\n }\n const outDir = resolve(opts.out ?? join(resolve(bundleDir), '..'));\n await mkdir(outDir, { recursive: true });\n const result = await compose(bundle, spec, { outDir, theme: resolveTheme(spec) });\n if (opts.expectSha) {\n const got = result.manifest.videoSha256 ?? (await sha256File(result.videoPath));\n if (got !== opts.expectSha.toLowerCase()) {\n log.error(`determinism check failed: rendered ${got.slice(0, 16)}…, expected ${opts.expectSha.slice(0, 16)}…`);\n process.exitCode = EXIT.QUALITY;\n } else {\n log.ok(`determinism check: sha256 matches (${got.slice(0, 16)}…)`);\n }\n }\n });\n\nprogram\n .command('validate')\n .description('preflight a spec against the LIVE app: every locator checked in one pass, all failures reported with suggestions — before a single frame is captured')\n .argument('<spec>', 'path to spec YAML')\n .option('--headed', 'show the browser')\n .action(async (specPath: string, opts: { headed?: boolean }) => {\n const spec = await loadSpec(specPath);\n const { validateLive, formatValidateResult } = await import('../authoring/validate.js');\n log.info(`validating \"${spec.title}\" against ${spec.app.url}`);\n const res = await validateLive(spec, { headless: !opts.headed });\n console.log(formatValidateResult(res));\n process.exitCode = res.ok ? 0 : 1;\n });\n\nprogram\n .command('login')\n .description('open a headed browser for you to log in, then save the session for authed captures (app.storageState) — Playhead never sees credentials')\n .argument('<url>', 'the app login URL')\n .option('-o, --out <file>', 'where to save the storage state', 'playhead-session.json')\n .action(async (url: string, opts: { out: string }) => {\n const { PlaywrightDriver } = await import('../capture/playwright-driver.js');\n const driver = new PlaywrightDriver();\n await driver.launch({ viewport: { w: 1440, h: 900 }, dpr: 1, headless: false });\n await driver.goto(url);\n log.info('log in in the browser window, then press Enter here to save the session…');\n await new Promise<void>((res) => {\n process.stdin.resume();\n process.stdin.once('data', () => res());\n });\n await driver.saveStorageState(resolve(opts.out));\n await driver.close();\n process.stdin.pause();\n log.ok(`session saved → ${opts.out} (reference it from the spec: app.storageState: ${opts.out})`);\n });\n\nprogram\n .command('jira')\n .description('report render evidence to an EXISTING Jira issue: attach the video/failure clip, verdict, contact sheet, and console log, and post a verdict comment')\n .argument('<action>', 'only \"report\" for now')\n .argument('<issueKey>', 'e.g. PROJ-123')\n .option('-o, --out <dir>', 'the render output directory holding the artifacts', 'out')\n .action(async (action: string, issueKey: string, opts: { out: string }) => {\n if (action !== 'report') {\n log.error(`unknown jira action \"${action}\" — only \"report\" is supported`);\n process.exitCode = EXIT.USAGE;\n return;\n }\n const { reportToJira } = await import('../integrations/jira.js');\n await reportToJira(issueKey, resolve(opts.out));\n });\n\nprogram\n .command('verify')\n .description('run the verification suite against a rendered video')\n .argument('<bundle>', 'path to the capture bundle directory')\n .argument('<video>', 'path to the rendered MP4')\n .option('-m, --manifest <path>', 'compose manifest path (default: next to the video)')\n .option('--vision', 'run the Claude vision review')\n .option('--json', 'print the verdict JSON to stdout')\n .option('--junit <path>', 'write a JUnit XML report')\n .action(async (bundleDir: string, videoPath: string, opts: { manifest?: string; vision?: boolean; json?: boolean; junit?: string }) => {\n const bundle = await openBundle(resolve(bundleDir));\n const manifestPath = opts.manifest ?? join(resolve(videoPath), '..', 'compose-manifest.json');\n const manifest = await loadComposeManifest(manifestPath);\n const verdict = await verify(bundle, manifest, resolve(videoPath), {\n outDir: join(resolve(videoPath), '..'),\n vision: opts.vision ?? false,\n });\n await emitReports(verdict, opts);\n process.exitCode = verdict.verdict === 'publishable' ? EXIT.OK : EXIT.QUALITY;\n });\n\nprogram\n .command('attest')\n .description('re-verify a verdict.json: artifact hashes recomputed, signature checked (PLAYHEAD_SIGNING_KEY) — proves the verdict describes THESE files and was not edited')\n .argument('<verdict>', 'path to verdict.json (or the verify/ directory containing it)')\n .option('--bundle <dir>', 'also re-hash the capture bundle against the verdict')\n .action(async (verdictPath: string, opts: { bundle?: string }) => {\n const { readFile } = await import('node:fs/promises');\n const p = verdictPath.endsWith('.json') ? resolve(verdictPath) : join(resolve(verdictPath), 'verdict.json');\n const verdict = JSON.parse(await readFile(p, 'utf8')) as Verdict;\n let ok = true;\n\n const videoSha = await sha256File(verdict.video.path).catch(() => null);\n if (videoSha === verdict.video.sha256) log.ok(`video sha256 matches (${videoSha!.slice(0, 12)}…)`);\n else {\n ok = false;\n log.error(`video hash mismatch: verdict says ${verdict.video.sha256.slice(0, 12)}…, file is ${videoSha ? videoSha.slice(0, 12) + '…' : 'missing'}`);\n }\n\n if (opts.bundle) {\n const bundle = await openBundle(resolve(opts.bundle));\n const events = sha256Json(bundle.events);\n const frames = sha256Json(bundle.frames);\n if (events === verdict.bundleHashes.events && frames === verdict.bundleHashes.framesIndex) {\n log.ok('bundle hashes match (events + frame index)');\n } else {\n ok = false;\n log.error('bundle hash mismatch — the bundle is not the one this verdict describes');\n }\n }\n\n const { signVerdict, signablePayload } = await import('../verify/report.js');\n if (!verdict.signature) {\n log.warn('verdict is unsigned (no PLAYHEAD_SIGNING_KEY at verify time) — content integrity not attestable');\n } else if (!process.env.PLAYHEAD_SIGNING_KEY) {\n ok = false;\n log.error('verdict is signed but PLAYHEAD_SIGNING_KEY is not set — cannot check the signature');\n } else {\n const { signature: _sig, ...unsigned } = verdict;\n void signablePayload; // (payload construction is inside signVerdict)\n const expect = signVerdict(unsigned);\n if (expect === verdict.signature) log.ok('signature valid — verdict content is untampered');\n else {\n ok = false;\n log.error('SIGNATURE MISMATCH — the verdict was modified after signing');\n }\n }\n log.info(\n `provenance: playhead ${verdict.provenance.playheadVersion}, spec ${verdict.provenance.specHash.slice(0, 12)}…, captured ${verdict.provenance.capturedAt}, ${verdict.provenance.host}`,\n );\n process.exitCode = ok ? EXIT.OK : EXIT.QUALITY;\n });\n\nprogram\n .command('explore')\n .description('inspect a live app and print a grounded catalog of addressable elements')\n .argument('<url>', 'the running app URL to explore')\n .option('--viewport <wxh>', 'viewport, e.g. 1280x720', '1280x720')\n .option('--storage-state <file>', 'session file from \"playhead login\" for authed screens')\n .option('--headed', 'show the browser')\n .action(async (url: string, opts: { viewport: string; headed?: boolean; storageState?: string }) => {\n const { exploreUrl, formatCatalog } = await import('../authoring/explore.js');\n const [w, h] = opts.viewport.split('x').map(Number);\n const snap = await exploreUrl(url, { viewport: { w: w!, h: h! }, headless: !opts.headed, ...(opts.storageState ? { storageStatePath: resolve(opts.storageState) } : {}) });\n console.log(formatCatalog(snap));\n });\n\nprogram\n .command('author')\n .description('agent-author a grounded, validated spec by exploring the app toward a goal')\n .argument('<url>', 'the running app URL')\n .argument('<goal>', 'natural-language description of the flow to demo')\n .option('-o, --out <file>', 'where to write the spec', 'playhead.yaml')\n .option('--title <title>', 'video title (defaults to the goal)')\n .option('--kind <kind>', 'output kind', 'walkthrough')\n .option('--viewport <wxh>', 'viewport', '1280x720')\n .option('--max-steps <n>', 'safety cap on authored steps', '40')\n .option('--headed', 'show the browser')\n .action(async (url: string, goal: string, opts: { out: string; title?: string; kind: string; viewport: string; maxSteps: string; headed?: boolean }) => {\n const { authorSpec } = await import('../authoring/author.js');\n const [w, h] = opts.viewport.split('x').map(Number);\n await authorSpec({\n url,\n goal,\n outPath: resolve(opts.out),\n ...(opts.title ? { title: opts.title } : {}),\n viewport: { w: w!, h: h! },\n maxSteps: Number(opts.maxSteps),\n headless: !opts.headed,\n });\n });\n\nprogram\n .command('init')\n .description('scaffold a starter spec')\n .argument('[path]', 'where to write it', 'playhead.yaml')\n .action(async (path: string) => {\n try {\n await access(path);\n log.error(`${path} already exists`);\n process.exitCode = 1;\n return;\n } catch {\n /* does not exist — good */\n }\n await writeFile(path, STARTER_SPEC);\n log.ok(`wrote ${path} — edit it, then run: playhead render ${path}`);\n });\n\nprogram\n .command('mcp')\n .description('run Playhead as an MCP server (stdio) so a coding agent can drive it')\n .action(async () => {\n const { startMcpServer } = await import('../mcp/server.js');\n await startMcpServer();\n });\n\nprogram\n .command('doctor')\n .description('check that ffmpeg, the browser, and fonts are ready')\n .option('--ci', 'also check CI/container prerequisites (TTS, sandbox, shm)')\n .action(async (opts: { ci?: boolean }) => {\n let ok = true;\n if (opts.ci) {\n // TTS availability: narration degrades to silent when absent, but CI should know.\n const { execFile } = await import('node:child_process');\n const { promisify } = await import('node:util');\n const which = promisify(execFile);\n const hasSay = await which('which', ['say']).then(() => true).catch(() => false);\n if (hasSay) log.ok('tts (say): macOS `say` available');\n else log.info('tts (say): no `say` binary here — the `say` provider is macOS-only');\n // kokoro: the natural, cross-platform voice — needs the optional kokoro-js package.\n const hasKokoro = await import('kokoro-js' as string).then(() => true).catch(() => false);\n if (hasKokoro) log.ok('tts (kokoro): kokoro-js installed — the natural offline voice is available');\n else log.warn('tts (kokoro): kokoro-js not installed — `provider: kokoro` needs `npm i -g kokoro-js` (~400MB, one time)');\n if (process.platform === 'linux') {\n log.info('linux: run chromium with a base image that provides fonts + sandbox deps (see Dockerfile), and give /dev/shm ≥ 512MB or pass --disable-dev-shm-usage');\n }\n if (!process.env.PLAYHEAD_SIGNING_KEY) log.warn('signing: PLAYHEAD_SIGNING_KEY not set — verdicts will be unsigned');\n else log.ok('signing: PLAYHEAD_SIGNING_KEY set');\n }\n try {\n const res = await runBinary(ffmpegPath(), ['-version']);\n log.ok(`ffmpeg: ${res.stdout.split('\\n')[0]}`);\n } catch (e) {\n ok = false;\n log.error(`ffmpeg: ${(e as Error).message}`);\n }\n try {\n const res = await runBinary(ffprobePath(), ['-version']);\n log.ok(`ffprobe: ${res.stdout.split('\\n')[0]}`);\n } catch (e) {\n ok = false;\n log.error(`ffprobe: ${(e as Error).message}`);\n }\n try {\n const { chromium } = await import('playwright');\n const path = chromium.executablePath();\n await access(path);\n log.ok(`chromium: ${path}`);\n } catch {\n ok = false;\n log.error('chromium: not installed — run: npx playwright install chromium');\n }\n try {\n const { registerFonts } = await import('../theme/index.js');\n registerFonts();\n log.ok('fonts: Inter registered');\n } catch (e) {\n ok = false;\n log.error(`fonts: ${(e as Error).message}`);\n }\n if (!process.env.ANTHROPIC_API_KEY) log.info(pc.dim('vision review: ANTHROPIC_API_KEY not set (optional)'));\n process.exitCode = ok ? 0 : 1;\n });\n\nconst STARTER_SPEC = `playhead: 1\ntitle: \"My product walkthrough\"\napp:\n url: http://localhost:3000\n viewport: 1280x720\noutput:\n kind: walkthrough\n pacing: normal\nscenes:\n - id: first-flow\n title: \"Do the thing\"\n steps:\n - click: 'role=button[name=\"Get started\"]'\n - type: { target: 'label=Name', text: \"Ada Lovelace\" }\n - click: 'role=button[name=\"Save\"]'\n - expect: { target: 'text=\"Saved\"', visible: true }\n`;\n\nprogram.parseAsync().catch((e: Error) => {\n log.error(e.message);\n // 4 = usage (bad spec/args) · 1 = flow (app broke) · 3 = infra (everything else unexpected)\n process.exitCode = exitCodeFor(e);\n});\n"],"mappings":"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","names":["ctx","resolve","count","resolve","plane","join","sleep","writeFile","resolve","round1","readFile","join","join","dirname","createRequire","require","log","log","log","plane","shot","log","plan","log","lowerFirst","ctx","ctx","sharp","createCanvas","ctx","createRequire","require","resolve","writeFile","mkdtemp","join","tmpdir","spawn","resolve","createCanvas","plane","ctx","mkdir","writeFile","existsSync","join","createHash","createRequire","ffprobePath","require","execFile","promisify","mkdir","existsSync","join","createRequire","exec","ffmpegPath","require","join","writeFile","sharp","ctx","rect","cap","CLICK_KINDS","writeFile","createCanvas","ctx","truncate","readFile","join","mkdir","writeFile","readFile","pc","ctx","join","mkdir","readFile","join","existsSync","content","firstLine","sleep","writeFile","SETTLE","writeFile","mkdir","readFile","join","z","validateLive","formatValidateResult","reportToJira","collectEvidence","mkdir","writeFile","join","resolve","pc","toJUnit","renderBeforeAfter","reportToJira","validateLive","formatValidateResult","PlaywrightDriver","readFile","signVerdict","signablePayload","exploreUrl","formatCatalog","authorSpec","startMcpServer","execFile","promisify","chromium","registerFonts"]}
|