@a-company/atelier 0.29.0 → 0.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-5QQESXI6.js +4432 -0
- package/dist/chunk-5QQESXI6.js.map +1 -0
- package/dist/cli.cjs +2391 -530
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +301 -429
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +2233 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +584 -2
- package/dist/index.d.ts +584 -2
- package/dist/index.js +111 -3
- package/dist/mcp.cjs +1215 -365
- package/dist/mcp.cjs.map +1 -1
- package/dist/mcp.js +1209 -365
- package/dist/mcp.js.map +1 -1
- package/package.json +20 -9
- package/src/web/inline-app.ts +867 -0
- package/src/web/tsconfig.json +9 -0
- package/templates/welcome.atelier +67 -0
- package/university/content/notes/N-atel-001-first-render.md +114 -0
- package/university/content/notes/N-atel-001-install-and-launch.md +84 -0
- package/university/content/notes/N-atel-001-what-is-atelier.md +51 -0
- package/university/content/notes/N-atel-101-easings.md +97 -0
- package/university/content/notes/N-atel-101-layers.md +106 -0
- package/university/content/notes/N-atel-101-states-and-deltas.md +94 -0
- package/university/content/notes/N-atel-101-the-atelier-format.md +72 -0
- package/university/content/notes/N-atel-201-authoring-tools.md +141 -0
- package/university/content/notes/N-atel-201-mcp-overview.md +86 -0
- package/university/content/notes/N-atel-201-patterns.md +108 -0
- package/university/content/notes/N-atel-201-visual-and-effects.md +125 -0
- package/university/content/notes/N-atel-301-composition-and-overlays.md +141 -0
- package/university/content/notes/N-atel-301-effects.md +136 -0
- package/university/content/notes/N-atel-301-images-and-video.md +126 -0
- package/university/content/notes/N-atel-301-shapes-and-text.md +118 -0
- package/university/content/notes/N-atel-401-hierarchical-states.md +71 -0
- package/university/content/notes/N-atel-401-motion-deep-dive.md +106 -0
- package/university/content/notes/N-atel-401-presets-and-templates.md +98 -0
- package/university/content/notes/N-atel-401-transitions.md +94 -0
- package/university/content/notes/N-atel-501-detected-vs-user-edited.md +76 -0
- package/university/content/notes/N-atel-501-layer-tag-isolation.md +62 -0
- package/university/content/notes/N-atel-501-silence-trim.md +98 -0
- package/university/content/notes/N-atel-501-transcribe-and-captions.md +98 -0
- package/university/content/notes/N-atel-601-carousel.md +71 -0
- package/university/content/notes/N-atel-601-overlay-rules.md +96 -0
- package/university/content/notes/N-atel-601-recipe-tools-and-apply.md +84 -0
- package/university/content/notes/N-atel-601-studio-recipe.md +103 -0
- package/university/content/notes/N-atel-701-choosing-output.md +68 -0
- package/university/content/notes/N-atel-701-png-and-frames.md +84 -0
- package/university/content/notes/N-atel-701-vector.md +85 -0
- package/university/content/notes/N-atel-701-video.md +88 -0
- package/university/content/notes/N-atel-801-editing-surface.md +69 -0
- package/university/content/notes/N-atel-801-live-bridge.md +84 -0
- package/university/content/notes/N-atel-801-studio-app.md +72 -0
- package/university/content/notes/N-atel-801-symbiotic-loop.md +56 -0
- package/university/content/paths/LP-atel-001.yaml +21 -0
- package/university/content/paths/LP-atel-101.yaml +22 -0
- package/university/content/paths/LP-atel-201.yaml +23 -0
- package/university/content/paths/LP-atel-301.yaml +22 -0
- package/university/content/paths/LP-atel-401.yaml +22 -0
- package/university/content/paths/LP-atel-501.yaml +22 -0
- package/university/content/paths/LP-atel-601.yaml +22 -0
- package/university/content/paths/LP-atel-701.yaml +22 -0
- package/university/content/paths/LP-atel-801.yaml +22 -0
- package/university/content/quizzes/Q-atel-001-orientation.yaml +66 -0
- package/university/content/quizzes/Q-atel-101-document-model.yaml +66 -0
- package/university/content/quizzes/Q-atel-201-mcp-authoring.yaml +66 -0
- package/university/content/quizzes/Q-atel-301-visual-system.yaml +66 -0
- package/university/content/quizzes/Q-atel-401-state-machines.yaml +66 -0
- package/university/content/quizzes/Q-atel-501-video-pipeline.yaml +66 -0
- package/university/content/quizzes/Q-atel-601-recipes.yaml +66 -0
- package/university/content/quizzes/Q-atel-701-export.yaml +66 -0
- package/university/content/quizzes/Q-atel-801-studio-loop.yaml +66 -0
- package/university/index.yaml +720 -0
- package/university/pack.yaml +21 -0
- package/dist/chunk-JV7RGETS.js +0 -2292
- package/dist/chunk-JV7RGETS.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/validate.ts","../../schema/src/units.ts","../../schema/src/coordinates.ts","../../schema/src/color.ts","../../schema/src/shape.ts","../../schema/src/easing.ts","../../schema/src/shadow.ts","../../schema/src/layer.ts","../../schema/src/interaction.ts","../../schema/src/delta.ts","../../schema/src/state.ts","../../schema/src/preset.ts","../../schema/src/variable.ts","../../schema/src/asset.ts","../../schema/src/document.ts","../../schema/src/recipe.ts","../../schema/src/validate.ts","../../schema/src/parse.ts","../src/lib/video-project.ts","../src/lib/recipe.ts","../src/lib/silence-detect.ts","../src/lib/cut-model.ts","../src/commands/trim.ts","../src/lib/whisper.ts","../src/lib/transcript-model.ts","../src/lib/caption-builder.ts","../src/commands/transcribe.ts","../src/commands/transcript.ts","../src/commands/captions.ts","../src/commands/recipe.ts","../src/commands/apply-recipe.ts","../src/lib/render-image.ts","../src/commands/carousel.ts","../src/commands/info.ts","../src/commands/still.ts","../src/commands/render-pipeline.ts","../src/commands/render.ts","../src/commands/export-svg.ts","../../svg/src/render-svg.ts","../../svg/src/svg-properties.ts","../../svg/src/svg-gradients.ts","../../svg/src/svg-shapes.ts","../../svg/src/svg-text.ts","../../svg/src/svg-filters.ts","../../svg/src/svg-clip.ts","../src/commands/export-lottie.ts","../../lottie/src/map-colors.ts","../../lottie/src/map-shapes.ts","../../lottie/src/map-easing.ts","../../lottie/src/map-keyframes.ts","../../lottie/src/map-layers.ts","../../lottie/src/warnings.ts","../../lottie/src/export-lottie.ts","../src/commands/export-image.ts","../src/commands/assets.ts","../src/commands/variables.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { Command } from \"commander\";\nimport { parseAtelier } from \"@a-company/atelier-schema\";\nimport { validateAllDeltas } from \"@a-company/atelier-core\";\n\n/**\n * Validate an .atelier file: parse YAML, check schema, check delta overlaps.\n * Returns { valid, errors } for programmatic use.\n */\nexport function validateFile(filePath: string): {\n valid: boolean;\n errors: string[];\n} {\n const absPath = resolve(filePath);\n let content: string;\n try {\n content = readFileSync(absPath, \"utf-8\");\n } catch {\n return { valid: false, errors: [`Cannot read file: ${absPath}`] };\n }\n\n const result = parseAtelier(content);\n if (!result.success) {\n return {\n valid: false,\n errors: result.errors.map(\n (e) => `${e.path}: ${e.message}`,\n ),\n };\n }\n\n // Check all states for delta overlaps\n const overlapErrors: string[] = [];\n for (const [stateName, state] of Object.entries(result.data.states)) {\n const overlaps = validateAllDeltas(state.deltas);\n for (const overlap of overlaps) {\n overlapErrors.push(`State \"${stateName}\": ${overlap.message}`);\n }\n }\n\n if (overlapErrors.length > 0) {\n return { valid: false, errors: overlapErrors };\n }\n\n return { valid: true, errors: [] };\n}\n\n/**\n * Register the `validate` subcommand on the Commander program.\n */\nexport function validateCommand(program: Command): void {\n program\n .command(\"validate <file>\")\n .description(\"Validate an .atelier YAML file\")\n .action((file: string) => {\n const { valid, errors } = validateFile(file);\n if (valid) {\n console.log(\"Valid\");\n } else {\n console.error(\"Validation errors:\");\n for (const error of errors) {\n console.error(` - ${error}`);\n }\n process.exit(1);\n }\n });\n}\n","import { z } from \"zod\";\n\n/** Pixel value — any number */\nexport const PixelSchema = z.number();\n\n/** Percentage string like \"50%\" */\nexport const PercentageSchema = z.string().regex(/^-?\\d+(\\.\\d+)?%$/, {\n message: \"Percentage must be a number followed by %, e.g. \\\"50%\\\"\",\n});\n\n/** Either pixel or percentage */\nexport const UnitValueSchema = z.union([PixelSchema, PercentageSchema]);\n","import { z } from \"zod\";\nimport { UnitValueSchema } from \"./units.js\";\n\nexport const FrameSchema = z.object({\n x: UnitValueSchema,\n y: UnitValueSchema,\n});\n\nexport const BoundsSchema = z.object({\n width: UnitValueSchema,\n height: UnitValueSchema,\n});\n\nexport const AnchorPointSchema = z.object({\n x: z.number().min(0).max(1),\n y: z.number().min(0).max(1),\n});\n","import { z } from \"zod\";\n\nexport const RGBAColorSchema = z.object({\n r: z.number().min(0).max(255),\n g: z.number().min(0).max(255),\n b: z.number().min(0).max(255),\n a: z.number().min(0).max(1),\n});\n\nexport const HSLAColorSchema = z.object({\n h: z.number().min(0).max(360),\n s: z.number().min(0).max(100),\n l: z.number().min(0).max(100),\n a: z.number().min(0).max(1),\n});\n\nexport const HexColorSchema = z.string().regex(/^#([0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/, {\n message: \"Color must be a hex string: #RGB, #RGBA, #RRGGBB, or #RRGGBBAA\",\n});\n\nexport const ColorSchema = z.union([RGBAColorSchema, HSLAColorSchema, HexColorSchema]);\n","import { z } from \"zod\";\nimport { ColorSchema } from \"./color.js\";\nimport { UnitValueSchema } from \"./units.js\";\n\nexport const PathPointSchema = z.object({\n x: z.number(),\n y: z.number(),\n in: z.object({ x: z.number(), y: z.number() }).optional(),\n out: z.object({ x: z.number(), y: z.number() }).optional(),\n});\n\nexport const RectShapeSchema = z.object({\n type: z.literal(\"rect\"),\n cornerRadius: z.union([\n z.number().min(0),\n z.tuple([z.number().min(0), z.number().min(0), z.number().min(0), z.number().min(0)]),\n ]).optional(),\n});\n\nexport const EllipseShapeSchema = z.object({\n type: z.literal(\"ellipse\"),\n});\n\nexport const PathShapeSchema = z.object({\n type: z.literal(\"path\"),\n points: z.array(PathPointSchema).min(2, \"Path must have at least 2 points\"),\n closed: z.boolean().optional(),\n});\n\nexport const ShapeSchema = z.discriminatedUnion(\"type\", [\n RectShapeSchema,\n EllipseShapeSchema,\n PathShapeSchema,\n]);\n\nexport const GradientStopSchema = z.object({\n offset: z.number().min(0).max(1),\n color: ColorSchema,\n});\n\nexport const SolidFillSchema = z.object({\n type: z.literal(\"solid\"),\n color: ColorSchema,\n});\n\nexport const LinearGradientFillSchema = z.object({\n type: z.literal(\"linear-gradient\"),\n angle: z.number(),\n stops: z.array(GradientStopSchema).min(2, \"Gradient needs at least 2 stops\"),\n});\n\nexport const RadialGradientFillSchema = z.object({\n type: z.literal(\"radial-gradient\"),\n center: z.object({ x: UnitValueSchema, y: UnitValueSchema }),\n radius: UnitValueSchema,\n stops: z.array(GradientStopSchema).min(2, \"Gradient needs at least 2 stops\"),\n});\n\nexport const FillSchema = z.discriminatedUnion(\"type\", [\n SolidFillSchema,\n LinearGradientFillSchema,\n RadialGradientFillSchema,\n]);\n\nexport const StrokeSchema = z.object({\n color: ColorSchema,\n width: z.number().min(0),\n dash: z.array(z.number().min(0)).optional(),\n lineCap: z.enum([\"butt\", \"round\", \"square\"]).optional(),\n lineJoin: z.enum([\"miter\", \"round\", \"bevel\"]).optional(),\n strokeStart: z.number().min(0).max(1).optional(),\n strokeEnd: z.number().min(0).max(1).optional(),\n});\n\nexport const TextStyleSchema = z.object({\n fontFamily: z.string().min(1, \"fontFamily is required\"),\n fontSize: z.number().positive(\"fontSize must be positive\"),\n fontWeight: z.union([z.number(), z.enum([\"normal\", \"bold\"])]).optional(),\n fontStyle: z.enum([\"normal\", \"italic\"]).optional(),\n textAlign: z.enum([\"left\", \"center\", \"right\"]).optional(),\n lineHeight: z.number().positive().optional(),\n letterSpacing: z.number().optional(),\n color: ColorSchema,\n});\n","import { z } from \"zod\";\n\nexport const LinearEasingSchema = z.object({ type: z.literal(\"linear\") });\n\nexport const CubicBezierEasingSchema = z.object({\n type: z.literal(\"cubic-bezier\"),\n x1: z.number().min(0).max(1),\n y1: z.number(),\n x2: z.number().min(0).max(1),\n y2: z.number(),\n});\n\nexport const SpringEasingSchema = z.object({\n type: z.literal(\"spring\"),\n mass: z.number().positive().optional(),\n stiffness: z.number().positive().optional(),\n damping: z.number().positive().optional(),\n velocity: z.number().optional(),\n});\n\nexport const StepEasingSchema = z.object({\n type: z.literal(\"step\"),\n steps: z.number().int().positive(),\n position: z.enum([\"start\", \"end\"]).optional(),\n});\n\nexport const EasingPresetSchema = z.enum([\"linear\", \"ease-in\", \"ease-out\", \"ease-in-out\"]);\n\nexport const EasingSchema = z.union([\n LinearEasingSchema,\n CubicBezierEasingSchema,\n SpringEasingSchema,\n StepEasingSchema,\n EasingPresetSchema,\n]);\n","import { z } from \"zod\";\nimport { ColorSchema } from \"./color.js\";\n\nexport const ShadowSchema = z.object({\n color: ColorSchema,\n blur: z.number().min(0),\n offsetX: z.number().optional(),\n offsetY: z.number().optional(),\n});\n","import { z } from \"zod\";\nimport { ShapeSchema, FillSchema, StrokeSchema, TextStyleSchema, PathPointSchema } from \"./shape.js\";\nimport { FrameSchema, BoundsSchema, AnchorPointSchema } from \"./coordinates.js\";\nimport { ShadowSchema } from \"./shadow.js\";\nimport { InteractionSchema } from \"./interaction.js\";\n\nexport const BlendModeSchema = z.enum([\n \"normal\", \"multiply\", \"screen\", \"overlay\",\n \"darken\", \"lighten\", \"color-dodge\", \"color-burn\",\n \"hard-light\", \"soft-light\", \"difference\", \"exclusion\",\n \"hue\", \"saturation\", \"color\", \"luminosity\",\n]);\n\nexport const MotionPathSchema = z.object({\n points: z.array(PathPointSchema).min(2, \"Motion path must have at least 2 points\"),\n closed: z.boolean().optional(),\n autoRotate: z.boolean().optional(),\n autoRotateOffset: z.number().optional(),\n});\n\nexport const ShapeVisualSchema = z.object({\n type: z.literal(\"shape\"),\n shape: ShapeSchema,\n fill: FillSchema.optional(),\n stroke: StrokeSchema.optional(),\n});\n\nexport const TextVisualSchema = z.object({\n type: z.literal(\"text\"),\n content: z.string(),\n style: TextStyleSchema,\n});\n\nexport const SpritesheetConfigSchema = z.object({\n columns: z.number().int().positive(),\n rows: z.number().int().positive(),\n frameCount: z.number().int().positive().optional(),\n frameWidth: z.number().positive(),\n frameHeight: z.number().positive(),\n});\n\nexport const SourceRectSchema = z.object({\n x: z.number(),\n y: z.number(),\n width: z.number().positive(),\n height: z.number().positive(),\n});\n\nexport const ImageVisualSchema = z.object({\n type: z.literal(\"image\"),\n assetId: z.string().min(1, \"assetId is required\"),\n src: z.string().optional(),\n sourceRect: SourceRectSchema.optional(),\n spritesheet: SpritesheetConfigSchema.optional(),\n frameIndex: z.number().int().min(0).optional(),\n});\n\nexport const VideoVisualSchema = z.object({\n type: z.literal(\"video\"),\n assetId: z.string().min(1, \"assetId is required\"),\n src: z.string().optional(),\n startFrame: z.number().int().min(0).optional(),\n sourceOffset: z.number().min(0).optional(),\n sourceEnd: z.number().positive().optional(),\n playbackRate: z.number().positive().optional(),\n volume: z.number().min(0).max(1).optional(),\n muted: z.boolean().optional(),\n objectFit: z.enum([\"contain\", \"cover\", \"fill\"]).optional(),\n});\n\nexport const GroupVisualSchema = z.object({\n type: z.literal(\"group\"),\n});\n\nexport const RefVisualSchema = z.object({\n type: z.literal(\"ref\"),\n src: z.string().min(1, \"src is required\"),\n state: z.string().optional(),\n frame: z.number().int().min(0).optional(),\n});\n\nexport const VisualSchema = z.discriminatedUnion(\"type\", [\n ShapeVisualSchema,\n TextVisualSchema,\n ImageVisualSchema,\n VideoVisualSchema,\n GroupVisualSchema,\n RefVisualSchema,\n]);\n\nexport const LayerSchema = z.object({\n id: z.string().min(1, \"Layer id is required\"),\n description: z.string().optional(),\n tags: z.array(z.string()).optional(),\n visual: VisualSchema,\n frame: FrameSchema,\n bounds: BoundsSchema,\n anchorPoint: AnchorPointSchema.optional(),\n parentId: z.string().optional(),\n opacity: z.number().min(0).max(1).optional(),\n rotation: z.number().optional(),\n scale: z.object({ x: z.number(), y: z.number() }).optional(),\n visible: z.boolean().optional(),\n shadow: ShadowSchema.optional(),\n blendMode: BlendModeSchema.optional(),\n motionPath: MotionPathSchema.optional(),\n clipPath: ShapeSchema.optional(),\n tint: z.object({\n color: z.string(),\n amount: z.number().min(0).max(1),\n }).optional(),\n interactions: z.array(InteractionSchema).optional(),\n});\n","import { z } from \"zod\";\n\nexport const TriggerTypeSchema = z.enum([\n \"click\", \"hover\", \"pointerdown\", \"pointerup\", \"timer\", \"signal\",\n]);\n\nexport const TriggerSchema = z.object({\n type: TriggerTypeSchema,\n delay: z.number().nonnegative(\"Timer delay must be non-negative\").optional(),\n signal: z.string().optional(),\n}).refine(\n (t) => t.type !== \"timer\" || t.delay !== undefined,\n { message: \"Timer trigger requires a delay\" },\n).refine(\n (t) => t.type !== \"signal\" || t.signal !== undefined,\n { message: \"Signal trigger requires a signal name\" },\n);\n\nexport const ActionTypeSchema = z.enum([\n \"go-to-state\", \"emit-signal\", \"set-variable\", \"toggle-visibility\",\n]);\n\nexport const ActionSchema = z.object({\n type: ActionTypeSchema,\n state: z.string().optional(),\n signal: z.string().optional(),\n variable: z.string().optional(),\n value: z.unknown().optional(),\n targetLayer: z.string().optional(),\n}).refine(\n (a) => a.type !== \"go-to-state\" || a.state !== undefined,\n { message: \"go-to-state action requires a state name\" },\n).refine(\n (a) => a.type !== \"emit-signal\" || a.signal !== undefined,\n { message: \"emit-signal action requires a signal name\" },\n).refine(\n (a) => a.type !== \"set-variable\" || (a.variable !== undefined && a.value !== undefined),\n { message: \"set-variable action requires variable and value\" },\n);\n\nexport const InteractionSchema = z.object({\n id: z.string().min(1, \"Interaction id is required\"),\n trigger: TriggerSchema,\n action: ActionSchema,\n description: z.string().optional(),\n});\n","import { z } from \"zod\";\nimport { EasingSchema } from \"./easing.js\";\n\nexport const AnimatablePropertySchema = z.enum([\n \"frame.x\",\n \"frame.y\",\n \"bounds.width\",\n \"bounds.height\",\n \"opacity\",\n \"rotation\",\n \"scale.x\",\n \"scale.y\",\n \"anchorPoint.x\",\n \"anchorPoint.y\",\n \"visual.shape.cornerRadius\",\n \"visual.fill.color\",\n \"visual.stroke.color\",\n \"visual.stroke.width\",\n \"visual.stroke.start\",\n \"visual.stroke.end\",\n \"visual.style.fontSize\",\n \"visual.style.color\",\n \"shadow.color\",\n \"shadow.blur\",\n \"shadow.offsetX\",\n \"shadow.offsetY\",\n \"motionPath.progress\",\n \"visual.fill.angle\",\n \"visual.fill.center.x\",\n \"visual.fill.center.y\",\n \"visual.fill.radius\",\n \"visual.image.sourceRect.x\",\n \"visual.image.sourceRect.y\",\n \"visual.image.sourceRect.width\",\n \"visual.image.sourceRect.height\",\n \"visual.image.frameIndex\",\n \"visible\",\n \"tint.color\",\n \"tint.amount\",\n]);\n\nexport const FrameRangeSchema = z.tuple([\n z.number().int().min(0, \"Frame start must be >= 0\"),\n z.number().int().min(0, \"Frame end must be >= 0\"),\n]).refine(([start, end]) => end >= start, {\n message: \"Frame range end must be >= start\",\n});\n\nexport const DeltaSchema = z.object({\n id: z.string().optional(),\n name: z.string().optional(),\n layer: z.string().min(1, \"Delta must reference a layer id\"),\n property: AnimatablePropertySchema,\n range: FrameRangeSchema,\n from: z.unknown(),\n to: z.unknown(),\n easing: EasingSchema.optional(),\n description: z.string().optional(),\n tags: z.array(z.string()).optional(),\n});\n","import { z } from \"zod\";\nimport { DeltaSchema } from \"./delta.js\";\nimport { EasingSchema } from \"./easing.js\";\n\nexport const AudioSchema = z.object({\n src: z.string().min(1, \"Audio src is required\"),\n offset: z.number().min(0, \"Audio offset must be non-negative\").optional(),\n volume: z.number().min(0).max(1, \"Audio volume must be 0–1\").optional(),\n loop: z.boolean().optional(),\n startFrame: z.number().int().min(0, \"Audio startFrame must be a non-negative integer\").optional(),\n});\n\nexport const StateTransitionConfigSchema = z.object({\n duration: z.number().int().positive(\"Transition duration must be a positive integer (frames)\"),\n easing: EasingSchema.optional(),\n});\n\nexport const StateSchema = z.object({\n description: z.string().optional(),\n tags: z.array(z.string()).optional(),\n parent: z.string().optional(),\n duration: z.number().int().positive(\"State duration must be a positive integer (frames)\"),\n deltas: z.array(DeltaSchema),\n audio: AudioSchema.optional(),\n transitions: z.record(z.string(), StateTransitionConfigSchema).optional(),\n});\n","import { z } from \"zod\";\nimport { AnimatablePropertySchema } from \"./delta.js\";\nimport { EasingSchema } from \"./easing.js\";\n\nexport const PresetDeltaSchema = z.object({\n property: AnimatablePropertySchema,\n offset: z.tuple([z.number().int().min(0), z.number().int().min(0)]).optional(),\n from: z.unknown(),\n to: z.unknown(),\n easing: EasingSchema.optional(),\n});\n\nexport const PresetSchema = z.object({\n description: z.string().optional(),\n tags: z.array(z.string()).optional(),\n deltas: z.array(PresetDeltaSchema).min(1, \"Preset must have at least one delta\"),\n});\n","import { z } from \"zod\";\n\nexport const VariableTypeSchema = z.enum([\"string\", \"number\", \"color\", \"asset\", \"boolean\"]);\n\nexport const VariableSchema = z.object({\n type: VariableTypeSchema,\n default: z.unknown().optional(),\n description: z.string().optional(),\n});\n","import { z } from \"zod\";\n\nexport const AssetTypeSchema = z.enum([\"image\", \"svg\", \"font\", \"animation\", \"audio\", \"video\"]);\n\nexport const AssetSchema = z.object({\n type: AssetTypeSchema,\n src: z.string().min(1, \"Asset src is required\"),\n description: z.string().optional(),\n spritesheet: z.object({\n columns: z.number().int().positive(),\n rows: z.number().int().positive(),\n frameCount: z.number().int().positive().optional(),\n frameWidth: z.number().positive(),\n frameHeight: z.number().positive(),\n }).optional(),\n videoMeta: z.object({\n duration: z.number().positive(\"videoMeta.duration must be positive\"),\n fps: z.number().positive(\"videoMeta.fps must be positive\"),\n width: z.number().int().positive(),\n height: z.number().int().positive(),\n }).optional(),\n});\n","import { z } from \"zod\";\nimport { LayerSchema } from \"./layer.js\";\nimport { StateSchema } from \"./state.js\";\nimport { PresetSchema } from \"./preset.js\";\nimport { VariableSchema } from \"./variable.js\";\nimport { AssetSchema } from \"./asset.js\";\n\nexport const CanvasSchema = z.object({\n width: z.number().int().positive(\"Canvas width must be a positive integer\"),\n height: z.number().int().positive(\"Canvas height must be a positive integer\"),\n fps: z.number().int().positive(\"FPS must be a positive integer\"),\n background: z.string().optional(),\n});\n\nexport const AtelierDocumentSchema = z.object({\n version: z.string().min(1, \"Version is required\"),\n name: z.string().min(1, \"Animation name is required\"),\n description: z.string().optional(),\n tags: z.array(z.string()).optional(),\n canvas: CanvasSchema,\n variables: z.record(z.string(), VariableSchema).optional(),\n assets: z.record(z.string(), AssetSchema).optional(),\n presets: z.record(z.string(), PresetSchema).optional(),\n layers: z.array(LayerSchema),\n states: z.record(z.string(), StateSchema),\n});\n","import { z } from \"zod\";\n\n/** Silence-trim policy block */\nexport const SilencePolicySchema = z.object({\n noise: z.string().optional(),\n min_silence: z.number().nonnegative().optional(),\n default_padding_pre: z.number().nonnegative().optional(),\n default_padding_post: z.number().nonnegative().optional(),\n match_tolerance: z.number().nonnegative().optional(),\n}).strict();\n\n/** Caption visual style block */\nexport const CaptionStyleSchema = z.object({\n font_family: z.string().optional(),\n font_size: z.number().positive().optional(),\n font_weight: z.union([z.literal(\"normal\"), z.literal(\"bold\"), z.number()]).optional(),\n text_align: z.enum([\"left\", \"center\", \"right\"]).optional(),\n color: z.string().optional(),\n y_ratio: z.number().min(0).max(1).optional(),\n width_ratio: z.number().min(0).max(1).optional(),\n fade_seconds: z.number().nonnegative().optional(),\n}).strict();\n\n/** Caption phrase grouping block */\nexport const CaptionGroupingSchema = z.object({\n max_words: z.number().int().positive().optional(),\n pause_gap: z.number().nonnegative().optional(),\n}).strict();\n\n/** Anchor enum shared by every overlay sub-rule */\nexport const OverlayAnchorSchema = z.enum([\n \"top-left\",\n \"top-right\",\n \"bottom-left\",\n \"bottom-right\",\n]);\n\n/** Visual subset for overlay text — recipe snake_case convention */\nexport const OverlayTextStyleSchema = z.object({\n font_family: z.string().optional(),\n font_size: z.number().positive().optional(),\n font_weight: z.union([z.literal(\"normal\"), z.literal(\"bold\"), z.number()]).optional(),\n color: z.string().optional(),\n}).strict();\n\n/**\n * Validate a page-number format template:\n * - braces must balance\n * - every {…} group must match (current|total)(:0Nd)? (zero-pad form)\n * - at least one of {current} / {total} must appear\n *\n * Render-time substitution is a separate concern; this only validates syntax.\n */\nfunction validatePageNumberFormat(\n format: string,\n ctx: z.RefinementCtx,\n): void {\n if (format.length === 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"format must be a non-empty string\",\n });\n return;\n }\n\n const open = (format.match(/\\{/g) ?? []).length;\n const close = (format.match(/\\}/g) ?? []).length;\n if (open !== close) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `format has unbalanced braces (${open} '{' vs ${close} '}')`,\n });\n return;\n }\n\n const groupRe = /\\{([^{}]*)\\}/g;\n const groupRule = /^(current|total)(:0\\d+d)?$/;\n let m: RegExpExecArray | null;\n let sawCurrent = false;\n let sawTotal = false;\n while ((m = groupRe.exec(format)) !== null) {\n const inner = m[1];\n if (!groupRule.test(inner)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `format placeholder \"{${inner}}\" is not recognized — expected {current}, {total}, {current:0Nd}, or {total:0Nd}`,\n });\n return;\n }\n if (inner.startsWith(\"current\")) sawCurrent = true;\n if (inner.startsWith(\"total\")) sawTotal = true;\n }\n\n if (!sawCurrent && !sawTotal) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"format must contain at least one {current} or {total} placeholder\",\n });\n }\n}\n\n/** Handle overlay rule schema — anchored creator-handle text */\nexport const OverlayHandleRuleSchema = z.object({\n text: z.string().min(1),\n anchor: OverlayAnchorSchema,\n margin: z.number().nonnegative().optional(),\n style: OverlayTextStyleSchema.optional(),\n}).strict();\n\n/** Page-number overlay rule schema — anchored \"1/5\"-style indicator */\nexport const OverlayPageNumberRuleSchema = z.object({\n format: z.string().superRefine(validatePageNumberFormat),\n anchor: OverlayAnchorSchema,\n margin: z.number().nonnegative().optional(),\n style: OverlayTextStyleSchema.optional(),\n}).strict();\n\n/** Overlay rules block (Phase 1.5) — both sub-blocks optional */\nexport const OverlayRulesSchema = z.object({\n handle: OverlayHandleRuleSchema.optional(),\n page_number: OverlayPageNumberRuleSchema.optional(),\n}).strict();\n\n/**\n * StudioRecipe — top-level. Reserved fields (caption_highlight, transition_kit,\n * etc.) still accept any shape; Phase 3 will refine them. Validate-time warnings\n * surface reserved-fields-in-use to authors so they aren't caught off-guard\n * when those sections become load-bearing.\n *\n * overlay_rules was promoted from reserved Phase 3 to first-class Phase 1.5.\n */\nexport const StudioRecipeSchema = z.object({\n version: z.string(),\n name: z.string(),\n description: z.string().optional(),\n author: z.string().optional(),\n tags: z.array(z.string()).optional(),\n\n silence_policy: SilencePolicySchema.optional(),\n caption_style: CaptionStyleSchema.optional(),\n caption_grouping: CaptionGroupingSchema.optional(),\n\n // Phase 1.5 — first-class overlay rules\n overlay_rules: OverlayRulesSchema.optional(),\n\n // Reserved — Phase 3 (parse-opaque)\n caption_highlight: z.unknown().optional(),\n transition_kit: z.unknown().optional(),\n palette: z.unknown().optional(),\n audio_policy: z.unknown().optional(),\n aspect_targets: z.array(z.unknown()).optional(),\n}).strict();\n\n/** Names of still-reserved fields — used by validators to emit forward-compat warnings */\nexport const RESERVED_RECIPE_FIELDS = [\n \"caption_highlight\",\n \"transition_kit\",\n \"palette\",\n \"audio_policy\",\n \"aspect_targets\",\n] as const;\n","import type { AtelierDocument, Layer, Delta, VideoVisual, StudioRecipe } from \"@a-company/atelier-types\";\nimport { AtelierDocumentSchema } from \"./document.js\";\nimport { LayerSchema } from \"./layer.js\";\nimport { DeltaSchema } from \"./delta.js\";\nimport { StudioRecipeSchema, RESERVED_RECIPE_FIELDS } from \"./recipe.js\";\nimport type { z } from \"zod\";\n\n/** Validation result — either success with typed data or failure with readable errors */\nexport type ValidationResult<T> =\n | { success: true; data: T }\n | { success: false; errors: ValidationError[] };\n\nexport interface ValidationError {\n path: string;\n message: string;\n}\n\n/** Format Zod errors into flat, AI-readable error messages */\nfunction formatErrors(error: z.ZodError): ValidationError[] {\n return error.issues.map((issue) => ({\n path: issue.path.join(\".\") || \"(root)\",\n message: issue.message,\n }));\n}\n\n/** Validate a complete AtelierDocument */\nexport function validateDocument(input: unknown): ValidationResult<AtelierDocument> {\n const result = AtelierDocumentSchema.safeParse(input);\n if (result.success) {\n return { success: true, data: result.data as AtelierDocument };\n }\n return { success: false, errors: formatErrors(result.error) };\n}\n\n/** Validate a single Layer */\nexport function validateLayer(input: unknown): ValidationResult<Layer> {\n const result = LayerSchema.safeParse(input);\n if (result.success) {\n return { success: true, data: result.data as Layer };\n }\n return { success: false, errors: formatErrors(result.error) };\n}\n\n/** Validate a single Delta */\nexport function validateDelta(input: unknown): ValidationResult<Delta> {\n const result = DeltaSchema.safeParse(input);\n if (result.success) {\n return { success: true, data: result.data as Delta };\n }\n return { success: false, errors: formatErrors(result.error) };\n}\n\n/**\n * Validate a VideoVisual layer against semantic constraints (^valid-video-layer gate).\n * Checks beyond Zod: sourceEnd > sourceOffset, sourceEnd ≤ videoMeta.duration.\n */\nexport function validateVideoLayer(\n visual: VideoVisual,\n videoMetaDuration?: number,\n): ValidationResult<VideoVisual> {\n const errors: ValidationError[] = [];\n\n if (!visual.assetId) {\n errors.push({ path: \"assetId\", message: \"assetId is required\" });\n }\n\n const sourceOffset = visual.sourceOffset ?? 0;\n if (visual.sourceEnd !== undefined) {\n if (visual.sourceEnd <= sourceOffset) {\n errors.push({\n path: \"sourceEnd\",\n message: `sourceEnd (${visual.sourceEnd}) must be greater than sourceOffset (${sourceOffset})`,\n });\n }\n if (videoMetaDuration !== undefined && visual.sourceEnd > videoMetaDuration) {\n errors.push({\n path: \"sourceEnd\",\n message: `sourceEnd (${visual.sourceEnd}) exceeds asset duration (${videoMetaDuration})`,\n });\n }\n }\n\n if (videoMetaDuration !== undefined && sourceOffset >= videoMetaDuration) {\n errors.push({\n path: \"sourceOffset\",\n message: `sourceOffset (${sourceOffset}) is at or beyond asset duration (${videoMetaDuration})`,\n });\n }\n\n if (errors.length > 0) return { success: false, errors };\n return { success: true, data: visual };\n}\n\n/**\n * Validate a StudioRecipe against the schema (^valid-recipe gate).\n * Returns success with the parsed recipe and optional warnings about\n * reserved-but-unimplemented Phase 3 fields that are present.\n */\nexport function validateRecipe(\n recipe: unknown,\n): ValidationResult<StudioRecipe> & { warnings?: string[] } {\n const parsed = StudioRecipeSchema.safeParse(recipe);\n if (!parsed.success) {\n return { success: false, errors: formatErrors(parsed.error) };\n }\n\n const warnings: string[] = [];\n const data = parsed.data as StudioRecipe;\n for (const field of RESERVED_RECIPE_FIELDS) {\n if (data[field] !== undefined) {\n warnings.push(\n `${field} is reserved for Phase 3 and currently has no effect.`,\n );\n }\n }\n\n return { success: true, data, ...(warnings.length > 0 && { warnings }) };\n}\n","import { parse as yamlParse, stringify as yamlStringify } from \"yaml\";\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport { validateDocument } from \"./validate.js\";\nimport type { ValidationResult } from \"./validate.js\";\n\n/**\n * Parse a YAML string into a validated AtelierDocument.\n * Returns validation errors if the YAML is invalid or doesn't match the schema.\n */\nexport function parseAtelier(yamlString: string): ValidationResult<AtelierDocument> {\n let parsed: unknown;\n try {\n parsed = yamlParse(yamlString);\n } catch (err) {\n return {\n success: false,\n errors: [{ path: \"(yaml)\", message: `YAML parse error: ${(err as Error).message}` }],\n };\n }\n return validateDocument(parsed);\n}\n\n/**\n * Serialize an AtelierDocument to YAML string.\n */\nexport function serializeAtelier(doc: AtelierDocument): string {\n return yamlStringify(doc, { indent: 2 });\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync, copyFileSync } from \"node:fs\";\nimport { join, basename, extname, resolve } from \"node:path\";\nimport type { AtelierDocument, Layer } from \"@a-company/atelier-types\";\nimport type {\n CutEntry,\n VideoCutList,\n VideoTranscript,\n VideoProjectManifest,\n} from \"@a-company/atelier-types\";\n\nexport const VIDEO_PROJECT_VERSION = \"1.0\";\nexport const VIDEO_CUTLIST_VERSION = \"1.1\";\nexport const VIDEO_TRANSCRIPT_VERSION = \"1.1\";\n\n/**\n * Compute the effective in/out span for a cut, clamped to source bounds.\n * `start = max(0, rawStart - paddingPre)`, `end = min(duration, rawEnd + paddingPost)`.\n */\nexport function effectiveSpan(\n cut: CutEntry,\n duration: number,\n): { start: number; end: number } {\n return {\n start: Math.max(0, cut.rawStart - cut.paddingPre),\n end: Math.min(duration, cut.rawEnd + cut.paddingPost),\n };\n}\n\n/** Resolved absolute paths for all files in a VideoProject folder */\nexport interface VideoProject {\n /** Absolute path to the project folder */\n dir: string;\n /** Absolute path to source video file */\n sourcePath: string;\n /** Absolute path to project.atelier composition */\n compositionPath: string;\n /** Absolute path to transcript.json */\n transcriptPath: string;\n /** Absolute path to cuts.json */\n cutsPath: string;\n /** Absolute path to export/ directory */\n exportDir: string;\n /** Manifest metadata */\n manifest: VideoProjectManifest;\n}\n\n/**\n * Scaffold a new VideoProject folder from a source video file.\n *\n * Creates the folder at `destDir` (defaults to same directory as source,\n * named after the video file without extension). Copies the source video\n * into the folder as \"source<ext>\". Writes an empty draft project.atelier,\n * an empty cuts.json, and creates the export/ directory.\n *\n * Does NOT run metadata extraction — the caller (`atelier edit`, T-005)\n * probes duration/fps via ffprobe and fills in videoMeta before saving.\n */\nexport async function createVideoProject(\n srcPath: string,\n destDir?: string,\n): Promise<VideoProject> {\n const absSrc = resolve(srcPath);\n const ext = extname(absSrc);\n const stem = basename(absSrc, ext);\n\n const projectDir = destDir ? resolve(destDir) : join(resolve(absSrc, \"..\"), stem);\n\n if (!existsSync(projectDir)) {\n mkdirSync(projectDir, { recursive: true });\n }\n\n const sourceFilename = `source${ext}`;\n const sourcePath = join(projectDir, sourceFilename);\n\n // Copy source only if not already in place (idempotent re-init)\n if (!existsSync(sourcePath)) {\n copyFileSync(absSrc, sourcePath);\n }\n\n const compositionPath = join(projectDir, \"project.atelier\");\n const transcriptPath = join(projectDir, \"transcript.json\");\n const cutsPath = join(projectDir, \"cuts.json\");\n const exportDir = join(projectDir, \"export\");\n\n if (!existsSync(exportDir)) {\n mkdirSync(exportDir, { recursive: true });\n }\n\n const manifest: VideoProjectManifest = {\n source: sourceFilename,\n composition: \"project.atelier\",\n transcript: \"transcript.json\",\n cuts: \"cuts.json\",\n exportDir: \"export/\",\n createdAt: new Date().toISOString(),\n version: VIDEO_PROJECT_VERSION,\n };\n\n // Draft composition — caller fills in canvas dimensions and videoMeta after probing\n const draft: AtelierDocument = {\n version: \"1.0\",\n name: stem,\n canvas: { width: 1920, height: 1080, fps: 30 },\n assets: {\n src: {\n type: \"video\",\n src: sourceFilename,\n description: `Source: ${basename(absSrc)}`,\n },\n },\n layers: [\n {\n id: \"clip-0\",\n visual: {\n type: \"video\",\n assetId: \"src\",\n src: sourceFilename,\n startFrame: 0,\n sourceOffset: 0,\n playbackRate: 1.0,\n objectFit: \"contain\",\n },\n frame: { x: 0, y: 0 },\n bounds: { width: 1920, height: 1080 },\n },\n ],\n states: {\n default: {\n duration: 0,\n deltas: [],\n },\n },\n };\n\n if (!existsSync(compositionPath)) {\n writeFileSync(compositionPath, JSON.stringify(draft, null, 2), \"utf-8\");\n }\n\n const initialCuts: VideoCutList = {\n version: VIDEO_CUTLIST_VERSION,\n source: sourceFilename,\n cuts: [],\n };\n\n if (!existsSync(cutsPath)) {\n writeFileSync(cutsPath, JSON.stringify(initialCuts, null, 2), \"utf-8\");\n }\n\n return {\n dir: projectDir,\n sourcePath,\n compositionPath,\n transcriptPath,\n cutsPath,\n exportDir,\n manifest,\n };\n}\n\n/**\n * Load an existing VideoProject from a folder path.\n * Does not validate that the composition or cut list are well-formed —\n * callers that need that should use lintFile() after loading.\n */\nexport function loadVideoProject(dir: string): VideoProject {\n const projectDir = resolve(dir);\n\n // Detect source file (source.mp4, source.mov, etc.)\n const possibleExts = [\".mp4\", \".mov\", \".webm\", \".mkv\", \".avi\"];\n let sourceFilename = \"source.mp4\";\n for (const ext of possibleExts) {\n if (existsSync(join(projectDir, `source${ext}`))) {\n sourceFilename = `source${ext}`;\n break;\n }\n }\n\n const manifest: VideoProjectManifest = {\n source: sourceFilename,\n composition: \"project.atelier\",\n transcript: \"transcript.json\",\n cuts: \"cuts.json\",\n exportDir: \"export/\",\n createdAt: new Date().toISOString(),\n version: VIDEO_PROJECT_VERSION,\n };\n\n return {\n dir: projectDir,\n sourcePath: join(projectDir, sourceFilename),\n compositionPath: join(projectDir, \"project.atelier\"),\n transcriptPath: join(projectDir, \"transcript.json\"),\n cutsPath: join(projectDir, \"cuts.json\"),\n exportDir: join(projectDir, \"export\"),\n manifest,\n };\n}\n\n/**\n * Read and parse cuts.json from a VideoProject.\n *\n * Migrates legacy 1.0 cuts (flat { start, end }) to 1.1 parametric form\n * (rawStart/rawEnd + zero padding) on the fly. Writers always emit 1.1.\n */\nexport function readCutList(project: VideoProject): VideoCutList {\n if (!existsSync(project.cutsPath)) {\n return { version: VIDEO_CUTLIST_VERSION, source: project.manifest.source, cuts: [] };\n }\n const raw = JSON.parse(readFileSync(project.cutsPath, \"utf-8\")) as {\n version?: string;\n source: string;\n cuts: Array<CutEntry | { start: number; end: number; label?: string }>;\n };\n\n const cuts: CutEntry[] = raw.cuts.map((entry) => {\n if (\"rawStart\" in entry) return entry;\n // Legacy 1.0 migration — stored start/end become rawStart/rawEnd with zero padding.\n return {\n rawStart: entry.start,\n rawEnd: entry.end,\n paddingPre: 0,\n paddingPost: 0,\n ...(entry.label !== undefined && { label: entry.label }),\n };\n });\n\n return {\n version: VIDEO_CUTLIST_VERSION,\n source: raw.source,\n cuts,\n };\n}\n\n/** Write cuts.json to a VideoProject (always at the current cut list version) */\nexport function writeCutList(project: VideoProject, cuts: VideoCutList): void {\n const payload: VideoCutList = { ...cuts, version: VIDEO_CUTLIST_VERSION };\n writeFileSync(project.cutsPath, JSON.stringify(payload, null, 2), \"utf-8\");\n}\n\n/**\n * Read and parse transcript.json from a VideoProject.\n *\n * Migrates legacy 1.0 transcripts (TranscriptWord had flat `word: string`)\n * to 1.1 (`detected` + `text` + flags) on the fly. Writers always emit 1.1.\n */\nexport function readTranscript(project: VideoProject): VideoTranscript | null {\n if (!existsSync(project.transcriptPath)) return null;\n const raw = JSON.parse(readFileSync(project.transcriptPath, \"utf-8\")) as {\n version?: string;\n language?: string;\n segments: Array<{\n text: string;\n start: number;\n end: number;\n words: Array<\n // 1.1 shape\n | { detected: string; text: string; start: number; end: number; confidence?: number; userEdited?: boolean; userAdded?: boolean; hidden?: boolean }\n // 1.0 legacy shape\n | { word: string; start: number; end: number; confidence?: number }\n >;\n }>;\n };\n\n const segments = raw.segments.map((seg) => ({\n text: seg.text,\n start: seg.start,\n end: seg.end,\n words: seg.words.map((w) => {\n if (\"detected\" in w) return w;\n // 1.0 migration — `word` becomes both detected and text\n return {\n detected: w.word,\n text: w.word,\n start: w.start,\n end: w.end,\n ...(w.confidence !== undefined && { confidence: w.confidence }),\n };\n }),\n }));\n\n return {\n version: VIDEO_TRANSCRIPT_VERSION,\n ...(raw.language !== undefined && { language: raw.language }),\n segments,\n };\n}\n\n/** Write transcript.json to a VideoProject (always at the current transcript version) */\nexport function writeTranscript(project: VideoProject, transcript: VideoTranscript): void {\n const payload: VideoTranscript = { ...transcript, version: VIDEO_TRANSCRIPT_VERSION };\n writeFileSync(project.transcriptPath, JSON.stringify(payload, null, 2), \"utf-8\");\n}\n\n/** Read and parse project.atelier from a VideoProject */\nexport function readComposition(project: VideoProject): AtelierDocument {\n return JSON.parse(readFileSync(project.compositionPath, \"utf-8\")) as AtelierDocument;\n}\n\n/** Write project.atelier to a VideoProject */\nexport function writeComposition(project: VideoProject, doc: AtelierDocument): void {\n writeFileSync(project.compositionPath, JSON.stringify(doc, null, 2), \"utf-8\");\n}\n\n/**\n * Rewrite the silence-trim layers in a composition from a current cut list.\n *\n * Drops every layer tagged \"silence-trim\" then appends one VideoVisual layer\n * per cut, in temporal order, with cumulative startFrame computed from prior\n * clip durations. All other layers (user-authored, captions, overlays) are\n * preserved untouched — this is the tag-namespace isolation invariant.\n */\nexport function rewriteCutLayers(\n doc: AtelierDocument,\n cuts: CutEntry[],\n sourceFilename: string,\n sourceDuration: number,\n assetId = \"src\",\n): AtelierDocument {\n const preserved = doc.layers.filter((l) => !(l.tags ?? []).includes(\"silence-trim\"));\n const fps = doc.canvas.fps;\n\n let cumulativeFrame = 0;\n const trimLayers: Layer[] = cuts.map((cut, idx) => {\n const span = effectiveSpan(cut, sourceDuration);\n const sourceOffsetFrames = Math.floor(span.start * fps) / fps;\n const sourceEndFrames = Math.ceil(span.end * fps) / fps;\n const durationFrames = Math.max(1, Math.round((sourceEndFrames - sourceOffsetFrames) * fps));\n\n const layer: Layer = {\n id: `clip-trim-${idx}`,\n tags: [\"silence-trim\"],\n visual: {\n type: \"video\",\n assetId,\n src: sourceFilename,\n startFrame: cumulativeFrame,\n sourceOffset: sourceOffsetFrames,\n sourceEnd: sourceEndFrames,\n playbackRate: 1.0,\n objectFit: \"contain\",\n },\n frame: { x: 0, y: 0 },\n bounds: { width: doc.canvas.width, height: doc.canvas.height },\n };\n cumulativeFrame += durationFrames;\n return layer;\n });\n\n return { ...doc, layers: [...preserved, ...trimLayers] };\n}\n","import { readFileSync, existsSync } from \"node:fs\";\nimport { join, resolve, isAbsolute } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { validateRecipe } from \"@a-company/atelier-schema\";\nimport type {\n StudioRecipe,\n SilencePolicy,\n CaptionStyle,\n CaptionGrouping,\n AtelierDocument,\n Layer,\n OverlayAnchor,\n OverlayTextStyle,\n OverlayPageNumberRule,\n} from \"@a-company/atelier-types\";\nimport type { TrimOptions } from \"../commands/trim.js\";\nimport type { TranscribeOptions } from \"../commands/transcribe.js\";\nimport type { CaptionStyle as RuntimeCaptionStyle, BuildCaptionsOptions } from \"./caption-builder.js\";\n\nexport const RECIPE_VERSION = \"1.0\";\n\nexport interface LoadedRecipe {\n recipe: StudioRecipe;\n /** Absolute path the recipe was read from */\n path: string;\n /** Warnings from validateRecipe (e.g. reserved-field usage) */\n warnings: string[];\n}\n\n/**\n * Resolve a recipe reference to an absolute path.\n *\n * Resolution order (per studio-recipe.md §6.2):\n * 1. <projectDir>/.atelier/recipes/<name>.recipe.{yaml,json}\n * 2. ~/.atelier/recipes/<name>.recipe.{yaml,json}\n * 3. The literal path passed (absolute or relative to cwd)\n *\n * Absolute paths and paths containing slashes skip resolution and load directly.\n */\nexport function resolveRecipePath(pathOrName: string, projectDir?: string): string {\n // Absolute path or contains a path separator — treat as literal\n if (isAbsolute(pathOrName) || pathOrName.includes(\"/\") || pathOrName.includes(\"\\\\\")) {\n return resolve(pathOrName);\n }\n\n const candidates: string[] = [];\n const exts = [\".recipe.yaml\", \".recipe.json\", \".yaml\", \".yml\", \".json\"];\n\n if (projectDir) {\n const projectRecipesDir = join(resolve(projectDir), \".atelier\", \"recipes\");\n for (const ext of exts) candidates.push(join(projectRecipesDir, `${pathOrName}${ext}`));\n }\n const userRecipesDir = join(homedir(), \".atelier\", \"recipes\");\n for (const ext of exts) candidates.push(join(userRecipesDir, `${pathOrName}${ext}`));\n\n for (const candidate of candidates) {\n if (existsSync(candidate)) return candidate;\n }\n\n throw new Error(\n `Recipe \"${pathOrName}\" not found. Looked in:\\n${candidates.map((c) => ` ${c}`).join(\"\\n\")}`,\n );\n}\n\n/**\n * Load and validate a recipe from a path or name.\n *\n * Sniffs YAML vs JSON by file extension; falls back to YAML parser when\n * unclear (YAML is a superset of JSON for objects).\n */\nexport function loadRecipe(pathOrName: string, projectDir?: string): LoadedRecipe {\n const path = resolveRecipePath(pathOrName, projectDir);\n const raw = readFileSync(path, \"utf-8\");\n\n let parsed: unknown;\n if (path.endsWith(\".json\")) {\n parsed = JSON.parse(raw);\n } else {\n parsed = parseYaml(raw);\n }\n\n const result = validateRecipe(parsed);\n if (!result.success) {\n const msg = result.errors.map((e) => ` ${e.path}: ${e.message}`).join(\"\\n\");\n throw new Error(`Invalid recipe at ${path}:\\n${msg}`);\n }\n\n return {\n recipe: result.data,\n path,\n warnings: result.warnings ?? [],\n };\n}\n\n/**\n * Generate a starter recipe YAML with every Phase 1 field present and\n * inline comments documenting it. Authors learn the shape by editing.\n */\nexport function scaffoldRecipeYaml(name: string): string {\n return `# Studio Recipe — ${name}\n# Phase 1 — manual authoring + apply\n# https://github.com/ascend42/a-atelier/blob/main/.paradigm/specs/studio-recipe.md\n\nversion: \"${RECIPE_VERSION}\"\nname: \"${name}\"\ndescription: \"\"\nauthor: \"\"\ntags: []\n\n# ── Silence-trim policy — consumed by \\`atelier trim\\` ───────────────────\nsilence_policy:\n # silencedetect noise threshold (default: -30dB)\n noise: \"-30dB\"\n # Minimum silence duration to register, in seconds (default: 0.35)\n min_silence: 0.35\n # Default leading padding for new cuts, in seconds (default: 0.08)\n default_padding_pre: 0.08\n # Default trailing padding for new cuts, in seconds (default: 0.12)\n default_padding_post: 0.12\n # Re-detect match tolerance for preserving user padding, in seconds (default: 0.5)\n match_tolerance: 0.5\n\n# ── Caption visual style — consumed by \\`atelier transcribe\\` ────────────\ncaption_style:\n font_family: \"Inter\"\n font_size: 84\n font_weight: \"bold\" # normal | bold | numeric (100..900)\n text_align: \"center\" # left | center | right\n color: \"#FFFFFF\"\n y_ratio: 0.85 # 0=top, 1=bottom\n width_ratio: 0.9\n fade_seconds: 0.05\n\n# ── Caption phrase grouping — consumed by \\`atelier transcribe\\` ─────────\ncaption_grouping:\n max_words: 5\n pause_gap: 0.4\n\n# ── Overlay rules (Phase 1.5) — anchored handle + page-number overlays ─\n# overlay_rules:\n# handle:\n# text: \"@username\"\n# anchor: \"bottom-left\" # top-left | top-right | bottom-left | bottom-right\n# margin: 24 # px from anchored edges\n# style:\n# font_family: \"Inter\"\n# font_size: 36\n# font_weight: \"bold\"\n# color: \"#FFFFFF\"\n# page_number:\n# format: \"{current}/{total}\" # supports {current:02d} / {total:02d} zero-pad\n# anchor: \"top-right\"\n# margin: 24\n# style:\n# font_family: \"Inter\"\n# font_size: 36\n# font_weight: \"normal\"\n# color: \"#FFFFFF\"\n\n# ── Phase 3 fields (reserved — Phase 1 ignores these) ──────────────────\n# caption_highlight: {}\n# transition_kit: {}\n# palette: {}\n# audio_policy: {}\n# aspect_targets: []\n`;\n}\n\n// ─── Recipe → CLI options translation ─────────────────────────────\n\n/**\n * Merge a recipe's silence_policy into TrimOptions.\n * CLI options take precedence (per studio-recipe.md §4.1).\n */\nexport function applyRecipeToTrimOptions(\n recipe: StudioRecipe | undefined,\n cliOptions: TrimOptions,\n): TrimOptions {\n const policy = recipe?.silence_policy;\n if (!policy) return cliOptions;\n\n // CLI options win — only fill in from recipe where CLI didn't specify\n return {\n ...cliOptions,\n noise: cliOptions.noise ?? policy.noise,\n minSilence: cliOptions.minSilence ?? policy.min_silence,\n padPre: cliOptions.padPre ?? policy.default_padding_pre,\n padPost: cliOptions.padPost ?? policy.default_padding_post,\n // matchTolerance is recipe-only at this layer (no CLI flag yet)\n matchTolerance: cliOptions.matchTolerance ?? policy.match_tolerance,\n };\n}\n\n/**\n * Translate a recipe's caption_style + caption_grouping into runtime\n * BuildCaptionsOptions for the caption builder.\n *\n * CLI doesn't currently expose per-invocation caption styling flags;\n * the recipe is the canonical source for now.\n */\nexport function applyRecipeToCaptionOptions(\n recipe: StudioRecipe | undefined,\n): BuildCaptionsOptions {\n if (!recipe) return {};\n const style = recipe.caption_style;\n const grouping = recipe.caption_grouping;\n\n const runtimeStyle: RuntimeCaptionStyle = {};\n if (style) {\n if (style.font_family !== undefined) runtimeStyle.fontFamily = style.font_family;\n if (style.font_size !== undefined) runtimeStyle.fontSize = style.font_size;\n if (style.font_weight !== undefined) runtimeStyle.fontWeight = style.font_weight;\n if (style.text_align !== undefined) runtimeStyle.textAlign = style.text_align;\n if (style.color !== undefined) runtimeStyle.color = style.color;\n if (style.y_ratio !== undefined) runtimeStyle.yRatio = style.y_ratio;\n if (style.width_ratio !== undefined) runtimeStyle.widthRatio = style.width_ratio;\n if (style.fade_seconds !== undefined) runtimeStyle.fadeSeconds = style.fade_seconds;\n }\n\n return {\n ...(Object.keys(runtimeStyle).length > 0 && { style: runtimeStyle }),\n ...(grouping?.max_words !== undefined && { maxWords: grouping.max_words }),\n ...(grouping?.pause_gap !== undefined && { pauseGap: grouping.pause_gap }),\n };\n}\n\n/**\n * Merge a recipe into TranscribeOptions. Caption-related recipe fields\n * are stashed on the transcribe options so the orchestrator can pass them\n * through to rewriteCaptionLayers.\n */\nexport function applyRecipeToTranscribeOptions(\n recipe: StudioRecipe | undefined,\n cliOptions: TranscribeOptions,\n): TranscribeOptions {\n if (!recipe) return cliOptions;\n const captionOptions = applyRecipeToCaptionOptions(recipe);\n return {\n ...cliOptions,\n captionOptions,\n };\n}\n\n/**\n * Render a recipe's effective values (recipe overlaid on code defaults).\n * Used by `atelier recipe show --with-defaults`.\n */\nexport function renderRecipeWithDefaults(recipe: StudioRecipe): StudioRecipe {\n const defaults: { silence_policy: SilencePolicy; caption_style: CaptionStyle; caption_grouping: CaptionGrouping } = {\n silence_policy: {\n noise: \"-30dB\",\n min_silence: 0.35,\n default_padding_pre: 0.08,\n default_padding_post: 0.12,\n match_tolerance: 0.5,\n },\n caption_style: {\n font_family: \"Inter\",\n font_size: 84,\n font_weight: \"bold\",\n text_align: \"center\",\n color: \"#FFFFFF\",\n y_ratio: 0.85,\n width_ratio: 0.9,\n fade_seconds: 0.05,\n },\n caption_grouping: {\n max_words: 5,\n pause_gap: 0.4,\n },\n };\n\n return {\n ...recipe,\n silence_policy: { ...defaults.silence_policy, ...recipe.silence_policy },\n caption_style: { ...defaults.caption_style, ...recipe.caption_style },\n caption_grouping: { ...defaults.caption_grouping, ...recipe.caption_grouping },\n };\n}\n\n/** Serialize a recipe back to YAML for `recipe show` output */\nexport function recipeToYaml(recipe: StudioRecipe): string {\n return stringifyYaml(recipe);\n}\n\n// ─── Overlay translator ──────────────────────────────────────────\n//\n// Translates recipe.overlay_rules → tag-isolated TextVisual layers\n// (handle + page_number). Mirrors rewriteCaptionLayers' tag-namespace\n// isolation invariant: only \"overlay\"-tagged layers are touched; all\n// user-authored / silence-trim / caption layers pass through untouched.\n// Re-applying is idempotent — the prior overlay set is dropped before\n// the fresh one is appended.\n\n/** Context for overlay translation — required for page_number rendering */\nexport interface ApplyOverlayContext {\n /** 1-based index in a carousel (substituted for {current}) */\n currentIndex?: number;\n /** Total carousel size (substituted for {total}) */\n totalCount?: number;\n}\n\n/** Default px from the anchored edges when a rule omits margin */\nconst DEFAULT_OVERLAY_MARGIN = 24;\n\n/** Default TextStyle baseline — overlay rule.style merges OVER these */\nconst DEFAULT_OVERLAY_TEXT_STYLE = {\n fontFamily: \"Inter\",\n fontSize: 24,\n fontWeight: 600 as const,\n color: \"#F5F5F7\",\n};\n\n/** Stable layer ids — re-apply replaces by id within the overlay drop+re-add */\nconst HANDLE_LAYER_ID = \"overlay-handle\";\nconst PAGE_NUMBER_LAYER_ID = \"overlay-page-number\";\n\n/**\n * Apply a Studio Recipe's overlay_rules to a document. Returns a NEW document;\n * input is never mutated. Drops every layer tagged \"overlay\" before appending\n * the freshly-derived overlay layers, so re-running is idempotent.\n *\n * page_number layers are only emitted when ctx.currentIndex + ctx.totalCount\n * are both present — single-frame application silently skips page_number\n * (with a one-shot console.warn) so apply-recipe pipelines stay safe outside\n * carousel batches.\n */\nexport function applyRecipeToOverlay(\n doc: AtelierDocument,\n recipe: StudioRecipe,\n ctx?: ApplyOverlayContext,\n): AtelierDocument {\n const preserved = doc.layers.filter((l) => !(l.tags ?? []).includes(\"overlay\"));\n const overlayLayers: Layer[] = [];\n\n const rules = recipe.overlay_rules;\n if (!rules) {\n return { ...doc, layers: preserved };\n }\n\n if (rules.handle) {\n overlayLayers.push(buildHandleLayer(rules.handle, doc.canvas));\n }\n\n if (rules.page_number) {\n if (ctx?.currentIndex != null && ctx?.totalCount != null) {\n overlayLayers.push(\n buildPageNumberLayer(rules.page_number, doc.canvas, ctx.currentIndex, ctx.totalCount),\n );\n } else {\n console.warn(\n `applyRecipeToOverlay: recipe.overlay_rules.page_number present but ` +\n `currentIndex/totalCount not provided — skipping page_number layer.`,\n );\n }\n }\n\n return {\n ...doc,\n layers: [...preserved, ...overlayLayers],\n };\n}\n\n/** Build the anchored handle TextVisual layer */\nfunction buildHandleLayer(\n rule: { text: string; anchor: OverlayAnchor; margin?: number; style?: OverlayTextStyle },\n canvas: AtelierDocument[\"canvas\"],\n): Layer {\n const margin = rule.margin ?? DEFAULT_OVERLAY_MARGIN;\n const { frame, anchorPoint } = anchorToFrame(rule.anchor, canvas, margin);\n return {\n id: HANDLE_LAYER_ID,\n tags: [\"overlay\"],\n visual: {\n type: \"text\",\n content: rule.text,\n style: mergeOverlayStyle(rule.style),\n },\n frame,\n bounds: { width: 600, height: 80 },\n anchorPoint,\n };\n}\n\n/** Build the anchored page-number TextVisual layer */\nfunction buildPageNumberLayer(\n rule: OverlayPageNumberRule,\n canvas: AtelierDocument[\"canvas\"],\n currentIndex: number,\n totalCount: number,\n): Layer {\n const margin = rule.margin ?? DEFAULT_OVERLAY_MARGIN;\n const { frame, anchorPoint } = anchorToFrame(rule.anchor, canvas, margin);\n return {\n id: PAGE_NUMBER_LAYER_ID,\n tags: [\"overlay\"],\n visual: {\n type: \"text\",\n content: renderPageNumberFormat(rule.format, currentIndex, totalCount),\n style: mergeOverlayStyle(rule.style),\n },\n frame,\n bounds: { width: 200, height: 80 },\n anchorPoint,\n };\n}\n\n/** Anchor enum → frame coords + 0/1 anchorPoint */\nfunction anchorToFrame(\n anchor: OverlayAnchor,\n canvas: AtelierDocument[\"canvas\"],\n margin: number,\n): { frame: { x: number; y: number }; anchorPoint: { x: number; y: number } } {\n switch (anchor) {\n case \"top-left\":\n return { frame: { x: margin, y: margin }, anchorPoint: { x: 0, y: 0 } };\n case \"top-right\":\n return { frame: { x: canvas.width - margin, y: margin }, anchorPoint: { x: 1, y: 0 } };\n case \"bottom-left\":\n return { frame: { x: margin, y: canvas.height - margin }, anchorPoint: { x: 0, y: 1 } };\n case \"bottom-right\":\n return {\n frame: { x: canvas.width - margin, y: canvas.height - margin },\n anchorPoint: { x: 1, y: 1 },\n };\n }\n}\n\n/** Merge a partial OverlayTextStyle over the runtime defaults (always returns a complete TextStyle) */\nfunction mergeOverlayStyle(\n style: OverlayTextStyle | undefined,\n): { fontFamily: string; fontSize: number; fontWeight: number | \"normal\" | \"bold\"; color: string } {\n return {\n fontFamily: style?.font_family ?? DEFAULT_OVERLAY_TEXT_STYLE.fontFamily,\n fontSize: style?.font_size ?? DEFAULT_OVERLAY_TEXT_STYLE.fontSize,\n fontWeight: style?.font_weight ?? DEFAULT_OVERLAY_TEXT_STYLE.fontWeight,\n color: style?.color ?? DEFAULT_OVERLAY_TEXT_STYLE.color,\n };\n}\n\n/**\n * Render a page_number format template by substituting {current} / {total}\n * placeholders (including zero-pad forms like {current:02d}, {total:02d}).\n *\n * The schema (^valid-recipe gate) already enforces that ≥1 placeholder is\n * present — this is render-time substitution only.\n */\nexport function renderPageNumberFormat(\n format: string,\n currentIndex: number,\n totalCount: number,\n): string {\n return format.replace(\n /\\{(current|total)(?::0(\\d+)d)?\\}/g,\n (_, name: string, padWidth?: string) => {\n const value = name === \"current\" ? currentIndex : totalCount;\n const str = String(value);\n if (padWidth) {\n const width = parseInt(padWidth, 10);\n return str.padStart(width, \"0\");\n }\n return str;\n },\n );\n}\n","import { spawn } from \"node:child_process\";\n\n/** A detected silence interval, in seconds from source start */\nexport interface SilenceInterval {\n start: number;\n end: number;\n}\n\n/** Options for the ffmpeg silencedetect filter */\nexport interface SilenceDetectOptions {\n /** Threshold below which audio counts as silence (default: \"-30dB\") */\n noise?: string;\n /** Minimum silence duration in seconds to register (default: 0.35) */\n minSilence?: number;\n}\n\n/**\n * Verify the local ffmpeg build has the silencedetect filter compiled in.\n * Fails loud and early if missing — some minimal builds disable filters.\n */\nexport async function probeSilencedetect(): Promise<void> {\n const stdout = await runCapture(\"ffmpeg\", [\"-hide_banner\", \"-filters\"]);\n if (!/\\bsilencedetect\\b/.test(stdout)) {\n throw new Error(\n \"Your ffmpeg build lacks the silencedetect filter. \" +\n \"Install a standard ffmpeg ≥ 4.0 (brew install ffmpeg / apt install ffmpeg).\",\n );\n }\n}\n\n/**\n * Probe source video duration via ffprobe, in seconds.\n * Used for boundary clamping of the trailing cut.\n */\nexport async function probeDuration(sourcePath: string): Promise<number> {\n const stdout = await runCapture(\"ffprobe\", [\n \"-v\", \"error\",\n \"-show_entries\", \"format=duration\",\n \"-of\", \"csv=p=0\",\n sourcePath,\n ]);\n const n = parseFloat(stdout.trim());\n if (!Number.isFinite(n) || n <= 0) {\n throw new Error(`ffprobe returned invalid duration for ${sourcePath}: \"${stdout}\"`);\n }\n return n;\n}\n\n/**\n * Run ffmpeg silencedetect on a source file, return list of silence intervals.\n *\n * silencedetect writes paired lines to stderr:\n * [silencedetect @ 0x...] silence_start: 1.234\n * [silencedetect @ 0x...] silence_end: 5.678 | silence_duration: 4.444\n *\n * Output to null muxer — no decoded frames, just the filter walking the audio.\n */\nexport async function runSilenceDetect(\n sourcePath: string,\n options: SilenceDetectOptions = {},\n): Promise<SilenceInterval[]> {\n const noise = options.noise ?? \"-30dB\";\n const minSilence = options.minSilence ?? 0.35;\n const filter = `silencedetect=noise=${noise}:d=${minSilence}`;\n\n const stderr = await runCaptureStderr(\"ffmpeg\", [\n \"-hide_banner\",\n \"-nostats\",\n \"-i\", sourcePath,\n \"-af\", filter,\n \"-f\", \"null\",\n \"-\",\n ]);\n\n return parseSilenceDetectStderr(stderr);\n}\n\n/**\n * Parse ffmpeg's silencedetect stderr output into intervals.\n * Pairs start/end lines in order; tolerates other filter chatter interleaved.\n * Exported for unit testing.\n */\nexport function parseSilenceDetectStderr(stderr: string): SilenceInterval[] {\n const intervals: SilenceInterval[] = [];\n const startRe = /silence_start:\\s*(-?[\\d.]+)/;\n const endRe = /silence_end:\\s*(-?[\\d.]+)/;\n\n let pendingStart: number | null = null;\n for (const line of stderr.split(/\\r?\\n/)) {\n const sm = line.match(startRe);\n if (sm) {\n pendingStart = parseFloat(sm[1]);\n continue;\n }\n const em = line.match(endRe);\n if (em && pendingStart !== null) {\n const end = parseFloat(em[1]);\n // silencedetect can emit start <0 if audio starts in silence — clamp\n intervals.push({ start: Math.max(0, pendingStart), end });\n pendingStart = null;\n }\n }\n return intervals;\n}\n\n// ─── subprocess plumbing ─────────────────────────────────────────\n\nfunction runCapture(cmd: string, args: string[]): Promise<string> {\n return new Promise((resolve, reject) => {\n const proc = spawn(cmd, args, { stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n let stdout = \"\";\n proc.stdout.on(\"data\", (b) => (stdout += b.toString()));\n proc.on(\"error\", (err) => {\n const e = err as NodeJS.ErrnoException;\n if (e.code === \"ENOENT\") {\n reject(new Error(`${cmd} not found on PATH. Install ffmpeg/ffprobe (brew install ffmpeg).`));\n } else {\n reject(err);\n }\n });\n proc.on(\"close\", (code) => {\n if (code !== 0) reject(new Error(`${cmd} exited ${code}`));\n else resolve(stdout);\n });\n });\n}\n\nfunction runCaptureStderr(cmd: string, args: string[]): Promise<string> {\n return new Promise((resolve, reject) => {\n const proc = spawn(cmd, args, { stdio: [\"ignore\", \"ignore\", \"pipe\"] });\n let stderr = \"\";\n proc.stderr.on(\"data\", (b) => (stderr += b.toString()));\n proc.on(\"error\", (err) => {\n const e = err as NodeJS.ErrnoException;\n if (e.code === \"ENOENT\") {\n reject(new Error(`${cmd} not found on PATH. Install ffmpeg (brew install ffmpeg).`));\n } else {\n reject(err);\n }\n });\n // null muxer always exits non-zero on EOF in some ffmpeg builds — accept any code\n proc.on(\"close\", () => resolve(stderr));\n });\n}\n","import type { CutEntry } from \"@a-company/atelier-types\";\nimport type { SilenceInterval } from \"./silence-detect.js\";\n\n/** A detected speech span (inverse of silence) — pre-padding */\nexport interface SpeechInterval {\n start: number;\n end: number;\n}\n\n/** Default leading/trailing padding around each detected speech segment */\nexport const DEFAULT_PADDING_PRE = 0.08;\nexport const DEFAULT_PADDING_POST = 0.12;\n\n/** Match tolerance (seconds) for preserving user padding on re-detect */\nexport const DEFAULT_MATCH_TOLERANCE = 0.5;\n\n/**\n * Invert silence intervals into the gaps between them — the speech intervals.\n * Handles leading and trailing silence (no speech before first silence /\n * after last silence respectively).\n */\nexport function invertToSpeechIntervals(\n silences: SilenceInterval[],\n duration: number,\n): SpeechInterval[] {\n if (silences.length === 0) {\n return duration > 0 ? [{ start: 0, end: duration }] : [];\n }\n\n const sorted = [...silences].sort((a, b) => a.start - b.start);\n const speech: SpeechInterval[] = [];\n\n // Leading speech (before first silence)\n if (sorted[0].start > 0) {\n speech.push({ start: 0, end: sorted[0].start });\n }\n\n // Speech between adjacent silences\n for (let i = 0; i < sorted.length - 1; i++) {\n const gapStart = sorted[i].end;\n const gapEnd = sorted[i + 1].start;\n if (gapEnd > gapStart) {\n speech.push({ start: gapStart, end: gapEnd });\n }\n }\n\n // Trailing speech (after last silence)\n const last = sorted[sorted.length - 1];\n if (last.end < duration) {\n speech.push({ start: last.end, end: duration });\n }\n\n return speech;\n}\n\n/** Build initial CutEntry[] from speech intervals using default padding */\nexport function buildInitialCuts(\n speech: SpeechInterval[],\n paddingPre = DEFAULT_PADDING_PRE,\n paddingPost = DEFAULT_PADDING_POST,\n): CutEntry[] {\n return speech.map((s) => ({\n rawStart: s.start,\n rawEnd: s.end,\n paddingPre,\n paddingPost,\n }));\n}\n\n/**\n * Resolve overlap between adjacent cuts (when paddingPost[i] + paddingPre[i+1]\n * exceeds the silence gap between them). Each cut gets equal share of the\n * silence — neither \"wins.\"\n *\n * Mutates cuts in place.\n */\nexport function resolveOverlaps(cuts: CutEntry[]): void {\n for (let i = 0; i < cuts.length - 1; i++) {\n const a = cuts[i];\n const b = cuts[i + 1];\n const aEnd = a.rawEnd + a.paddingPost;\n const bStart = b.rawStart - b.paddingPre;\n if (aEnd > bStart) {\n // Overlap — split at silence midpoint\n const mid = (a.rawEnd + b.rawStart) / 2;\n a.paddingPost = Math.max(0, mid - a.rawEnd);\n b.paddingPre = Math.max(0, b.rawStart - mid);\n }\n }\n}\n\n/**\n * Clamp first cut's paddingPre so effective start >= 0, and last cut's\n * paddingPost so effective end <= duration.\n *\n * Mutates cuts in place.\n */\nexport function clampBoundaries(cuts: CutEntry[], duration: number): void {\n if (cuts.length === 0) return;\n const first = cuts[0];\n if (first.rawStart - first.paddingPre < 0) {\n first.paddingPre = first.rawStart;\n }\n const last = cuts[cuts.length - 1];\n if (last.rawEnd + last.paddingPost > duration) {\n last.paddingPost = Math.max(0, duration - last.rawEnd);\n }\n}\n\n/**\n * Merge a freshly-detected cut list with an existing one, preserving user\n * padding overrides on any cut whose raw boundary still matches within\n * `tolerance` seconds (both start and end).\n *\n * For each fresh cut:\n * - if an existing cut matches: copy its padding and label, update raw values\n * - if no match: keep the fresh defaults\n *\n * Returns a new array; does not mutate inputs.\n */\nexport function mergeWithExisting(\n fresh: CutEntry[],\n existing: CutEntry[],\n tolerance = DEFAULT_MATCH_TOLERANCE,\n): CutEntry[] {\n return fresh.map((f) => {\n const match = existing.find(\n (e) =>\n Math.abs(e.rawStart - f.rawStart) < tolerance &&\n Math.abs(e.rawEnd - f.rawEnd) < tolerance,\n );\n if (!match) return f;\n return {\n rawStart: f.rawStart,\n rawEnd: f.rawEnd,\n paddingPre: match.paddingPre,\n paddingPost: match.paddingPost,\n ...(match.label !== undefined && { label: match.label }),\n };\n });\n}\n\n/**\n * Apply a global padding delta to every cut (positive = loosen, negative = tighten).\n * Floors padding at 0 — never goes negative.\n *\n * Mutates cuts in place.\n */\nexport function applyGlobalPadding(cuts: CutEntry[], deltaSeconds: number): void {\n for (const cut of cuts) {\n cut.paddingPre = Math.max(0, cut.paddingPre + deltaSeconds);\n cut.paddingPost = Math.max(0, cut.paddingPost + deltaSeconds);\n }\n}\n","import type { Command } from \"commander\";\nimport type { CutEntry } from \"@a-company/atelier-types\";\nimport {\n loadVideoProject,\n readCutList,\n writeCutList,\n readComposition,\n writeComposition,\n rewriteCutLayers,\n} from \"../lib/video-project.js\";\nimport {\n probeSilencedetect,\n probeDuration,\n runSilenceDetect,\n} from \"../lib/silence-detect.js\";\nimport {\n invertToSpeechIntervals,\n buildInitialCuts,\n resolveOverlaps,\n clampBoundaries,\n mergeWithExisting,\n applyGlobalPadding,\n DEFAULT_PADDING_PRE,\n DEFAULT_PADDING_POST,\n} from \"../lib/cut-model.js\";\nimport { loadRecipe, applyRecipeToTrimOptions } from \"../lib/recipe.js\";\n\nexport interface TrimOptions {\n /** silencedetect noise threshold, e.g. \"-30dB\" */\n noise?: string;\n /** Minimum silence duration to register, in seconds */\n minSilence?: number;\n /** Default leading padding for new cuts, in seconds */\n padPre?: number;\n /** Default trailing padding for new cuts, in seconds */\n padPost?: number;\n /** Re-detect match tolerance for preserving user padding, in seconds */\n matchTolerance?: number;\n /** Global tighten across all cuts, in milliseconds (positive number) */\n tightenMs?: number;\n /** Global loosen across all cuts, in milliseconds (positive number) */\n loosenMs?: number;\n /** Apply --pad-pre / --pad-post to one specific cut index only */\n cutIndex?: number;\n /** Discard existing padding; full fresh detect with default padding */\n reset?: boolean;\n /** Don't write files; return result */\n dryRun?: boolean;\n}\n\nexport interface TrimResult {\n projectDir: string;\n duration: number;\n cuts: CutEntry[];\n layerCount: number;\n}\n\n/**\n * Run the silence-trim pipeline on a VideoProject folder.\n *\n * Pipeline:\n * 1. Probe ffmpeg has silencedetect filter\n * 2. ffprobe source duration\n * 3. Run silencedetect → silence intervals\n * 4. Invert to speech intervals\n * 5. Build fresh CutEntry[] with default (or recipe) padding\n * 6. Merge with existing cuts (preserves user padding) unless --reset\n * 7. Apply --tighten / --loosen / --cut overrides\n * 8. Resolve overlaps at silence midpoints\n * 9. Clamp boundaries to [0, duration]\n * 10. Write cuts.json + rewrite silence-trim layers in project.atelier\n */\nexport async function trimProject(\n projectDir: string,\n options: TrimOptions = {},\n): Promise<TrimResult> {\n const project = loadVideoProject(projectDir);\n\n await probeSilencedetect();\n const duration = await probeDuration(project.sourcePath);\n\n const silences = await runSilenceDetect(project.sourcePath, {\n noise: options.noise,\n minSilence: options.minSilence,\n });\n const speech = invertToSpeechIntervals(silences, duration);\n\n const padPre = options.padPre ?? DEFAULT_PADDING_PRE;\n const padPost = options.padPost ?? DEFAULT_PADDING_POST;\n let cuts = buildInitialCuts(speech, padPre, padPost);\n\n // Re-run preservation — keep user padding on matching raw boundaries\n if (!options.reset) {\n const existing = readCutList(project);\n cuts = mergeWithExisting(cuts, existing.cuts, options.matchTolerance);\n }\n\n // Global tighten/loosen — applied to current padding (preserves overrides)\n if (typeof options.tightenMs === \"number\") {\n applyGlobalPadding(cuts, -options.tightenMs / 1000);\n }\n if (typeof options.loosenMs === \"number\") {\n applyGlobalPadding(cuts, options.loosenMs / 1000);\n }\n\n // Single-cut override\n if (typeof options.cutIndex === \"number\") {\n if (options.cutIndex < 0 || options.cutIndex >= cuts.length) {\n throw new Error(\n `--cut ${options.cutIndex} out of range (have ${cuts.length} cuts)`,\n );\n }\n if (options.padPre !== undefined) cuts[options.cutIndex].paddingPre = options.padPre;\n if (options.padPost !== undefined) cuts[options.cutIndex].paddingPost = options.padPost;\n }\n\n resolveOverlaps(cuts);\n clampBoundaries(cuts, duration);\n\n const result: TrimResult = {\n projectDir: project.dir,\n duration,\n cuts,\n layerCount: cuts.length,\n };\n\n if (options.dryRun) return result;\n\n writeCutList(project, {\n version: \"1.1\",\n source: project.manifest.source,\n cuts,\n });\n\n const doc = readComposition(project);\n const updated = rewriteCutLayers(doc, cuts, project.manifest.source, duration);\n writeComposition(project, updated);\n\n return result;\n}\n\n/** Format a TrimResult for human-readable terminal output */\nfunction formatResult(result: TrimResult): string {\n const lines: string[] = [];\n lines.push(`Trimmed ${result.projectDir}`);\n lines.push(` source duration: ${result.duration.toFixed(2)}s`);\n lines.push(` cuts: ${result.cuts.length}`);\n for (let i = 0; i < result.cuts.length; i++) {\n const c = result.cuts[i];\n const effStart = Math.max(0, c.rawStart - c.paddingPre);\n const effEnd = Math.min(result.duration, c.rawEnd + c.paddingPost);\n const dur = effEnd - effStart;\n lines.push(\n ` [${i}] ${effStart.toFixed(2)}s → ${effEnd.toFixed(2)}s ` +\n `(${dur.toFixed(2)}s, pad ${c.paddingPre.toFixed(2)}/${c.paddingPost.toFixed(2)})` +\n (c.label ? ` \"${c.label}\"` : \"\"),\n );\n }\n return lines.join(\"\\n\");\n}\n\n/** Register `atelier trim` on the Commander program */\nexport function trimCommand(program: Command): void {\n program\n .command(\"trim <project>\")\n .description(\n \"Detect silence and rewrite project.atelier with parametric cuts \" +\n \"(silence-trim tagged layers). Preserves user padding overrides on re-run.\",\n )\n .option(\"--noise <dB>\", \"Silence threshold (default: -30dB)\", \"-30dB\")\n .option(\n \"--min-silence <seconds>\",\n \"Minimum silence duration to register (default: 0.35)\",\n (v) => parseFloat(v),\n 0.35,\n )\n .option(\n \"--pad-pre <seconds>\",\n `Default leading padding (default: ${DEFAULT_PADDING_PRE})`,\n (v) => parseFloat(v),\n )\n .option(\n \"--pad-post <seconds>\",\n `Default trailing padding (default: ${DEFAULT_PADDING_POST})`,\n (v) => parseFloat(v),\n )\n .option(\"--tighten <ms>\", \"Reduce all current padding by N ms\", (v) => parseInt(v, 10))\n .option(\"--loosen <ms>\", \"Increase all current padding by N ms\", (v) => parseInt(v, 10))\n .option(\n \"--cut <index>\",\n \"Apply --pad-pre / --pad-post to one specific cut only\",\n (v) => parseInt(v, 10),\n )\n .option(\"--reset\", \"Discard existing padding; re-detect from scratch\")\n .option(\"--recipe <name>\", \"Apply a Studio Recipe's silence_policy as the baseline\")\n .option(\"--dry-run\", \"Print computed cuts; don't write files\")\n .option(\"--json\", \"Output result as JSON for piping\")\n .action(async (\n project: string,\n opts: {\n noise: string;\n minSilence: number;\n padPre?: number;\n padPost?: number;\n tighten?: number;\n loosen?: number;\n cut?: number;\n reset?: boolean;\n recipe?: string;\n dryRun?: boolean;\n json?: boolean;\n },\n ) => {\n try {\n let trimOpts: TrimOptions = {\n noise: opts.noise,\n minSilence: opts.minSilence,\n padPre: opts.padPre,\n padPost: opts.padPost,\n tightenMs: opts.tighten,\n loosenMs: opts.loosen,\n cutIndex: opts.cut,\n reset: opts.reset,\n dryRun: opts.dryRun,\n };\n if (opts.recipe) {\n const { recipe } = loadRecipe(opts.recipe, project);\n trimOpts = applyRecipeToTrimOptions(recipe, trimOpts);\n }\n const result = await trimProject(project, trimOpts);\n\n if (opts.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log(formatResult(result));\n if (opts.dryRun) console.log(\"(dry-run — no files written)\");\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(`atelier trim: ${msg}`);\n process.exit(1);\n }\n });\n}\n","import { spawn } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport type { VideoTranscript } from \"@a-company/atelier-types\";\n\n/** Whisper model selection (size/quality tradeoff) */\nexport type WhisperModel =\n | \"tiny\" | \"tiny.en\"\n | \"base\" | \"base.en\"\n | \"small\" | \"small.en\"\n | \"medium\" | \"medium.en\"\n | \"large-v3\";\n\nexport interface WhisperOptions {\n /** Model size (default: \"base.en\") */\n model?: WhisperModel;\n /** BCP-47 language hint (omit for autodetect) */\n language?: string;\n /** Explicit path to the model file — overrides model lookup by name */\n modelPath?: string;\n}\n\n/** Backend that produced a transcript run */\nexport type WhisperBackend = \"whisper-cpp\" | \"openai-api\" | \"none\";\n\n/**\n * Probe which Whisper backend is available on this machine.\n * - \"whisper-cpp\" if `whisper-cli` is on PATH\n * - \"openai-api\" if OPENAI_API_KEY is set and --use-api requested\n * - \"none\" otherwise — caller throws with install guidance\n */\nexport async function probeWhisper(): Promise<WhisperBackend> {\n if (await commandExists(\"whisper-cli\")) return \"whisper-cpp\";\n if (process.env.OPENAI_API_KEY) return \"openai-api\";\n return \"none\";\n}\n\n/**\n * Run whisper.cpp on a source file and return the raw JSON stdout.\n * Caller passes to parseWhisperCppJson() to get a VideoTranscript.\n *\n * Note: whisper-cli writes JSON to stdout when given --output-json and \"-\"\n * as the output destination. Some builds always write to a file with the\n * `.json` suffix appended to the input path; we handle both.\n */\nexport async function runWhisperCpp(\n sourcePath: string,\n options: WhisperOptions = {},\n): Promise<string> {\n const model = options.modelPath ?? options.model ?? \"base.en\";\n\n const args = [\n sourcePath,\n \"--model\", model,\n \"--output-json\",\n \"--word-thold\", \"0.01\", // emit word-level timestamps\n \"--print-progress\", \"false\",\n ];\n if (options.language) {\n args.push(\"--language\", options.language);\n }\n\n return runCaptureStdout(\"whisper-cli\", args);\n}\n\n/**\n * Parse whisper.cpp --output-json output into a VideoTranscript.\n *\n * whisper.cpp emits a structure like:\n * {\n * \"result\": { \"language\": \"en\" },\n * \"transcription\": [\n * {\n * \"timestamps\": { \"from\": \"00:00:00,000\", \"to\": \"00:00:02,300\" },\n * \"offsets\": { \"from\": 0, \"to\": 2300 },\n * \"text\": \" Hello world\",\n * \"tokens\": [ ... ] // optional per-token detail\n * }\n * ]\n * }\n *\n * Token-level word timestamps come via the \"tokens\" array on each segment\n * when --output-json-full is used. With --output-json (lighter), only\n * segment-level boundaries are present and we synthesize word timing by\n * even split across the segment.\n *\n * Exported for unit testing.\n */\nexport function parseWhisperCppJson(jsonStr: string): VideoTranscript {\n const raw = JSON.parse(jsonStr) as {\n result?: { language?: string };\n transcription?: Array<{\n offsets?: { from: number; to: number };\n timestamps?: { from: string; to: string };\n text: string;\n tokens?: Array<{\n text: string;\n offsets?: { from: number; to: number };\n timestamps?: { from: string; to: string };\n p?: number; // probability/confidence\n }>;\n }>;\n };\n\n const segments = (raw.transcription ?? []).map((seg) => {\n const segStart = (seg.offsets?.from ?? 0) / 1000;\n const segEnd = (seg.offsets?.to ?? 0) / 1000;\n const segText = seg.text.trim();\n\n let words;\n if (seg.tokens && seg.tokens.length > 0) {\n // Token-level detail available — emit one word per non-special token\n words = seg.tokens\n .filter((t) => t.text.trim().length > 0 && !t.text.startsWith(\"[_\"))\n .map((t) => ({\n detected: t.text.trim(),\n text: t.text.trim(),\n start: (t.offsets?.from ?? segStart * 1000) / 1000,\n end: (t.offsets?.to ?? segEnd * 1000) / 1000,\n ...(t.p !== undefined && { confidence: t.p }),\n }));\n } else {\n // Fall back to even-split across segment\n const tokens = segText.split(/\\s+/).filter((t) => t.length > 0);\n const span = segEnd - segStart;\n const per = tokens.length > 0 ? span / tokens.length : 0;\n words = tokens.map((tok, i) => ({\n detected: tok,\n text: tok,\n start: segStart + i * per,\n end: segStart + (i + 1) * per,\n }));\n }\n\n return {\n text: segText,\n start: segStart,\n end: segEnd,\n words,\n };\n });\n\n return {\n version: \"1.1\",\n ...(raw.result?.language !== undefined && { language: raw.result.language }),\n segments,\n };\n}\n\n// ─── subprocess plumbing ─────────────────────────────────────────\n\n/** Check whether a binary is callable on PATH (cross-platform-ish via `which` / `where`) */\nexport async function commandExists(name: string): Promise<boolean> {\n // If user passed an absolute path, just check the file\n if (name.startsWith(\"/\") || name.match(/^[A-Z]:\\\\/)) {\n return existsSync(name);\n }\n return new Promise((resolve) => {\n const probe = spawn(process.platform === \"win32\" ? \"where\" : \"which\", [name], {\n stdio: [\"ignore\", \"ignore\", \"ignore\"],\n });\n probe.on(\"error\", () => resolve(false));\n probe.on(\"close\", (code) => resolve(code === 0));\n });\n}\n\nfunction runCaptureStdout(cmd: string, args: string[]): Promise<string> {\n return new Promise((resolve, reject) => {\n const proc = spawn(cmd, args, { stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n let stdout = \"\";\n let stderr = \"\";\n proc.stdout.on(\"data\", (b) => (stdout += b.toString()));\n proc.stderr.on(\"data\", (b) => (stderr += b.toString()));\n proc.on(\"error\", (err) => {\n const e = err as NodeJS.ErrnoException;\n if (e.code === \"ENOENT\") {\n reject(new Error(\n `${cmd} not found on PATH. Install whisper.cpp (brew install whisper-cpp) ` +\n `or run \\`pnpm add @xenova/transformers\\` for the ONNX fallback.`,\n ));\n } else {\n reject(err);\n }\n });\n proc.on(\"close\", (code) => {\n if (code !== 0) {\n reject(new Error(`${cmd} exited ${code}\\n${stderr}`));\n } else {\n resolve(stdout);\n }\n });\n });\n}\n","import type { TranscriptWord, TranscriptSegment, VideoTranscript } from \"@a-company/atelier-types\";\n\n/** Default match tolerance for re-transcribe merge (seconds) */\nexport const DEFAULT_TRANSCRIPT_MATCH_TOLERANCE = 0.3;\n\n/** Default phrase grouping parameters */\nexport const DEFAULT_PHRASE_MAX_WORDS = 5;\nexport const DEFAULT_PHRASE_PAUSE_GAP_SECONDS = 0.4;\n\n/** End-of-phrase punctuation marks */\nconst END_PUNCT = /[.!?,;:]\\s*$/;\n\n/**\n * Flatten a VideoTranscript's segments into a single ordered word array.\n * Used by edit commands that take a global word index.\n */\nexport function flattenWords(transcript: VideoTranscript): TranscriptWord[] {\n return transcript.segments.flatMap((s) => s.words);\n}\n\n/**\n * Phrase block — one rendered caption layer's worth of words.\n */\nexport interface CaptionPhrase {\n start: number;\n end: number;\n text: string;\n words: TranscriptWord[];\n}\n\n/**\n * Group transcript words into caption-sized phrases.\n *\n * Emits a new phrase when ANY of:\n * - currentPhrase.length >= maxWords\n * - currentWord.text ends in . ! ? , ; :\n * - gap between currentWord and nextWord > pauseGap seconds\n *\n * Hidden words are skipped (do not appear in captions but still in transcript).\n */\nexport function groupIntoPhrases(\n transcript: VideoTranscript,\n options: { maxWords?: number; pauseGap?: number } = {},\n): CaptionPhrase[] {\n const maxWords = options.maxWords ?? DEFAULT_PHRASE_MAX_WORDS;\n const pauseGap = options.pauseGap ?? DEFAULT_PHRASE_PAUSE_GAP_SECONDS;\n\n const phrases: CaptionPhrase[] = [];\n const visibleWords = flattenWords(transcript).filter((w) => !w.hidden);\n\n let current: TranscriptWord[] = [];\n for (let i = 0; i < visibleWords.length; i++) {\n const w = visibleWords[i];\n current.push(w);\n\n const next = visibleWords[i + 1];\n const gap = next ? next.start - w.end : 0;\n const endsOnPunct = END_PUNCT.test(w.text);\n const atMax = current.length >= maxWords;\n\n if (!next || atMax || endsOnPunct || gap > pauseGap) {\n phrases.push({\n start: current[0].start,\n end: current[current.length - 1].end,\n text: current.map((c) => c.text).join(\" \"),\n words: current,\n });\n current = [];\n }\n }\n\n return phrases;\n}\n\n/**\n * Merge a freshly-detected transcript with an existing one, preserving user\n * edits (userEdited / userAdded / hidden + text override) on any word whose\n * raw boundary still matches within `tolerance` seconds AND whose `detected`\n * string is unchanged.\n *\n * userAdded words in the existing transcript have no matching fresh entry by\n * definition — they're preserved as orphans, inserted into the appropriate\n * segment by timing.\n */\nexport function mergeTranscriptWithExisting(\n fresh: VideoTranscript,\n existing: VideoTranscript,\n tolerance = DEFAULT_TRANSCRIPT_MATCH_TOLERANCE,\n): VideoTranscript {\n const existingWords = flattenWords(existing);\n\n const merged: VideoTranscript = {\n version: \"1.1\",\n ...(fresh.language !== undefined && { language: fresh.language }),\n segments: fresh.segments.map((seg) => ({\n text: seg.text,\n start: seg.start,\n end: seg.end,\n words: seg.words.map((freshWord) => {\n const match = existingWords.find(\n (e) =>\n !e.userAdded &&\n Math.abs(e.start - freshWord.start) < tolerance &&\n e.detected === freshWord.detected,\n );\n if (!match) return freshWord;\n return {\n detected: freshWord.detected,\n text: match.text,\n start: freshWord.start,\n end: freshWord.end,\n ...(freshWord.confidence !== undefined && { confidence: freshWord.confidence }),\n ...(match.userEdited && { userEdited: true }),\n ...(match.hidden && { hidden: true }),\n };\n }),\n })),\n };\n\n // Re-insert user-added orphan words into their original segment by timing\n const orphans = existingWords.filter((w) => w.userAdded);\n for (const orphan of orphans) {\n const segIdx = merged.segments.findIndex(\n (s) => orphan.start >= s.start && orphan.start <= s.end,\n );\n const targetSeg = segIdx >= 0\n ? merged.segments[segIdx]\n : merged.segments[merged.segments.length - 1];\n if (!targetSeg) continue;\n const insertIdx = targetSeg.words.findIndex((w) => w.start > orphan.start);\n if (insertIdx === -1) targetSeg.words.push(orphan);\n else targetSeg.words.splice(insertIdx, 0, orphan);\n }\n\n return merged;\n}\n\n/**\n * Replace the text of word at the given global index. Sets userEdited=true.\n * Returns a new VideoTranscript; does not mutate input.\n */\nexport function applyTextEdit(\n transcript: VideoTranscript,\n wordIndex: number,\n newText: string,\n): VideoTranscript {\n return mapWord(transcript, wordIndex, (w) => ({\n ...w,\n text: newText,\n userEdited: true,\n }));\n}\n\n/**\n * Apply a batch find/replace across all detected words.\n * Sets userEdited=true on every word whose detected text matches `find`.\n */\nexport function applyBatchReplace(\n transcript: VideoTranscript,\n find: string,\n replace: string,\n): VideoTranscript {\n return {\n ...transcript,\n segments: transcript.segments.map((seg) => ({\n ...seg,\n words: seg.words.map((w) =>\n w.detected === find\n ? { ...w, text: replace, userEdited: true }\n : w,\n ),\n })),\n };\n}\n\n/** Hide a word (excluded from caption render, kept in transcript). Sets hidden=true. */\nexport function applyHide(transcript: VideoTranscript, wordIndex: number): VideoTranscript {\n return mapWord(transcript, wordIndex, (w) => ({ ...w, hidden: true }));\n}\n\n/**\n * Insert a user-added word after the given global index.\n * Sets userAdded=true. Duration defaults to 0.15s if not specified.\n * Word is placed in the segment containing the anchor word.\n */\nexport function applyAdd(\n transcript: VideoTranscript,\n afterIndex: number,\n text: string,\n duration = 0.15,\n): VideoTranscript {\n const flat = flattenWords(transcript);\n if (afterIndex < 0 || afterIndex >= flat.length) {\n throw new Error(`afterIndex ${afterIndex} out of range (have ${flat.length} words)`);\n }\n const anchor = flat[afterIndex];\n const newWord: TranscriptWord = {\n detected: text,\n text,\n start: anchor.end,\n end: anchor.end + duration,\n userAdded: true,\n };\n\n // Find which segment contains the anchor word and insert there\n let cursor = 0;\n return {\n ...transcript,\n segments: transcript.segments.map((seg) => {\n const segStart = cursor;\n cursor += seg.words.length;\n if (afterIndex < segStart || afterIndex >= cursor) return seg;\n const localIdx = afterIndex - segStart;\n return {\n ...seg,\n words: [...seg.words.slice(0, localIdx + 1), newWord, ...seg.words.slice(localIdx + 1)],\n };\n }),\n };\n}\n\n/**\n * Merge adjacent words at indices i and i+1 into a single word.\n * The merged word's detected/text becomes the concatenation; timing spans both.\n * Sets userEdited=true.\n */\nexport function applyMerge(transcript: VideoTranscript, firstIndex: number): VideoTranscript {\n const flat = flattenWords(transcript);\n if (firstIndex < 0 || firstIndex >= flat.length - 1) {\n throw new Error(`firstIndex ${firstIndex} out of range for merge`);\n }\n const a = flat[firstIndex];\n const b = flat[firstIndex + 1];\n const mergedWord: TranscriptWord = {\n detected: a.detected + b.detected,\n text: a.text + b.text,\n start: a.start,\n end: b.end,\n userEdited: true,\n };\n\n let cursor = 0;\n return {\n ...transcript,\n segments: transcript.segments.map((seg) => {\n const segStart = cursor;\n cursor += seg.words.length;\n // Both words must fall in the same segment to merge cleanly\n if (firstIndex < segStart || firstIndex >= cursor - 1) return seg;\n const localIdx = firstIndex - segStart;\n return {\n ...seg,\n words: [...seg.words.slice(0, localIdx), mergedWord, ...seg.words.slice(localIdx + 2)],\n };\n }),\n };\n}\n\n/**\n * Split one word at the given fractional point (0–1). Timing prorates.\n * Sets userEdited=true on both halves. `firstText` and `secondText` default\n * to slicing the original text at its character midpoint.\n */\nexport function applySplit(\n transcript: VideoTranscript,\n wordIndex: number,\n fraction: number,\n firstText?: string,\n secondText?: string,\n): VideoTranscript {\n if (fraction <= 0 || fraction >= 1) {\n throw new Error(`split fraction must be in (0, 1), got ${fraction}`);\n }\n const flat = flattenWords(transcript);\n if (wordIndex < 0 || wordIndex >= flat.length) {\n throw new Error(`wordIndex ${wordIndex} out of range`);\n }\n const w = flat[wordIndex];\n const splitTime = w.start + (w.end - w.start) * fraction;\n const cutChar = Math.max(1, Math.floor(w.text.length * fraction));\n const first: TranscriptWord = {\n detected: w.detected,\n text: firstText ?? w.text.slice(0, cutChar),\n start: w.start,\n end: splitTime,\n userEdited: true,\n };\n const second: TranscriptWord = {\n detected: w.detected,\n text: secondText ?? w.text.slice(cutChar),\n start: splitTime,\n end: w.end,\n userEdited: true,\n };\n\n let cursor = 0;\n return {\n ...transcript,\n segments: transcript.segments.map((seg) => {\n const segStart = cursor;\n cursor += seg.words.length;\n if (wordIndex < segStart || wordIndex >= cursor) return seg;\n const localIdx = wordIndex - segStart;\n return {\n ...seg,\n words: [...seg.words.slice(0, localIdx), first, second, ...seg.words.slice(localIdx + 1)],\n };\n }),\n };\n}\n\n// ─── helpers ─────────────────────────────────────────────────────\n\nfunction mapWord(\n transcript: VideoTranscript,\n wordIndex: number,\n fn: (w: TranscriptWord) => TranscriptWord,\n): VideoTranscript {\n const flat = flattenWords(transcript);\n if (wordIndex < 0 || wordIndex >= flat.length) {\n throw new Error(`wordIndex ${wordIndex} out of range (have ${flat.length} words)`);\n }\n let cursor = 0;\n return {\n ...transcript,\n segments: transcript.segments.map((seg) => {\n const segStart = cursor;\n cursor += seg.words.length;\n if (wordIndex < segStart || wordIndex >= cursor) return seg;\n const localIdx = wordIndex - segStart;\n return {\n ...seg,\n words: seg.words.map((w, i) => (i === localIdx ? fn(w) : w)),\n };\n }),\n };\n}\n\n// Re-export for convenience\nexport type { TranscriptSegment };\n","import type {\n AtelierDocument,\n Layer,\n Delta,\n VideoTranscript,\n} from \"@a-company/atelier-types\";\nimport { groupIntoPhrases, type CaptionPhrase } from \"./transcript-model.js\";\n\n/** Default style for generated caption layers — overridable by Studio Recipe */\nexport interface CaptionStyle {\n fontFamily?: string;\n fontSize?: number;\n fontWeight?: number | \"normal\" | \"bold\";\n textAlign?: \"left\" | \"center\" | \"right\";\n color?: string;\n /** Relative vertical position 0–1 (0 = top, 1 = bottom). Default 0.85 — lower-third. */\n yRatio?: number;\n /** Horizontal width as ratio of canvas width. Default 0.9. */\n widthRatio?: number;\n /** Fade duration in seconds for opacity in/out. Default 0.05 (3 frames at 60fps). */\n fadeSeconds?: number;\n}\n\nconst DEFAULT_STYLE: Required<CaptionStyle> = {\n fontFamily: \"Inter\",\n fontSize: 84,\n fontWeight: \"bold\" as const,\n textAlign: \"center\" as const,\n color: \"#FFFFFF\",\n yRatio: 0.85,\n widthRatio: 0.9,\n fadeSeconds: 0.05,\n};\n\nexport interface BuildCaptionsOptions {\n style?: CaptionStyle;\n /** Phrase grouping — max words per caption phrase */\n maxWords?: number;\n /** Phrase grouping — pause gap in seconds that forces a phrase break */\n pauseGap?: number;\n}\n\n/**\n * Build caption-tagged TextVisual layers from a transcript + canvas dimensions.\n *\n * Each phrase becomes one Layer with:\n * - tags: [\"caption\"]\n * - TextVisual with merged style\n * - opacity: 0 (default; deltas animate to 1 during the phrase)\n * - positioned at canvas.width * 0.5, canvas.height * yRatio\n *\n * Caller is responsible for appending these to a state's deltas array\n * (returned alongside the layers as Delta[] keyed to layer id).\n */\nexport function buildCaptionLayers(\n transcript: VideoTranscript,\n canvas: AtelierDocument[\"canvas\"],\n options: BuildCaptionsOptions = {},\n): { layers: Layer[]; deltas: Delta[] } {\n const style = { ...DEFAULT_STYLE, ...options.style };\n const phrases = groupIntoPhrases(transcript, {\n maxWords: options.maxWords,\n pauseGap: options.pauseGap,\n });\n\n const layers: Layer[] = [];\n const deltas: Delta[] = [];\n const fps = canvas.fps;\n\n phrases.forEach((phrase, idx) => {\n const layerId = `caption-${idx}`;\n layers.push(buildPhraseLayer(layerId, phrase, canvas, style));\n deltas.push(...buildPhraseDeltas(layerId, phrase, style.fadeSeconds, fps));\n });\n\n return { layers, deltas };\n}\n\n/**\n * Drop caption-tagged layers + their deltas from a composition,\n * append fresh ones from the current transcript.\n *\n * Mirrors rewriteCutLayers' invariant: only caption-tagged layers touched;\n * all other layers (silence-trim, overlay, user-authored) preserved.\n *\n * Deltas are written into the default state (or first state if no \"default\").\n */\nexport function rewriteCaptionLayers(\n doc: AtelierDocument,\n transcript: VideoTranscript,\n options: BuildCaptionsOptions = {},\n): AtelierDocument {\n const preserved = doc.layers.filter((l) => !(l.tags ?? []).includes(\"caption\"));\n const { layers: captionLayers, deltas: captionDeltas } = buildCaptionLayers(\n transcript,\n doc.canvas,\n options,\n );\n const captionLayerIds = new Set(captionLayers.map((l) => l.id));\n\n // Pick the target state for caption deltas: prefer \"default\", else first\n const stateNames = Object.keys(doc.states);\n const targetStateName = stateNames.includes(\"default\") ? \"default\" : stateNames[0];\n const states = { ...doc.states };\n\n if (targetStateName && states[targetStateName]) {\n const existing = states[targetStateName];\n // Drop deltas on caption layers we're rewriting; keep all others\n const preservedDeltas = existing.deltas.filter(\n (d) => !captionLayerIds.has(d.layer),\n );\n states[targetStateName] = {\n ...existing,\n deltas: [...preservedDeltas, ...captionDeltas],\n };\n }\n\n return {\n ...doc,\n layers: [...preserved, ...captionLayers],\n states,\n };\n}\n\n// ─── internals ───────────────────────────────────────────────────\n\nfunction buildPhraseLayer(\n id: string,\n phrase: CaptionPhrase,\n canvas: AtelierDocument[\"canvas\"],\n style: Required<CaptionStyle>,\n): Layer {\n return {\n id,\n tags: [\"caption\"],\n visual: {\n type: \"text\",\n content: phrase.text,\n style: {\n fontFamily: style.fontFamily,\n fontSize: style.fontSize,\n fontWeight: style.fontWeight,\n textAlign: style.textAlign,\n color: style.color,\n },\n },\n frame: {\n x: canvas.width / 2,\n y: canvas.height * style.yRatio,\n },\n bounds: {\n width: canvas.width * style.widthRatio,\n height: Math.max(120, style.fontSize * 1.6),\n },\n anchorPoint: { x: 0.5, y: 0.5 },\n opacity: 0,\n };\n}\n\nfunction buildPhraseDeltas(\n layerId: string,\n phrase: CaptionPhrase,\n fadeSeconds: number,\n fps: number,\n): Delta[] {\n const fadeFrames = Math.max(1, Math.round(fadeSeconds * fps));\n const startFrame = Math.floor(phrase.start * fps);\n const endFrame = Math.ceil(phrase.end * fps);\n const fadeOutStart = Math.max(startFrame + 1, endFrame - fadeFrames);\n\n return [\n // Fade in to visible at phrase start\n {\n layer: layerId,\n property: \"opacity\",\n range: [Math.max(0, startFrame - fadeFrames), startFrame],\n from: 0,\n to: 1,\n easing: \"ease-out\",\n },\n // Hold visible through the phrase\n // (no explicit delta needed — value persists between deltas)\n // Fade out at phrase end\n {\n layer: layerId,\n property: \"opacity\",\n range: [fadeOutStart, endFrame],\n from: 1,\n to: 0,\n easing: \"ease-in\",\n },\n ];\n}\n","import type { Command } from \"commander\";\nimport type { VideoTranscript } from \"@a-company/atelier-types\";\nimport {\n loadVideoProject,\n readTranscript,\n writeTranscript,\n readComposition,\n writeComposition,\n} from \"../lib/video-project.js\";\nimport {\n probeWhisper,\n runWhisperCpp,\n parseWhisperCppJson,\n type WhisperModel,\n} from \"../lib/whisper.js\";\nimport { mergeTranscriptWithExisting } from \"../lib/transcript-model.js\";\nimport { rewriteCaptionLayers, type BuildCaptionsOptions } from \"../lib/caption-builder.js\";\nimport { loadRecipe, applyRecipeToTranscribeOptions } from \"../lib/recipe.js\";\n\nexport interface TranscribeOptions {\n /** Whisper model selection */\n model?: WhisperModel;\n /** BCP-47 language hint (omit for autodetect) */\n language?: string;\n /** Discard existing user edits; full fresh transcript */\n reset?: boolean;\n /** Skip caption layer generation; transcript.json only */\n noCaptions?: boolean;\n /** Don't write files; return result */\n dryRun?: boolean;\n /** Caption style + grouping overrides, typically supplied by a Studio Recipe */\n captionOptions?: BuildCaptionsOptions;\n}\n\nexport interface TranscribeResult {\n projectDir: string;\n backend: string;\n transcript: VideoTranscript;\n wordCount: number;\n captionsGenerated: boolean;\n}\n\n/**\n * Run the transcription pipeline on a VideoProject folder.\n *\n * Pipeline:\n * 1. Probe Whisper backend (whisper-cpp / openai-api / none)\n * 2. Run Whisper → raw transcript JSON\n * 3. Parse into VideoTranscript shape\n * 4. Merge with existing transcript (preserves user edits) unless --reset\n * 5. Write transcript.json\n * 6. Unless --no-captions: rewriteCaptionLayers in project.atelier\n */\nexport async function transcribeProject(\n projectDir: string,\n options: TranscribeOptions = {},\n): Promise<TranscribeResult> {\n const project = loadVideoProject(projectDir);\n\n const backend = await probeWhisper();\n if (backend === \"none\") {\n throw new Error(\n \"No Whisper backend available. Install whisper.cpp (brew install whisper-cpp) \" +\n \"or set OPENAI_API_KEY and pass --use-api.\",\n );\n }\n if (backend === \"openai-api\") {\n // Reserved for the --use-api opt-in path; not implemented in this milestone\n throw new Error(\n \"OpenAI API backend is not yet implemented. Install whisper.cpp for local transcription.\",\n );\n }\n\n const rawJson = await runWhisperCpp(project.sourcePath, {\n model: options.model,\n language: options.language,\n });\n let transcript = parseWhisperCppJson(rawJson);\n\n // Re-run preservation — keep user edits on matching detected words\n if (!options.reset) {\n const existing = readTranscript(project);\n if (existing) {\n transcript = mergeTranscriptWithExisting(transcript, existing);\n }\n }\n\n const wordCount = transcript.segments.reduce((n, s) => n + s.words.length, 0);\n\n const result: TranscribeResult = {\n projectDir: project.dir,\n backend,\n transcript,\n wordCount,\n captionsGenerated: false,\n };\n\n if (options.dryRun) return result;\n\n writeTranscript(project, transcript);\n\n if (!options.noCaptions) {\n const doc = readComposition(project);\n const updated = rewriteCaptionLayers(doc, transcript, options.captionOptions);\n writeComposition(project, updated);\n result.captionsGenerated = true;\n }\n\n return result;\n}\n\nfunction formatResult(result: TranscribeResult): string {\n const lines: string[] = [];\n lines.push(`Transcribed ${result.projectDir} via ${result.backend}`);\n if (result.transcript.language) {\n lines.push(` language: ${result.transcript.language}`);\n }\n lines.push(` segments: ${result.transcript.segments.length}`);\n lines.push(` words: ${result.wordCount}`);\n if (result.captionsGenerated) {\n lines.push(` captions: written to project.atelier`);\n } else {\n lines.push(` captions: skipped`);\n }\n return lines.join(\"\\n\");\n}\n\n/** Register `atelier transcribe` on the Commander program */\nexport function transcribeCommand(program: Command): void {\n program\n .command(\"transcribe <project>\")\n .description(\n \"Transcribe source video via Whisper, write transcript.json, and \" +\n \"rewrite caption-tagged TextVisual layers in project.atelier. \" +\n \"Preserves user transcript edits on re-run.\",\n )\n .option(\"--model <name>\", \"Whisper model: tiny|base|small|medium|large-v3\", \"base.en\")\n .option(\"--language <code>\", \"BCP-47 language hint (omit for autodetect)\")\n .option(\"--reset\", \"Discard existing user edits; full fresh transcript\")\n .option(\"--no-captions\", \"Write transcript.json only; skip caption layer generation\")\n .option(\"--recipe <name>\", \"Apply a Studio Recipe's caption_style + caption_grouping\")\n .option(\"--dry-run\", \"Print transcript; don't write files\")\n .option(\"--json\", \"Output result as JSON for piping\")\n .action(async (\n project: string,\n opts: {\n model: WhisperModel;\n language?: string;\n reset?: boolean;\n captions: boolean;\n recipe?: string;\n dryRun?: boolean;\n json?: boolean;\n },\n ) => {\n try {\n let transcribeOpts: TranscribeOptions = {\n model: opts.model,\n language: opts.language,\n reset: opts.reset,\n noCaptions: !opts.captions,\n dryRun: opts.dryRun,\n };\n if (opts.recipe) {\n const { recipe } = loadRecipe(opts.recipe, project);\n transcribeOpts = applyRecipeToTranscribeOptions(recipe, transcribeOpts);\n }\n const result = await transcribeProject(project, transcribeOpts);\n if (opts.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log(formatResult(result));\n if (opts.dryRun) console.log(\"(dry-run — no files written)\");\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(`atelier transcribe: ${msg}`);\n process.exit(1);\n }\n });\n}\n","import type { Command } from \"commander\";\nimport type { VideoTranscript } from \"@a-company/atelier-types\";\nimport {\n loadVideoProject,\n readTranscript,\n writeTranscript,\n readComposition,\n writeComposition,\n} from \"../lib/video-project.js\";\nimport {\n applyTextEdit,\n applyBatchReplace,\n applyHide,\n applyAdd,\n applyMerge,\n applySplit,\n flattenWords,\n} from \"../lib/transcript-model.js\";\nimport { rewriteCaptionLayers } from \"../lib/caption-builder.js\";\n\n/** Read the project's transcript; throws if none exists */\nfunction loadOrThrow(projectDir: string): { project: ReturnType<typeof loadVideoProject>; transcript: VideoTranscript } {\n const project = loadVideoProject(projectDir);\n const transcript = readTranscript(project);\n if (!transcript) {\n throw new Error(\n `No transcript.json in ${projectDir}. Run \\`atelier transcribe ${projectDir}\\` first.`,\n );\n }\n return { project, transcript };\n}\n\n/** Save the transcript and optionally regenerate caption layers */\nfunction save(\n project: ReturnType<typeof loadVideoProject>,\n transcript: VideoTranscript,\n noRegenerate: boolean,\n): void {\n writeTranscript(project, transcript);\n if (!noRegenerate) {\n const doc = readComposition(project);\n const updated = rewriteCaptionLayers(doc, transcript);\n writeComposition(project, updated);\n }\n}\n\n/** Register the `atelier transcript` family of edit subcommands */\nexport function transcriptCommand(program: Command): void {\n const transcript = program\n .command(\"transcript\")\n .description(\"Edit transcript.json — fix, add, delete, merge, split, list\");\n\n transcript\n .command(\"fix <project>\")\n .description(\"Apply text correction(s). Use --replace 'wrong=right' for batch, or --word <idx> --text '<correction>' for single edit.\")\n .option(\"--replace <pair...>\", \"Batch find/replace, format: 'detected=replacement' (repeatable)\")\n .option(\"--word <index>\", \"Single-word edit by index\", (v) => parseInt(v, 10))\n .option(\"--text <text>\", \"Correction text (paired with --word)\")\n .option(\"--no-regenerate\", \"Skip caption layer regeneration after edit\")\n .action(async (\n projectDir: string,\n opts: { replace?: string[]; word?: number; text?: string; regenerate: boolean },\n ) => {\n try {\n const { project, transcript } = loadOrThrow(projectDir);\n let updated = transcript;\n\n if (opts.replace?.length) {\n for (const pair of opts.replace) {\n const [find, repl] = pair.split(\"=\");\n if (!find || repl === undefined) {\n throw new Error(`Invalid --replace pair: \"${pair}\". Use 'detected=replacement'.`);\n }\n updated = applyBatchReplace(updated, find, repl);\n }\n }\n\n if (typeof opts.word === \"number\") {\n if (opts.text === undefined) {\n throw new Error(\"--word requires --text <correction>\");\n }\n updated = applyTextEdit(updated, opts.word, opts.text);\n }\n\n if (!opts.replace?.length && opts.word === undefined) {\n throw new Error(\"Provide --replace 'wrong=right' or --word <idx> --text '...'\");\n }\n\n save(project, updated, !opts.regenerate);\n console.log(`Updated transcript in ${project.dir}`);\n } catch (err) {\n console.error(`atelier transcript fix: ${err instanceof Error ? err.message : err}`);\n process.exit(1);\n }\n });\n\n transcript\n .command(\"add <project>\")\n .description(\"Insert a user-added word after the anchor word.\")\n .requiredOption(\"--after-word <index>\", \"Anchor word index\", (v) => parseInt(v, 10))\n .requiredOption(\"--text <text>\", \"Text of the new word\")\n .option(\"--duration <seconds>\", \"Word duration in seconds (default: 0.15)\", (v) => parseFloat(v), 0.15)\n .option(\"--no-regenerate\", \"Skip caption layer regeneration\")\n .action(async (\n projectDir: string,\n opts: { afterWord: number; text: string; duration: number; regenerate: boolean },\n ) => {\n try {\n const { project, transcript } = loadOrThrow(projectDir);\n const updated = applyAdd(transcript, opts.afterWord, opts.text, opts.duration);\n save(project, updated, !opts.regenerate);\n console.log(`Inserted \"${opts.text}\" after word ${opts.afterWord} in ${project.dir}`);\n } catch (err) {\n console.error(`atelier transcript add: ${err instanceof Error ? err.message : err}`);\n process.exit(1);\n }\n });\n\n transcript\n .command(\"delete <project>\")\n .description(\"Hide a word (excluded from captions, kept in transcript).\")\n .requiredOption(\"--word <index>\", \"Word index\", (v) => parseInt(v, 10))\n .option(\"--no-regenerate\", \"Skip caption layer regeneration\")\n .action(async (\n projectDir: string,\n opts: { word: number; regenerate: boolean },\n ) => {\n try {\n const { project, transcript } = loadOrThrow(projectDir);\n const updated = applyHide(transcript, opts.word);\n save(project, updated, !opts.regenerate);\n console.log(`Hidden word ${opts.word} in ${project.dir}`);\n } catch (err) {\n console.error(`atelier transcript delete: ${err instanceof Error ? err.message : err}`);\n process.exit(1);\n }\n });\n\n transcript\n .command(\"merge <project>\")\n .description(\"Merge two adjacent words at indices i and i+1.\")\n .requiredOption(\"--word <index>\", \"First of the two words to merge\", (v) => parseInt(v, 10))\n .option(\"--no-regenerate\", \"Skip caption layer regeneration\")\n .action(async (\n projectDir: string,\n opts: { word: number; regenerate: boolean },\n ) => {\n try {\n const { project, transcript } = loadOrThrow(projectDir);\n const updated = applyMerge(transcript, opts.word);\n save(project, updated, !opts.regenerate);\n console.log(`Merged words ${opts.word} and ${opts.word + 1} in ${project.dir}`);\n } catch (err) {\n console.error(`atelier transcript merge: ${err instanceof Error ? err.message : err}`);\n process.exit(1);\n }\n });\n\n transcript\n .command(\"split <project>\")\n .description(\"Split one word at a fractional point.\")\n .requiredOption(\"--word <index>\", \"Word to split\", (v) => parseInt(v, 10))\n .requiredOption(\"--at <fraction>\", \"Split point (0–1)\", (v) => parseFloat(v))\n .option(\"--first <text>\", \"Override text for first half\")\n .option(\"--second <text>\", \"Override text for second half\")\n .option(\"--no-regenerate\", \"Skip caption layer regeneration\")\n .action(async (\n projectDir: string,\n opts: { word: number; at: number; first?: string; second?: string; regenerate: boolean },\n ) => {\n try {\n const { project, transcript } = loadOrThrow(projectDir);\n const updated = applySplit(transcript, opts.word, opts.at, opts.first, opts.second);\n save(project, updated, !opts.regenerate);\n console.log(`Split word ${opts.word} at ${opts.at} in ${project.dir}`);\n } catch (err) {\n console.error(`atelier transcript split: ${err instanceof Error ? err.message : err}`);\n process.exit(1);\n }\n });\n\n transcript\n .command(\"list <project>\")\n .description(\"Print all words with their indices for reference.\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (projectDir: string, opts: { json?: boolean }) => {\n try {\n const { transcript } = loadOrThrow(projectDir);\n const words = flattenWords(transcript);\n if (opts.json) {\n console.log(JSON.stringify(words.map((w, i) => ({ index: i, ...w })), null, 2));\n } else {\n for (let i = 0; i < words.length; i++) {\n const w = words[i];\n const flags: string[] = [];\n if (w.userEdited) flags.push(\"edited\");\n if (w.userAdded) flags.push(\"added\");\n if (w.hidden) flags.push(\"hidden\");\n const flagStr = flags.length ? ` [${flags.join(\", \")}]` : \"\";\n const editedDisplay = w.text !== w.detected ? ` ← \"${w.detected}\"` : \"\";\n console.log(\n ` [${i.toString().padStart(4)}] ${w.start.toFixed(2).padStart(7)}s ` +\n `\"${w.text}\"${editedDisplay}${flagStr}`,\n );\n }\n }\n } catch (err) {\n console.error(`atelier transcript list: ${err instanceof Error ? err.message : err}`);\n process.exit(1);\n }\n });\n}\n","import type { Command } from \"commander\";\nimport {\n loadVideoProject,\n readTranscript,\n readComposition,\n writeComposition,\n} from \"../lib/video-project.js\";\nimport { rewriteCaptionLayers } from \"../lib/caption-builder.js\";\nimport { loadRecipe, applyRecipeToCaptionOptions } from \"../lib/recipe.js\";\n\n/** Register `atelier captions regenerate <project>` */\nexport function captionsCommand(program: Command): void {\n const captions = program.command(\"captions\").description(\"Manage caption layers in a VideoProject\");\n\n captions\n .command(\"regenerate <project>\")\n .description(\n \"Re-derive caption-tagged TextVisual layers from the current transcript.json. \" +\n \"Used when caption styling changes without re-running Whisper.\",\n )\n .option(\"--recipe <name>\", \"Apply a Studio Recipe's caption_style + caption_grouping\")\n .action(async (projectDir: string, opts: { recipe?: string }) => {\n try {\n const project = loadVideoProject(projectDir);\n const transcript = readTranscript(project);\n if (!transcript) {\n throw new Error(\n `No transcript.json in ${projectDir}. Run \\`atelier transcribe ${projectDir}\\` first.`,\n );\n }\n const captionOptions = opts.recipe\n ? applyRecipeToCaptionOptions(loadRecipe(opts.recipe, projectDir).recipe)\n : {};\n const doc = readComposition(project);\n const updated = rewriteCaptionLayers(doc, transcript, captionOptions);\n writeComposition(project, updated);\n const captionLayers = updated.layers.filter((l) =>\n (l.tags ?? []).includes(\"caption\"),\n );\n console.log(\n `Regenerated ${captionLayers.length} caption layer${captionLayers.length === 1 ? \"\" : \"s\"} in ${project.dir}`,\n );\n } catch (err) {\n console.error(`atelier captions regenerate: ${err instanceof Error ? err.message : err}`);\n process.exit(1);\n }\n });\n}\n","import { writeFileSync, existsSync, mkdirSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport type { Command } from \"commander\";\nimport {\n loadRecipe,\n scaffoldRecipeYaml,\n renderRecipeWithDefaults,\n recipeToYaml,\n} from \"../lib/recipe.js\";\n\n/** Register `atelier recipe new/validate/show` family */\nexport function recipeCommand(program: Command): void {\n const recipe = program.command(\"recipe\").description(\"Manage Studio Recipes — reusable style presets\");\n\n recipe\n .command(\"new <name>\")\n .description(\"Scaffold a starter recipe YAML with all current defaults filled in\")\n .option(\"--dir <path>\", \"Where to write the recipe (default: ./.atelier/recipes/)\")\n .action((name: string, opts: { dir?: string }) => {\n try {\n const baseDir = opts.dir ?? join(resolve(process.cwd()), \".atelier\", \"recipes\");\n if (!existsSync(baseDir)) {\n mkdirSync(baseDir, { recursive: true });\n }\n // Footgun guard: if the name already carries a recognized extension,\n // treat it as a filename so `recipe new foo.recipe.yaml` doesn't\n // produce `foo.recipe.yaml.recipe.yaml`. Otherwise append the canonical\n // extension. The bare-name stem (without ext) is what `recipe validate\n // <name>` resolves, so they stay in agreement.\n const hasKnownExt = /\\.(recipe\\.yaml|recipe\\.json|yaml|yml|json)$/i.test(name);\n const fileName = hasKnownExt ? name : `${name}.recipe.yaml`;\n const outPath = join(baseDir, fileName);\n if (existsSync(outPath)) {\n throw new Error(`Recipe already exists at ${outPath} — refusing to overwrite.`);\n }\n const recipeName = name.replace(/\\.(recipe\\.yaml|recipe\\.json|yaml|yml|json)$/i, \"\");\n const yaml = scaffoldRecipeYaml(recipeName);\n writeFileSync(outPath, yaml, \"utf-8\");\n console.log(`Created ${outPath}`);\n } catch (err) {\n console.error(`atelier recipe new: ${err instanceof Error ? err.message : err}`);\n process.exit(1);\n }\n });\n\n recipe\n .command(\"validate <path>\")\n .description(\"Validate a recipe against the schema (^valid-recipe gate). Warns on reserved Phase 3 fields.\")\n .option(\"--json\", \"Output result as JSON\")\n .action((path: string, opts: { json?: boolean }) => {\n try {\n // Resolve a bare name against the project-local recipes dir first\n // (where `recipe new` writes), then the user library — so new/validate\n // agree on where a bare name lives.\n const loaded = loadRecipe(path, process.cwd());\n if (opts.json) {\n console.log(JSON.stringify({\n valid: true,\n path: loaded.path,\n warnings: loaded.warnings,\n }, null, 2));\n } else {\n console.log(`PASS ${loaded.path}`);\n for (const w of loaded.warnings) {\n console.log(` ⚠ ${w}`);\n }\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (opts.json) {\n console.log(JSON.stringify({ valid: false, error: msg }, null, 2));\n } else {\n console.error(`FAIL ${path}`);\n console.error(` ${msg}`);\n }\n process.exit(1);\n }\n });\n\n recipe\n .command(\"show <path>\")\n .description(\"Print a recipe; --with-defaults fills in every omitted field with its code default.\")\n .option(\"--with-defaults\", \"Overlay code defaults onto omitted fields\")\n .action((path: string, opts: { withDefaults?: boolean }) => {\n try {\n // Same project-local-first resolution as `recipe validate`.\n const loaded = loadRecipe(path, process.cwd());\n const out = opts.withDefaults ? renderRecipeWithDefaults(loaded.recipe) : loaded.recipe;\n console.log(recipeToYaml(out));\n for (const w of loaded.warnings) {\n console.error(`# ⚠ ${w}`);\n }\n } catch (err) {\n console.error(`atelier recipe show: ${err instanceof Error ? err.message : err}`);\n process.exit(1);\n }\n });\n}\n","import type { Command } from \"commander\";\nimport { trimProject } from \"./trim.js\";\nimport { transcribeProject } from \"./transcribe.js\";\nimport {\n loadRecipe,\n applyRecipeToTrimOptions,\n applyRecipeToTranscribeOptions,\n applyRecipeToOverlay,\n} from \"../lib/recipe.js\";\nimport {\n loadVideoProject,\n readComposition,\n writeComposition,\n} from \"../lib/video-project.js\";\n\n/**\n * Register `atelier apply-recipe <project> <recipe>` — convenience verb that\n * runs `atelier trim` and `atelier transcribe` against the same recipe in\n * one shot. Useful for fresh-project bootstrap.\n */\nexport function applyRecipeCommand(program: Command): void {\n program\n .command(\"apply-recipe <project> <recipe>\")\n .description(\n \"Apply a Studio Recipe by running atelier trim + atelier transcribe \" +\n \"with the same recipe, in that order.\",\n )\n .option(\"--reset\", \"Apply --reset to both pipelines (destructive — discards existing user padding and transcript edits)\")\n .option(\"--no-trim\", \"Skip the atelier trim step\")\n .option(\"--no-transcribe\", \"Skip the atelier transcribe step\")\n .action(async (\n project: string,\n recipeRef: string,\n opts: { reset?: boolean; trim: boolean; transcribe: boolean },\n ) => {\n try {\n const { recipe, path, warnings } = loadRecipe(recipeRef, project);\n console.log(`Loaded recipe ${path}`);\n for (const w of warnings) console.log(` ⚠ ${w}`);\n\n if (opts.trim) {\n const trimOpts = applyRecipeToTrimOptions(recipe, { reset: opts.reset });\n console.log(`\\nRunning atelier trim...`);\n const r = await trimProject(project, trimOpts);\n console.log(` ${r.cuts.length} cut${r.cuts.length === 1 ? \"\" : \"s\"} written`);\n }\n\n if (opts.transcribe) {\n const transcribeOpts = applyRecipeToTranscribeOptions(recipe, { reset: opts.reset });\n console.log(`\\nRunning atelier transcribe...`);\n const r = await transcribeProject(project, transcribeOpts);\n console.log(` ${r.wordCount} words, ${r.captionsGenerated ? \"captions written\" : \"captions skipped\"}`);\n }\n\n // Overlay translator — rewrites \"overlay\"-tagged layers in project.atelier\n // from recipe.overlay_rules. Single-frame apply: no carousel ctx, so\n // page_number is silently skipped (handle is always applied if present).\n if (recipe.overlay_rules) {\n const vp = loadVideoProject(project);\n const doc = readComposition(vp);\n const updated = applyRecipeToOverlay(doc, recipe);\n writeComposition(vp, updated);\n console.log(`\\nApplied overlay rules to ${vp.compositionPath}`);\n }\n\n console.log(`\\nDone.`);\n } catch (err) {\n console.error(`atelier apply-recipe: ${err instanceof Error ? err.message : err}`);\n process.exit(1);\n }\n });\n}\n","/**\n * Shared single-frame render-to-PNG path.\n *\n * Extracted from `atelier export-image` so the carousel batch driver and the\n * single-frame export command render through one code path. Rasterizes via\n * `@napi-rs/canvas` — a Canvas2D implementation shipped as prebuilt platform\n * binaries, so PNG export works on a plain install with no node-gyp build and\n * no system libraries (cairo/pango/etc.). Pre-loads any ImageVisual layers via\n * its `loadImage` (file path / data-URL / buffer all work server-side, the same\n * mechanism the MP4 render-pipeline uses) and renders one resolved frame scaled\n * to the requested output dimensions.\n */\n\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport { resolveFrame } from \"@a-company/atelier-core\";\nimport { createCanvas, loadImage } from \"@napi-rs/canvas\";\n\n/** @napi-rs/canvas surface — the subset this module touches. */\ninterface NodeCanvas {\n getContext(id: \"2d\"): unknown;\n toBuffer(format: \"image/png\"): Buffer;\n}\n\n/** A loaded image — width/height are the natural pixel dims. */\nexport interface LoadedImage {\n width: number;\n height: number;\n}\n\n/** Canvas module surface (createCanvas + loadImage). */\ninterface CanvasModule {\n createCanvas: (w: number, h: number) => NodeCanvas;\n loadImage: (src: string) => Promise<LoadedImage>;\n}\n\n/** Bounds + centered frame for fitting an image into a canvas. */\nexport interface ImageFitResult {\n bounds: { width: number; height: number };\n frame: { x: number; y: number };\n}\n\n/**\n * Fit a natural-sized image into a canvas while preserving aspect ratio,\n * centered. Adapted from studio's image-drop helper (kept local so the CLI's\n * server-side render path doesn't import the browser studio package).\n *\n * Landscape (wider than canvas) → fit to width; portrait (taller or equal) →\n * fit to height; both dims capped at the canvas extents. Degenerate natural\n * sizes fall back to canvas extents so callers always get valid bounds.\n */\nexport function fitImageToCanvas(\n canvas: { width: number; height: number },\n natural: { width: number; height: number },\n): ImageFitResult {\n const cw = canvas.width;\n const ch = canvas.height;\n const iw = natural.width;\n const ih = natural.height;\n\n if (!iw || !ih) {\n return { bounds: { width: cw, height: ch }, frame: { x: cw / 2, y: ch / 2 } };\n }\n\n const imageAspect = iw / ih;\n const canvasAspect = cw / ch;\n\n let width: number;\n let height: number;\n if (imageAspect > canvasAspect) {\n width = cw;\n height = cw / imageAspect;\n } else {\n height = ch;\n width = ch * imageAspect;\n }\n width = Math.min(width, cw);\n height = Math.min(height, ch);\n\n return { bounds: { width, height }, frame: { x: cw / 2, y: ch / 2 } };\n}\n\n/**\n * Raised when the `@napi-rs/canvas` rasterizer cannot be loaded. In practice\n * this never fires: `@napi-rs/canvas` is a hard dependency that ships prebuilt\n * platform binaries (no node-gyp, no system libraries). It can only happen if\n * the install is corrupt or running on an unsupported platform with no prebuilt\n * binary — in which case a reinstall is the fix. Kept as a typed seam so call\n * sites can still distinguish a missing-rasterizer failure from a bad document.\n */\nexport class CanvasUnavailableError extends Error {\n constructor() {\n super(\n \"The '@napi-rs/canvas' rasterizer could not be loaded.\\n\" +\n \"This package ships prebuilt platform binaries — no system libraries needed.\\n\" +\n \"Try reinstalling dependencies (e.g. `npm install`) to fetch the binary for this platform.\",\n );\n this.name = \"CanvasUnavailableError\";\n }\n}\n\n/**\n * Resolve the canvas module. `@napi-rs/canvas` is a hard, statically-imported\n * dependency, so this is a thin accessor that surfaces a typed\n * {@link CanvasUnavailableError} on the (essentially impossible) chance the\n * platform binary failed to load.\n */\nexport async function loadCanvasModule(): Promise<CanvasModule> {\n if (typeof createCanvas !== \"function\" || typeof loadImage !== \"function\") {\n throw new CanvasUnavailableError();\n }\n return {\n createCanvas: createCanvas as unknown as CanvasModule[\"createCanvas\"],\n loadImage: loadImage as unknown as CanvasModule[\"loadImage\"],\n };\n}\n\n/**\n * Compute final output dimensions from the document canvas and optional\n * width/height overrides. When only one of width/height is provided, the\n * other is derived to preserve the document's aspect ratio. When both are\n * provided, both are used verbatim (allows non-uniform scaling).\n */\nexport function resolveExportDimensions(\n docWidth: number,\n docHeight: number,\n width?: number,\n height?: number,\n): { width: number; height: number } {\n if (width !== undefined && height !== undefined) {\n return { width, height };\n }\n if (width !== undefined) {\n const h = Math.max(1, Math.round((width * docHeight) / docWidth));\n return { width, height: h };\n }\n if (height !== undefined) {\n const w = Math.max(1, Math.round((height * docWidth) / docHeight));\n return { width: w, height };\n }\n return { width: docWidth, height: docHeight };\n}\n\n/**\n * Build an {@link ImageCache} pre-populated with every ImageVisual source in\n * the document. Mirrors render-pipeline.ts: load each source with\n * `loadImage`, then wire a synchronous-from-cache `createImage` so the renderer\n * resolves images immediately. Returns the cache plus a map of src → loaded\n * image so callers can read natural dimensions.\n */\nasync function preloadImages(\n doc: AtelierDocument,\n loadImage: (src: string) => Promise<LoadedImage>,\n): Promise<{\n imageCache: import(\"@a-company/atelier-canvas\").ImageCache;\n loaded: Map<string, LoadedImage>;\n}> {\n const { ImageCache } = await import(\"@a-company/atelier-canvas\");\n\n const sources = new Set<string>();\n for (const layer of doc.layers) {\n if (layer.visual.type === \"image\") {\n const iv = layer.visual as { src?: string; assetId?: string };\n if (iv.src) sources.add(iv.src);\n else if (iv.assetId && doc.assets?.[iv.assetId]) sources.add(doc.assets[iv.assetId].src);\n }\n }\n\n if (sources.size === 0) {\n return { imageCache: new ImageCache(), loaded: new Map() };\n }\n\n const preloaded = new Map<string, LoadedImage>();\n await Promise.all(\n [...sources].map(async (src) => {\n try {\n preloaded.set(src, await loadImage(src));\n } catch {\n // Sources that fail to load render blank — same tolerance as render-pipeline.\n }\n }),\n );\n\n const imageCache = new ImageCache({\n createImage: (src, onLoad, onError) => {\n const img = preloaded.get(src);\n if (img) {\n process.nextTick(onLoad);\n return img;\n }\n process.nextTick(onError);\n return {};\n },\n });\n for (const src of preloaded.keys()) imageCache.load(src);\n await new Promise<void>((resolve) => process.nextTick(resolve));\n\n return { imageCache, loaded: preloaded };\n}\n\nexport interface RenderToPngOptions {\n /** State to resolve (defaults to the first state). */\n state?: string;\n /** Frame within the state (defaults to 0). */\n frame?: number;\n /** Output width override (px). */\n width?: number;\n /** Output height override (px). */\n height?: number;\n /**\n * Optional hook to adjust each image layer's bounds once natural dimensions\n * are known from the loaded image. Receives the layer src + natural dims and\n * the doc canvas; returns new bounds (and frame). Used by the carousel driver\n * to aspect-fit fit-to-canvas images that were composed with placeholder\n * bounds (natural dims are unknown until the rasterizer decodes the file).\n */\n refitImageBounds?: (args: {\n canvas: { width: number; height: number };\n natural: { width: number; height: number };\n }) => { bounds: { width: number; height: number }; frame: { x: number; y: number } };\n}\n\n/**\n * Render a single resolved frame of a document to a PNG buffer.\n *\n * Validates state/frame, pre-loads image layers, scales rendering to fit the\n * requested output dimensions, and returns the encoded PNG bytes. Throws\n * {@link CanvasUnavailableError} when the rasterizer is missing and a plain\n * Error for bad state/frame selection.\n */\nexport async function renderDocumentToPng(\n doc: AtelierDocument,\n opts: RenderToPngOptions = {},\n): Promise<Buffer> {\n const stateNames = Object.keys(doc.states);\n if (stateNames.length === 0) {\n throw new Error(\"Document has no states\");\n }\n const stateName = opts.state ?? stateNames[0];\n if (!doc.states[stateName]) {\n throw new Error(`State \"${stateName}\" not found. Available: ${stateNames.join(\", \")}`);\n }\n const frameNumber = opts.frame ?? 0;\n if (!Number.isInteger(frameNumber) || frameNumber < 0) {\n throw new Error(`Invalid frame number: ${frameNumber}`);\n }\n const duration = doc.states[stateName].duration;\n if (frameNumber >= duration) {\n throw new Error(\n `Frame ${frameNumber} is out of range for state \"${stateName}\" (duration ${duration})`,\n );\n }\n\n const { createCanvas, loadImage } = await loadCanvasModule();\n const { renderFrame } = await import(\"@a-company/atelier-canvas\");\n\n const { imageCache, loaded } = await preloadImages(doc, loadImage);\n\n // Re-fit image layers now that natural dims are known (carousel path).\n let renderDoc = doc;\n if (opts.refitImageBounds && loaded.size > 0) {\n renderDoc = {\n ...doc,\n layers: doc.layers.map((layer) => {\n if (layer.visual.type !== \"image\") return layer;\n const iv = layer.visual as { src?: string; assetId?: string };\n const src = iv.src ?? (iv.assetId ? doc.assets?.[iv.assetId]?.src : undefined);\n const natural = src ? loaded.get(src) : undefined;\n if (!natural || !natural.width || !natural.height) return layer;\n const fit = opts.refitImageBounds!({ canvas: doc.canvas, natural });\n return { ...layer, bounds: fit.bounds, frame: fit.frame };\n }),\n };\n }\n\n const { width: outW, height: outH } = resolveExportDimensions(\n renderDoc.canvas.width,\n renderDoc.canvas.height,\n opts.width,\n opts.height,\n );\n\n const resolved = resolveFrame(renderDoc, stateName, frameNumber);\n const cvs = createCanvas(outW, outH);\n const ctx = cvs.getContext(\"2d\") as unknown as import(\"@a-company/atelier-canvas\").RenderContext;\n\n const sx = outW / renderDoc.canvas.width;\n const sy = outH / renderDoc.canvas.height;\n if (sx !== 1 || sy !== 1) ctx.scale(sx, sy);\n\n renderFrame(ctx, resolved, renderDoc, imageCache);\n\n return cvs.toBuffer(\"image/png\");\n}\n","import { readdirSync, mkdirSync, writeFileSync, statSync } from \"node:fs\";\nimport { resolve, join, basename, extname, dirname, sep } from \"node:path\";\nimport type { Command } from \"commander\";\nimport type { AtelierDocument, StudioRecipe } from \"@a-company/atelier-types\";\nimport { loadRecipe, applyRecipeToOverlay } from \"../lib/recipe.js\";\nimport {\n renderDocumentToPng,\n fitImageToCanvas,\n CanvasUnavailableError,\n} from \"../lib/render-image.js\";\n\n/** Image extensions the carousel driver accepts (lower-cased, with leading dot). */\nconst IMAGE_EXTS = new Set([\".png\", \".jpg\", \".jpeg\", \".webp\"]);\n\n/** Default canvas size when neither --width/--height nor a recipe aspect is set. */\nconst DEFAULT_CANVAS = 1080;\n\n/**\n * Expand an --inputs pattern into a sorted list of absolute image file paths.\n *\n * Deliberately minimal (no new glob dependency): supports a directory path\n * (lists all image files within), a single file path, or a single-segment\n * `*`-glob in the final path component (e.g. `shots/*.png`, `shots/img-*`).\n * Multi-segment / recursive globs are out of scope — point --inputs at a\n * directory instead. The returned list is filtered to image extensions and\n * sorted lexicographically so output ordering is stable.\n */\nexport function expandInputs(pattern: string): string[] {\n const abs = resolve(pattern);\n\n // Directory → every image file inside it.\n let isDir = false;\n try {\n isDir = statSync(abs).isDirectory();\n } catch {\n isDir = false;\n }\n if (isDir) {\n return listImages(abs);\n }\n\n const dir = dirname(abs);\n const base = basename(abs);\n\n // Single-segment `*` glob in the final component.\n if (base.includes(\"*\")) {\n const matcher = globToRegExp(base);\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return [];\n }\n return entries\n .filter((name) => matcher.test(name) && isImageFile(name))\n .map((name) => join(dir, name))\n .sort();\n }\n\n // Literal file path — keep it only if it is an image file.\n return isImageFile(base) ? [abs] : [];\n}\n\n/** List image files directly within a directory, sorted, as absolute paths. */\nfunction listImages(dir: string): string[] {\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return [];\n }\n return entries\n .filter(isImageFile)\n .map((name) => join(dir, name))\n .sort();\n}\n\n/** True when a filename has an accepted image extension. */\nfunction isImageFile(name: string): boolean {\n return IMAGE_EXTS.has(extname(name).toLowerCase());\n}\n\n/**\n * Convert a single path-component glob (only `*` and `?` honored) into a\n * RegExp anchored to the whole name. `*` matches any run except the path\n * separator; `?` matches a single non-separator char.\n */\nfunction globToRegExp(glob: string): RegExp {\n const escaped = glob.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const pattern = escaped.replace(/\\*/g, `[^${sep === \"\\\\\" ? \"\\\\\\\\\" : sep}]*`).replace(/\\?/g, \".\");\n return new RegExp(`^${pattern}$`);\n}\n\n/**\n * Build a single-frame carousel document for one image: a canvas-sized doc with\n * a background and one fit-to-canvas ImageVisual layer, then the recipe's\n * overlay_rules applied with currentIndex/totalCount threaded so the page-number\n * overlay renders \"i/N\".\n *\n * Pure + synchronous (no node-canvas): image bounds use the canvas-extent\n * fallback because natural dimensions aren't known until node-canvas decodes\n * the file at render time. {@link renderDocumentToPng} re-fits the bounds via\n * `refitImageBounds` once the image is loaded.\n */\nexport function composeCarouselFrameDoc(args: {\n imagePath: string;\n index: number;\n total: number;\n width: number;\n height: number;\n recipe: StudioRecipe;\n background?: string;\n}): AtelierDocument {\n const { imagePath, index, total, width, height, recipe } = args;\n const canvas = { width, height };\n\n // Natural dims unknown here → fitImageToCanvas falls back to canvas extents.\n const fit = fitImageToCanvas(canvas, { width: 0, height: 0 });\n\n const assetId = \"carousel-image-asset\";\n const baseDoc: AtelierDocument = {\n version: \"1.0\",\n name: `carousel-${index}`,\n canvas: { width, height, fps: 30, background: args.background ?? \"#000000\" },\n assets: { [assetId]: { type: \"image\", src: imagePath } },\n layers: [\n {\n id: \"carousel-image\",\n visual: { type: \"image\", assetId, src: imagePath },\n frame: fit.frame,\n bounds: fit.bounds,\n anchorPoint: { x: 0.5, y: 0.5 },\n opacity: 1,\n },\n ],\n states: { default: { duration: 1, deltas: [] } },\n };\n\n // Thread the carousel position so page_number resolves \"i/N\"; handle (if any)\n // is anchored on top of the image.\n return applyRecipeToOverlay(baseDoc, recipe, { currentIndex: index, totalCount: total });\n}\n\n/** Zero-padded sortable filename prefix: width = max(2, digits in N). */\nexport function carouselFileName(index: number, total: number, imagePath: string): string {\n const padWidth = Math.max(2, String(total).length);\n const prefix = String(index).padStart(padWidth, \"0\");\n const ext = extname(imagePath);\n const stem = basename(imagePath, ext);\n return `${prefix}-${stem}.png`;\n}\n\ninterface CarouselOptions {\n inputs: string;\n outDir: string;\n width?: string;\n height?: string;\n frame: string;\n}\n\n/** Parse a positive-integer CLI option, exiting on bad input. */\nfunction parseDim(raw: string | undefined, name: string): number | undefined {\n if (raw === undefined) return undefined;\n const n = parseInt(raw, 10);\n if (isNaN(n) || n <= 0) {\n console.error(`Invalid --${name}: ${raw}`);\n process.exit(1);\n }\n return n;\n}\n\n/**\n * Register `atelier carousel <recipe> --inputs <glob> --out-dir <dir>` — batch\n * compose a folder of images into recipe-overlaid PNGs.\n *\n * For each image i of N: build a fit-to-canvas doc, apply the recipe's\n * overlay_rules with currentIndex=i / totalCount=N (handle + \"i/N\" page-number),\n * render via the shared export-image path, and write a zero-padded sortable\n * PNG into --out-dir.\n */\nexport function carouselCommand(program: Command): void {\n program\n .command(\"carousel <recipe>\")\n .description(\n \"Batch-compose a folder of images into recipe-overlaid PNGs. \" +\n \"Each image becomes a fit-to-canvas post with the recipe's handle + \" +\n \"page-number ('i/N') overlays, written to --out-dir as zero-padded PNGs.\",\n )\n .requiredOption(\"-i, --inputs <glob>\", \"Input images: a directory, file, or single-segment *-glob\")\n .requiredOption(\"-d, --out-dir <dir>\", \"Destination directory for composed PNGs\")\n .option(\"--width <number>\", \"Canvas width (px)\", String(DEFAULT_CANVAS))\n .option(\"--height <number>\", \"Canvas height (px)\", String(DEFAULT_CANVAS))\n .option(\"-f, --frame <number>\", \"Frame to render (defaults to 0)\", \"0\")\n .action(async (recipeRef: string, options: CarouselOptions) => {\n // Resolve the recipe (same chain as other recipe commands).\n let recipe: StudioRecipe;\n try {\n const loaded = loadRecipe(recipeRef);\n recipe = loaded.recipe;\n console.log(`Loaded recipe ${loaded.path}`);\n for (const w of loaded.warnings) console.log(` ⚠ ${w}`);\n } catch (err) {\n console.error(`atelier carousel: ${err instanceof Error ? err.message : err}`);\n process.exit(1);\n return;\n }\n\n // Expand inputs.\n const inputs = expandInputs(options.inputs);\n if (inputs.length === 0) {\n console.error(\n `atelier carousel: no image files matched --inputs \"${options.inputs}\" ` +\n `(accepted: ${[...IMAGE_EXTS].join(\", \")})`,\n );\n process.exit(1);\n return;\n }\n\n const width = parseDim(options.width, \"width\") ?? DEFAULT_CANVAS;\n const height = parseDim(options.height, \"height\") ?? DEFAULT_CANVAS;\n const frame = parseInt(options.frame, 10);\n if (isNaN(frame) || frame < 0) {\n console.error(`Invalid frame number: ${options.frame}`);\n process.exit(1);\n return;\n }\n\n // Ensure the destination exists / is writable.\n const outDir = resolve(options.outDir);\n try {\n mkdirSync(outDir, { recursive: true });\n } catch (err) {\n console.error(`atelier carousel: cannot create out-dir ${outDir}: ${(err as Error).message}`);\n process.exit(1);\n return;\n }\n\n const total = inputs.length;\n console.log(`Composing ${total} image${total === 1 ? \"\" : \"s\"} → ${outDir}`);\n\n try {\n for (let n = 0; n < total; n++) {\n const index = n + 1; // 1-based\n const imagePath = inputs[n];\n const doc = composeCarouselFrameDoc({\n imagePath,\n index,\n total,\n width,\n height,\n recipe,\n });\n\n const buffer = await renderDocumentToPng(doc, {\n frame,\n // Re-fit the image to the canvas using real natural dims once decoded.\n refitImageBounds: ({ canvas, natural }) => fitImageToCanvas(canvas, natural),\n });\n\n const outName = carouselFileName(index, total, imagePath);\n writeFileSync(join(outDir, outName), buffer);\n console.log(` [${index}/${total}] ${basename(imagePath)} → ${outName}`);\n }\n } catch (err) {\n if (err instanceof CanvasUnavailableError) {\n console.error(err.message);\n process.exit(1);\n return;\n }\n console.error(`atelier carousel: ${err instanceof Error ? err.message : err}`);\n process.exit(1);\n return;\n }\n\n console.log(`\\nDone. ${total} image${total === 1 ? \"\" : \"s\"} → ${outDir}`);\n });\n}\n","import { readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { Command } from \"commander\";\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport { parseAtelier } from \"@a-company/atelier-schema\";\n\n/**\n * Info summary for an AtelierDocument.\n */\nexport interface DocumentInfo {\n name: string;\n description?: string;\n canvas: {\n width: number;\n height: number;\n fps: number;\n background?: string;\n };\n layers: {\n count: number;\n items: { id: string; type: string }[];\n };\n states: {\n count: number;\n items: { name: string; duration: number; deltaCount: number }[];\n };\n presets: {\n count: number;\n };\n}\n\n/**\n * Extract summary info from a parsed AtelierDocument.\n */\nexport function getInfo(doc: AtelierDocument): DocumentInfo {\n return {\n name: doc.name,\n description: doc.description,\n canvas: {\n width: doc.canvas.width,\n height: doc.canvas.height,\n fps: doc.canvas.fps,\n background: doc.canvas.background,\n },\n layers: {\n count: doc.layers.length,\n items: doc.layers.map((layer) => ({\n id: layer.id,\n type: layer.visual.type,\n })),\n },\n states: {\n count: Object.keys(doc.states).length,\n items: Object.entries(doc.states).map(([name, state]) => ({\n name,\n duration: state.duration,\n deltaCount: state.deltas.length,\n })),\n },\n presets: {\n count: doc.presets ? Object.keys(doc.presets).length : 0,\n },\n };\n}\n\n/**\n * Format a DocumentInfo for terminal output.\n */\nfunction formatInfo(info: DocumentInfo): string {\n const lines: string[] = [];\n\n lines.push(`Name: ${info.name}`);\n if (info.description) {\n lines.push(`Description: ${info.description}`);\n }\n\n const bg = info.canvas.background\n ? `, background: ${info.canvas.background}`\n : \"\";\n lines.push(\n `Canvas: ${info.canvas.width}x${info.canvas.height} @ ${info.canvas.fps}fps${bg}`,\n );\n\n lines.push(`Layers: ${info.layers.count}`);\n for (const layer of info.layers.items) {\n lines.push(` - ${layer.id} (${layer.type})`);\n }\n\n lines.push(`States: ${info.states.count}`);\n for (const state of info.states.items) {\n lines.push(\n ` - ${state.name}: ${state.duration} frames, ${state.deltaCount} deltas`,\n );\n }\n\n if (info.presets.count > 0) {\n lines.push(`Presets: ${info.presets.count}`);\n }\n\n return lines.join(\"\\n\");\n}\n\n/** Read and parse an .atelier file, exiting on failure. */\nfunction readAndParse(file: string): AtelierDocument {\n const absPath = resolve(file);\n let content: string;\n try {\n content = readFileSync(absPath, \"utf-8\");\n } catch {\n console.error(`Cannot read file: ${absPath}`);\n return process.exit(1);\n }\n\n const result = parseAtelier(content);\n if (!result.success) {\n console.error(\"Parse errors:\");\n for (const error of result.errors) {\n console.error(` - ${error.path}: ${error.message}`);\n }\n return process.exit(1);\n }\n\n return result.data;\n}\n\n/**\n * Register the `info` subcommand on the Commander program.\n */\nexport function infoCommand(program: Command): void {\n program\n .command(\"info <file>\")\n .description(\"Display summary info for an .atelier file\")\n .action((file: string) => {\n const doc = readAndParse(file);\n const info = getInfo(doc);\n console.log(formatInfo(info));\n });\n}\n","import { readFileSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { Command } from \"commander\";\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport { parseAtelier } from \"@a-company/atelier-schema\";\nimport { resolveFrame } from \"@a-company/atelier-core\";\nimport type { ResolvedFrame } from \"@a-company/atelier-core\";\n\n/**\n * Resolve a single frame from a document, returning the resolved frame data.\n * If stateName is not provided, uses the first state.\n * If frame is not provided, uses frame 0.\n */\nexport function resolveStill(\n doc: AtelierDocument,\n stateName?: string,\n frame?: number,\n): ResolvedFrame {\n const stateNames = Object.keys(doc.states);\n if (stateNames.length === 0) {\n throw new Error(\"Document has no states\");\n }\n\n const resolvedStateName = stateName ?? stateNames[0];\n if (!(resolvedStateName in doc.states)) {\n throw new Error(\n `State \"${resolvedStateName}\" not found. Available: ${stateNames.join(\", \")}`,\n );\n }\n\n const resolvedFrame = frame ?? 0;\n return resolveFrame(doc, resolvedStateName, resolvedFrame);\n}\n\n/** Read and parse an .atelier file, exiting on failure. */\nfunction readAndParse(file: string): AtelierDocument {\n const absPath = resolve(file);\n let content: string;\n try {\n content = readFileSync(absPath, \"utf-8\");\n } catch {\n console.error(`Cannot read file: ${absPath}`);\n return process.exit(1);\n }\n\n const result = parseAtelier(content);\n if (!result.success) {\n console.error(\"Parse errors:\");\n for (const error of result.errors) {\n console.error(` - ${error.path}: ${error.message}`);\n }\n return process.exit(1);\n }\n\n return result.data;\n}\n\n/**\n * Register the `still` subcommand on the Commander program.\n */\nexport function stillCommand(program: Command): void {\n program\n .command(\"still <file>\")\n .description(\n \"Resolve a single frame and output as JSON or render as PNG\",\n )\n .option(\"-s, --state <name>\", \"State name (defaults to first state)\")\n .option(\n \"-f, --frame <number>\",\n \"Frame number (defaults to 0)\",\n \"0\",\n )\n .option(\n \"--format <type>\",\n \"Output format: json | png (default: json)\",\n \"json\",\n )\n .option(\"-o, --output <path>\", \"Output file path (default: stdout)\")\n .action(\n async (\n file: string,\n options: { state?: string; frame: string; format: string; output?: string },\n ) => {\n const doc = readAndParse(file);\n\n const frameNumber = parseInt(options.frame, 10);\n if (isNaN(frameNumber) || frameNumber < 0) {\n console.error(\n `Invalid frame number: ${options.frame}`,\n );\n process.exit(1);\n return;\n }\n\n if (options.format !== \"json\" && options.format !== \"png\") {\n console.error(`Unknown format: \"${options.format}\". Use json or png.`);\n process.exit(1);\n return;\n }\n\n try {\n const resolved = resolveStill(\n doc,\n options.state,\n frameNumber,\n );\n\n if (options.format === \"json\") {\n const json = JSON.stringify(resolved, null, 2);\n if (options.output) {\n writeFileSync(resolve(options.output), json, \"utf-8\");\n } else {\n console.log(json);\n }\n } else {\n // PNG format — rasterize via @napi-rs/canvas (prebuilt platform\n // binaries; no node-gyp / system libraries, so PNG output works on\n // a plain install).\n const { createCanvas } = await import(\"@napi-rs/canvas\");\n const { renderFrame } = await import(\"@a-company/atelier-canvas\");\n\n const cvs = createCanvas(doc.canvas.width, doc.canvas.height);\n const ctx = cvs.getContext(\"2d\");\n renderFrame(ctx as unknown as import(\"@a-company/atelier-canvas\").RenderContext, resolved, doc);\n\n const buffer = cvs.toBuffer(\"image/png\");\n if (options.output) {\n writeFileSync(resolve(options.output), buffer);\n } else {\n process.stdout.write(buffer);\n }\n }\n } catch (err) {\n console.error(\n (err as Error).message,\n );\n process.exit(1);\n }\n },\n );\n}\n","/**\n * Core render pipeline — renders an Atelier document to MP4 or GIF via FFmpeg.\n * Pure pipeline with no Commander dependency; testable in isolation.\n */\n\nimport { spawn } from \"node:child_process\";\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport { resolveFrame } from \"@a-company/atelier-core\";\nimport { renderFrame, ImageCache } from \"@a-company/atelier-canvas\";\n\n// ─── Types ───────────────────────────────────────────────────\n\nexport type RenderFormat = \"mp4\" | \"gif\";\n\nexport interface RenderOptions {\n output: string;\n format: RenderFormat;\n states?: string[];\n onProgress?: (info: ProgressInfo) => void;\n}\n\nexport interface ProgressInfo {\n frame: number;\n totalFrames: number;\n state: string;\n percent: number;\n}\n\nexport interface RenderResult {\n output: string;\n format: RenderFormat;\n totalFrames: number;\n states: string[];\n durationMs: number;\n}\n\n// ─── FFmpeg Helpers ──────────────────────────────────────────\n\n/** Check whether FFmpeg is available on the system PATH. */\nexport async function checkFfmpeg(): Promise<boolean> {\n return new Promise((resolve) => {\n const proc = spawn(\"ffmpeg\", [\"-version\"], { stdio: \"pipe\" });\n proc.on(\"error\", () => resolve(false));\n proc.on(\"close\", (code) => resolve(code === 0));\n });\n}\n\n/** Build the FFmpeg argument array for the given format. Pure function. */\nexport function buildFfmpegArgs(\n width: number,\n height: number,\n fps: number,\n format: RenderFormat,\n output: string,\n): string[] {\n const input = [\n \"-y\",\n \"-f\", \"rawvideo\",\n \"-pix_fmt\", \"bgra\",\n \"-s\", `${width}x${height}`,\n \"-r\", String(fps),\n \"-i\", \"pipe:0\",\n ];\n\n if (format === \"mp4\") {\n return [\n ...input,\n \"-c:v\", \"libx264\",\n \"-pix_fmt\", \"yuv420p\",\n \"-preset\", \"medium\",\n \"-crf\", \"18\",\n \"-movflags\", \"+faststart\",\n output,\n ];\n }\n\n // GIF — single-pass palette generation (stdin-compatible)\n return [\n ...input,\n \"-vf\", \"split[s0][s1];[s0]palettegen=stats_mode=single[p];[s1][p]paletteuse=dither=sierra2_4a\",\n \"-loop\", \"0\",\n output,\n ];\n}\n\n// ─── Image Pre-loading ───────────────────────────────────────\n\n/**\n * Scan document layers for image visuals, pre-load them with node-canvas\n * loadImage, and return a populated ImageCache ready for rendering.\n */\nasync function preloadImages(\n doc: AtelierDocument,\n loadImage: (src: string) => Promise<unknown>,\n): Promise<ImageCache> {\n const sources = new Set<string>();\n\n for (const layer of doc.layers) {\n if (layer.visual.type === \"image\") {\n const iv = layer.visual as { src?: string; assetId?: string };\n if (iv.src) {\n sources.add(iv.src);\n } else if (iv.assetId && doc.assets?.[iv.assetId]) {\n sources.add(doc.assets[iv.assetId].src);\n }\n }\n }\n\n if (sources.size === 0) {\n return new ImageCache();\n }\n\n // Load all images in parallel\n const preloaded = new Map<string, unknown>();\n await Promise.all(\n [...sources].map(async (src) => {\n try {\n preloaded.set(src, await loadImage(src));\n } catch {\n // Images that fail to load will render as blank\n }\n }),\n );\n\n // Create ImageCache pre-populated with loaded images.\n // createImage returns the pre-loaded image and fires onLoad on next tick\n // so that the ImageCache internal `image` variable is assigned first.\n const imageCache = new ImageCache({\n createImage: (src, onLoad, onError) => {\n const img = preloaded.get(src);\n if (img) {\n process.nextTick(onLoad);\n return img;\n }\n process.nextTick(onError);\n return {};\n },\n });\n\n for (const src of preloaded.keys()) {\n imageCache.load(src);\n }\n\n // Wait for nextTick callbacks to populate the cache\n await new Promise<void>((resolve) => process.nextTick(resolve));\n\n return imageCache;\n}\n\n// ─── Main Render Loop ────────────────────────────────────────\n\n/**\n * Render an Atelier document to a video/GIF file via FFmpeg.\n * Dynamically imports `canvas` (node-canvas) — fails with a helpful\n * message if the native dependency is not installed.\n */\nexport async function renderDocument(\n doc: AtelierDocument,\n opts: RenderOptions,\n): Promise<RenderResult> {\n // Dynamic import — canvas requires native compilation.\n // Use a variable to avoid TypeScript resolving the module at compile time.\n const canvasModuleName = \"canvas\";\n let createCanvas: (w: number, h: number) => unknown;\n let loadImage: (src: string) => Promise<unknown>;\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const canvasModule = await import(/* webpackIgnore: true */ canvasModuleName);\n createCanvas = canvasModule.createCanvas;\n loadImage = canvasModule.loadImage;\n } catch {\n throw new Error(\n \"The 'canvas' package is not installed.\\n\" +\n \"Install it with:\\n\" +\n \" npm install canvas\\n\" +\n \"Prerequisites vary by OS:\\n\" +\n \" macOS: brew install pkg-config cairo pango libpng jpeg giflib librsvg pixman\\n\" +\n \" Ubuntu: sudo apt install build-essential libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev\\n\" +\n \"See: https://github.com/Automattic/node-canvas#compiling\",\n );\n }\n\n const { width, height, fps } = doc.canvas;\n const { output, format, states, onProgress } = opts;\n\n // H.264 requires even dimensions\n if (format === \"mp4\" && (width % 2 !== 0 || height % 2 !== 0)) {\n throw new Error(\n `H.264 requires even dimensions. Canvas is ${width}\\u00d7${height}. ` +\n `Try ${width + (width % 2)}\\u00d7${height + (height % 2)}.`,\n );\n }\n\n // Resolve which states to render\n const allStates = Object.keys(doc.states);\n const renderStates = states ?? allStates;\n for (const s of renderStates) {\n if (!(s in doc.states)) {\n throw new Error(\n `State \"${s}\" not found. Available: ${allStates.join(\", \")}`,\n );\n }\n }\n\n // Total frame count across all states\n let totalFrames = 0;\n for (const s of renderStates) {\n totalFrames += doc.states[s].duration;\n }\n\n if (totalFrames === 0) {\n throw new Error(\"Nothing to render \\u2014 all states have duration 0\");\n }\n\n // Pre-load images before the render loop\n const imageCache = await preloadImages(doc, loadImage);\n\n // Create node-canvas\n const canvas = createCanvas(width, height) as { getContext(id: \"2d\"): unknown; toBuffer(format: \"raw\"): Buffer };\n const ctx = canvas.getContext(\"2d\");\n\n // Spawn FFmpeg\n const ffmpegArgs = buildFfmpegArgs(width, height, fps, format, output);\n const ffmpeg = spawn(\"ffmpeg\", ffmpegArgs, {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n\n let stderrOutput = \"\";\n ffmpeg.stderr?.on(\"data\", (chunk: Buffer) => {\n stderrOutput += chunk.toString();\n });\n\n const startTime = Date.now();\n let frameIndex = 0;\n\n for (const stateName of renderStates) {\n const duration = doc.states[stateName].duration;\n for (let f = 0; f < duration; f++) {\n const resolved = resolveFrame(doc, stateName, f);\n renderFrame(ctx as never, resolved, doc, imageCache);\n\n const raw = canvas.toBuffer(\"raw\");\n const canWrite = ffmpeg.stdin!.write(raw);\n if (!canWrite) {\n await new Promise<void>((resolve) =>\n ffmpeg.stdin!.once(\"drain\", resolve),\n );\n }\n\n frameIndex++;\n onProgress?.({\n frame: frameIndex,\n totalFrames,\n state: stateName,\n percent: Math.round((frameIndex / totalFrames) * 100),\n });\n }\n }\n\n // Close stdin and wait for FFmpeg to exit\n ffmpeg.stdin!.end();\n\n const exitCode = await new Promise<number | null>((resolve) => {\n ffmpeg.on(\"close\", resolve);\n });\n\n if (exitCode !== 0) {\n throw new Error(\n `FFmpeg exited with code ${exitCode}.\\n${stderrOutput.slice(-500)}`,\n );\n }\n\n return {\n output,\n format,\n totalFrames,\n states: renderStates,\n durationMs: Date.now() - startTime,\n };\n}\n","/**\n * `atelier render <file>` — render an animation to MP4 or GIF via FFmpeg.\n *\n * Usage:\n * atelier render animation.atelier → animation.mp4\n * atelier render animation.atelier -f gif → animation.gif\n * atelier render animation.atelier -o out/video.mp4 → custom path\n * atelier render animation.atelier -s intro outro → specific states\n */\n\nimport { readFileSync } from \"node:fs\";\nimport { resolve, basename, extname } from \"node:path\";\nimport type { Command } from \"commander\";\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport { parseAtelier } from \"@a-company/atelier-schema\";\nimport {\n checkFfmpeg,\n renderDocument,\n type RenderFormat,\n} from \"./render-pipeline.js\";\n\n/** Read and parse an .atelier file, exiting on failure. */\nfunction readAndParse(file: string): AtelierDocument {\n const absPath = resolve(file);\n let content: string;\n try {\n content = readFileSync(absPath, \"utf-8\");\n } catch {\n console.error(`Cannot read file: ${absPath}`);\n return process.exit(1);\n }\n\n const result = parseAtelier(content);\n if (!result.success) {\n console.error(\"Parse errors:\");\n for (const error of result.errors) {\n console.error(` - ${error.path}: ${error.message}`);\n }\n return process.exit(1);\n }\n\n return result.data;\n}\n\nfunction inferFormat(output: string | undefined): RenderFormat {\n if (!output) return \"mp4\";\n const ext = extname(output).toLowerCase();\n if (ext === \".gif\") return \"gif\";\n return \"mp4\";\n}\n\n/** Register the `render` subcommand on the Commander program. */\nexport function renderCommand(program: Command): void {\n program\n .command(\"render <file>\")\n .description(\"Render animation to MP4 or GIF via FFmpeg\")\n .option(\"-o, --output <path>\", \"Output file path\")\n .option(\"-f, --format <type>\", \"Output format: mp4 | gif\")\n .option(\n \"-s, --state <names...>\",\n \"State(s) to render (default: all in order)\",\n )\n .action(\n async (\n file: string,\n options: {\n output?: string;\n format?: string;\n state?: string[];\n },\n ) => {\n // Check FFmpeg availability\n const hasFfmpeg = await checkFfmpeg();\n if (!hasFfmpeg) {\n console.error(\"FFmpeg is not installed or not in PATH.\");\n console.error(\"Install it:\");\n console.error(\" macOS: brew install ffmpeg\");\n console.error(\" Ubuntu: sudo apt install ffmpeg\");\n console.error(\" Windows: https://ffmpeg.org/download.html\");\n process.exit(1);\n return;\n }\n\n const doc = readAndParse(file);\n\n // Resolve format\n let format: RenderFormat;\n if (options.format) {\n if (options.format !== \"mp4\" && options.format !== \"gif\") {\n console.error(\n `Unknown format: \"${options.format}\". Use mp4 or gif.`,\n );\n process.exit(1);\n return;\n }\n format = options.format;\n } else {\n format = inferFormat(options.output);\n }\n\n // Resolve output path\n const inputName = basename(file, extname(file));\n const output = options.output ?? `${inputName}.${format}`;\n\n const startTime = Date.now();\n\n try {\n const result = await renderDocument(doc, {\n output: resolve(output),\n format,\n states: options.state,\n onProgress: ({ frame, totalFrames, state, percent }) => {\n const elapsed = (Date.now() - startTime) / 1000;\n const rate = elapsed > 0 ? frame / elapsed : 0;\n const remaining =\n rate > 0 ? (totalFrames - frame) / rate : 0;\n process.stderr.write(\n `\\rRendering: frame ${frame}/${totalFrames} (${percent}%) - state \"${state}\" - ETA ${remaining.toFixed(1)}s`,\n );\n },\n });\n\n process.stderr.write(\"\\n\");\n console.log(\n `Done: ${result.totalFrames} frames \\u2192 ${result.output} (${(result.durationMs / 1000).toFixed(1)}s)`,\n );\n } catch (err) {\n process.stderr.write(\"\\n\");\n console.error((err as Error).message);\n process.exit(1);\n }\n },\n );\n}\n","import { readFileSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { Command } from \"commander\";\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport { parseAtelier } from \"@a-company/atelier-schema\";\nimport { renderFrameSVG } from \"@a-company/atelier-svg\";\n\n/** Read and parse an .atelier file, exiting on failure. */\nfunction readAndParse(file: string): AtelierDocument {\n const absPath = resolve(file);\n let content: string;\n try {\n content = readFileSync(absPath, \"utf-8\");\n } catch {\n console.error(`Cannot read file: ${absPath}`);\n return process.exit(1);\n }\n\n const result = parseAtelier(content);\n if (!result.success) {\n console.error(\"Parse errors:\");\n for (const error of result.errors) {\n console.error(` - ${error.path}: ${error.message}`);\n }\n return process.exit(1);\n }\n\n return result.data;\n}\n\n/** Register the `export-svg` subcommand on the Commander program. */\nexport function exportSvgCommand(program: Command): void {\n program\n .command(\"export-svg <file>\")\n .description(\"Export a frame as SVG\")\n .option(\"-s, --state <name>\", \"State name (defaults to first state)\")\n .option(\"-f, --frame <number>\", \"Frame number (defaults to 0)\", \"0\")\n .option(\"-o, --output <path>\", \"Output file path (default: stdout)\")\n .option(\"--xml-declaration\", \"Include XML declaration\")\n .action(\n (\n file: string,\n options: { state?: string; frame: string; output?: string; xmlDeclaration?: boolean },\n ) => {\n const doc = readAndParse(file);\n\n const frameNumber = parseInt(options.frame, 10);\n if (isNaN(frameNumber) || frameNumber < 0) {\n console.error(`Invalid frame number: ${options.frame}`);\n process.exit(1);\n return;\n }\n\n const stateNames = Object.keys(doc.states);\n if (stateNames.length === 0) {\n console.error(\"Document has no states\");\n process.exit(1);\n return;\n }\n\n const stateName = options.state ?? stateNames[0];\n if (!doc.states[stateName]) {\n console.error(`State \"${stateName}\" not found. Available: ${stateNames.join(\", \")}`);\n process.exit(1);\n return;\n }\n\n try {\n const svg = renderFrameSVG(doc, stateName, frameNumber, {\n xmlDeclaration: options.xmlDeclaration,\n });\n\n if (options.output) {\n writeFileSync(resolve(options.output), svg, \"utf-8\");\n } else {\n console.log(svg);\n }\n } catch (err) {\n console.error((err as Error).message);\n process.exit(1);\n }\n },\n );\n}\n","import type { AtelierDocument, ImageVisual, RefVisual } from \"@a-company/atelier-types\";\nimport { resolveFrame, type ResolvedFrame } from \"@a-company/atelier-core\";\nimport { buildEffectiveLayer, type EffectiveLayer, type DocumentResolver } from \"@a-company/atelier-canvas\";\nimport { buildTransform, buildStyleAttrs } from \"./svg-properties.js\";\nimport { renderShapeSVG } from \"./svg-shapes.js\";\nimport { renderTextSVG } from \"./svg-text.js\";\nimport { buildShadowFilter, buildTintFilter, resetFilterCounter } from \"./svg-filters.js\";\nimport { resetGradientCounter } from \"./svg-gradients.js\";\nimport { buildClipPathDef, resetClipCounter } from \"./svg-clip.js\";\nimport { escapeXml } from \"./svg-properties.js\";\n\nexport interface RenderSVGOptions {\n /** Include XML declaration (default: false) */\n xmlDeclaration?: boolean;\n /** Include viewBox attribute (default: true) */\n viewBox?: boolean;\n /** Indent size in spaces (default: 2) */\n indent?: number;\n /** Resolves ref layer src paths to loaded AtelierDocuments */\n documentResolver?: DocumentResolver;\n /** Maximum ref nesting depth (default: 4) */\n maxRefDepth?: number;\n}\n\n/**\n * Render a resolved frame as an SVG string.\n * If no resolved frame is provided, resolves the given state and frame.\n */\nexport function renderFrameSVG(\n doc: AtelierDocument,\n stateOrFrame: string | ResolvedFrame,\n frame?: number,\n opts?: RenderSVGOptions,\n): string {\n // Reset counters for deterministic IDs\n resetGradientCounter();\n resetFilterCounter();\n resetClipCounter();\n\n let resolved: ResolvedFrame;\n if (typeof stateOrFrame === \"string\") {\n resolved = resolveFrame(doc, stateOrFrame, frame ?? 0);\n } else {\n resolved = stateOrFrame;\n }\n\n const { width, height } = doc.canvas;\n const indent = opts?.indent ?? 2;\n const pad = \" \".repeat(indent);\n\n // Build effective layers\n const effLayers: EffectiveLayer[] = resolved.layers.map(rl =>\n buildEffectiveLayer(rl, width, height),\n );\n\n // Collect all defs and layer elements\n const allDefs: string[] = [];\n const layerElements: string[] = [];\n\n for (let i = 0; i < effLayers.length; i++) {\n const eff = effLayers[i];\n const layer = resolved.layers[i].layer;\n\n // Skip invisible or fully transparent\n if (!eff.visible) continue;\n if (eff.opacity <= 0) continue;\n\n // Resolve asset for images\n if (layer.visual.type === \"image\") {\n const iv = eff.visual as ImageVisual;\n if (!iv.src && iv.assetId && doc.assets?.[iv.assetId]) {\n (eff.visual as ImageVisual).src = doc.assets[iv.assetId].src;\n }\n }\n\n // Build transform\n const transform = buildTransform(eff);\n const styleAttrs = buildStyleAttrs(eff);\n\n // Build shadow filter\n const filterResult = buildShadowFilter(eff);\n if (filterResult) allDefs.push(filterResult.defs);\n\n // Build tint filter\n const tintResult = buildTintFilter(eff);\n if (tintResult) allDefs.push(tintResult.defs);\n\n // Build clip path\n let clipAttr = \"\";\n if (layer.clipPath) {\n const clipResult = buildClipPathDef(layer.clipPath, eff.width, eff.height);\n if (clipResult.defs) {\n allDefs.push(clipResult.defs);\n clipAttr = ` clip-path=\"${clipResult.clipRef}\"`;\n }\n }\n\n // Build group attributes\n const gAttrs: string[] = [];\n if (transform) gAttrs.push(`transform=\"${transform}\"`);\n if (styleAttrs) gAttrs.push(styleAttrs);\n // Apply combined or individual filters\n if (filterResult && tintResult) {\n // When both shadow and tint exist, we need a combined filter\n // For simplicity, apply shadow filter and tint separately via style\n gAttrs.push(`filter=\"${filterResult.filterRef}\"`);\n // Tint is a second filter — wrap content in nested group\n } else if (filterResult) {\n gAttrs.push(`filter=\"${filterResult.filterRef}\"`);\n } else if (tintResult) {\n gAttrs.push(`filter=\"${tintResult.filterRef}\"`);\n }\n if (clipAttr) gAttrs.push(clipAttr.trim());\n\n // Render visual content\n let content = \"\";\n let layerDefs = \"\";\n\n switch (layer.visual.type) {\n case \"shape\": {\n const result = renderShapeSVG(eff, eff.visual as import(\"@a-company/atelier-types\").ShapeVisual);\n content = result.elements;\n layerDefs = result.defs;\n break;\n }\n case \"text\":\n content = renderTextSVG(eff, eff.visual as import(\"@a-company/atelier-types\").TextVisual);\n break;\n case \"image\": {\n const iv = eff.visual as ImageVisual;\n if (iv.src) {\n if (iv.spritesheet) {\n // Spritesheet: compute source rect and use full sheet dimensions for inner image\n const { columns, rows, frameWidth, frameHeight, frameCount } = iv.spritesheet;\n const maxFrames = frameCount ?? (columns * rows);\n const idx = Math.max(0, Math.min(Math.floor(iv.frameIndex ?? 0), maxFrames - 1));\n const col = idx % columns;\n const row = Math.floor(idx / columns);\n const sx = col * frameWidth;\n const sy = row * frameHeight;\n const imgW = columns * frameWidth;\n const imgH = rows * frameHeight;\n content = `<svg viewBox=\"${sx} ${sy} ${frameWidth} ${frameHeight}\" width=\"${eff.width}\" height=\"${eff.height}\">` +\n `<image href=\"${escapeXml(iv.src)}\" width=\"${imgW}\" height=\"${imgH}\" />` +\n `</svg>`;\n } else if (iv.sourceRect) {\n // Manual sourceRect: viewBox crops from image coordinate space\n const sr = iv.sourceRect;\n content = `<svg viewBox=\"${sr.x} ${sr.y} ${sr.width} ${sr.height}\" width=\"${eff.width}\" height=\"${eff.height}\">` +\n `<image href=\"${escapeXml(iv.src)}\" width=\"${eff.width}\" height=\"${eff.height}\" />` +\n `</svg>`;\n } else {\n content = `<image href=\"${escapeXml(iv.src)}\" width=\"${eff.width}\" height=\"${eff.height}\" />`;\n }\n }\n break;\n }\n case \"group\":\n // Groups are structural — no visual content in SVG either\n break;\n case \"ref\": {\n const refVisual = eff.visual as RefVisual;\n const refContent = renderRefSVG(eff, refVisual, doc, opts);\n content = refContent;\n break;\n }\n }\n\n if (layerDefs) allDefs.push(layerDefs);\n\n if (content) {\n const gOpen = gAttrs.length > 0 ? `<g ${gAttrs.join(\" \")}>` : \"<g>\";\n layerElements.push(`${pad}${gOpen}${content}</g>`);\n }\n }\n\n // Build SVG\n const lines: string[] = [];\n\n if (opts?.xmlDeclaration) {\n lines.push('<?xml version=\"1.0\" encoding=\"UTF-8\"?>');\n }\n\n const viewBox = opts?.viewBox !== false ? ` viewBox=\"0 0 ${width} ${height}\"` : \"\";\n const bg = doc.canvas.background;\n\n lines.push(`<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width}\" height=\"${height}\"${viewBox}>`);\n\n // Defs section\n if (allDefs.length > 0) {\n lines.push(`${pad}<defs>`);\n for (const def of allDefs) {\n lines.push(`${pad}${pad}${def}`);\n }\n lines.push(`${pad}</defs>`);\n }\n\n // Background\n if (bg && bg !== \"transparent\") {\n lines.push(`${pad}<rect width=\"${width}\" height=\"${height}\" fill=\"${bg}\" />`);\n }\n\n // Layers\n lines.push(...layerElements);\n\n lines.push(\"</svg>\");\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Render a ref layer as SVG. Uses documentResolver to inline sub-doc content,\n * or falls back to a dashed placeholder rectangle.\n */\nfunction renderRefSVG(\n eff: EffectiveLayer,\n visual: RefVisual,\n _parentDoc: AtelierDocument,\n opts?: RenderSVGOptions,\n _depth?: number,\n _visitedRefs?: Set<string>,\n): string {\n const resolver = opts?.documentResolver;\n\n if (!resolver) {\n return `<rect width=\"${eff.width}\" height=\"${eff.height}\" fill=\"none\" stroke=\"#999\" stroke-dasharray=\"4 2\" />`;\n }\n\n const depth = _depth ?? 0;\n const maxDepth = opts?.maxRefDepth ?? 4;\n if (depth >= maxDepth) {\n return `<rect width=\"${eff.width}\" height=\"${eff.height}\" fill=\"none\" stroke=\"#c33\" stroke-dasharray=\"4 2\" /><text x=\"${eff.width / 2}\" y=\"${eff.height / 2}\" text-anchor=\"middle\" dominant-baseline=\"middle\" fill=\"#c33\" font-size=\"12\">MAX DEPTH</text>`;\n }\n\n const visitedRefs = _visitedRefs ?? new Set<string>();\n if (visitedRefs.has(visual.src)) {\n return `<rect width=\"${eff.width}\" height=\"${eff.height}\" fill=\"none\" stroke=\"#c33\" stroke-dasharray=\"4 2\" /><text x=\"${eff.width / 2}\" y=\"${eff.height / 2}\" text-anchor=\"middle\" dominant-baseline=\"middle\" fill=\"#c33\" font-size=\"12\">CYCLE</text>`;\n }\n\n const subDoc = resolver(visual.src);\n if (!subDoc) {\n return `<rect width=\"${eff.width}\" height=\"${eff.height}\" fill=\"none\" stroke=\"#999\" stroke-dasharray=\"4 2\" /><text x=\"${eff.width / 2}\" y=\"${eff.height / 2}\" text-anchor=\"middle\" dominant-baseline=\"middle\" fill=\"#999\" font-size=\"12\">NOT FOUND</text>`;\n }\n\n const stateNames = Object.keys(subDoc.states);\n if (stateNames.length === 0) {\n return `<rect width=\"${eff.width}\" height=\"${eff.height}\" fill=\"none\" stroke=\"#999\" stroke-dasharray=\"4 2\" />`;\n }\n\n const stateName = visual.state ?? stateNames[0];\n const stateObj = subDoc.states[stateName];\n if (!stateObj) {\n return `<rect width=\"${eff.width}\" height=\"${eff.height}\" fill=\"none\" stroke=\"#999\" stroke-dasharray=\"4 2\" />`;\n }\n\n const maxFrame = Math.max(0, stateObj.duration - 1);\n const frame = Math.min(visual.frame ?? 0, maxFrame);\n\n visitedRefs.add(visual.src);\n\n // Render sub-doc as nested <svg> with viewBox for scaling\n const subW = subDoc.canvas.width;\n const subH = subDoc.canvas.height;\n const resolved = resolveFrame(subDoc, stateName, frame);\n\n const subParts: string[] = [];\n for (const rl of resolved.layers) {\n const subEff = buildEffectiveLayer(rl, subW, subH);\n if (!subEff.visible || subEff.opacity <= 0) continue;\n\n // Resolve asset\n if (rl.layer.visual.type === \"image\") {\n const iv = subEff.visual as ImageVisual;\n if (!iv.src && iv.assetId && subDoc.assets?.[iv.assetId]) {\n iv.src = subDoc.assets[iv.assetId].src;\n }\n }\n\n const transform = buildTransform(subEff);\n const styleAttrs = buildStyleAttrs(subEff);\n const gAttrs: string[] = [];\n if (transform) gAttrs.push(`transform=\"${transform}\"`);\n if (styleAttrs) gAttrs.push(styleAttrs);\n\n let childContent = \"\";\n switch (rl.layer.visual.type) {\n case \"shape\": {\n const result = renderShapeSVG(subEff, subEff.visual as import(\"@a-company/atelier-types\").ShapeVisual);\n childContent = result.elements;\n break;\n }\n case \"text\":\n childContent = renderTextSVG(subEff, subEff.visual as import(\"@a-company/atelier-types\").TextVisual);\n break;\n case \"image\": {\n const iv = subEff.visual as ImageVisual;\n if (iv.src) {\n childContent = `<image href=\"${escapeXml(iv.src)}\" width=\"${subEff.width}\" height=\"${subEff.height}\" />`;\n }\n break;\n }\n case \"ref\": {\n const refV = subEff.visual as RefVisual;\n childContent = renderRefSVG(subEff, refV, subDoc, opts, depth + 1, visitedRefs);\n break;\n }\n }\n\n if (childContent) {\n const gOpen = gAttrs.length > 0 ? `<g ${gAttrs.join(\" \")}>` : \"<g>\";\n subParts.push(`${gOpen}${childContent}</g>`);\n }\n }\n\n visitedRefs.delete(visual.src);\n\n return `<svg x=\"0\" y=\"0\" width=\"${eff.width}\" height=\"${eff.height}\" viewBox=\"0 0 ${subW} ${subH}\">${subParts.join(\"\")}</svg>`;\n}\n","import type { EffectiveLayer } from \"@a-company/atelier-canvas\";\n\n/** Build SVG transform attribute from effective layer values */\nexport function buildTransform(eff: EffectiveLayer): string {\n const parts: string[] = [];\n\n // Translate to position\n if (eff.x !== 0 || eff.y !== 0) {\n parts.push(`translate(${eff.x}, ${eff.y})`);\n }\n\n const totalRotation = eff.rotation + eff.motionPathAngle;\n if (totalRotation !== 0 || eff.scaleX !== 1 || eff.scaleY !== 1) {\n const ax = eff.anchorX * eff.width;\n const ay = eff.anchorY * eff.height;\n\n // Move to anchor, apply rotation/scale, move back\n if (ax !== 0 || ay !== 0) {\n parts.push(`translate(${ax}, ${ay})`);\n }\n if (totalRotation !== 0) {\n parts.push(`rotate(${totalRotation})`);\n }\n if (eff.scaleX !== 1 || eff.scaleY !== 1) {\n parts.push(`scale(${eff.scaleX}, ${eff.scaleY})`);\n }\n if (ax !== 0 || ay !== 0) {\n parts.push(`translate(${-ax}, ${-ay})`);\n }\n }\n\n return parts.length > 0 ? parts.join(\" \") : \"\";\n}\n\n/** Build common SVG style attributes */\nexport function buildStyleAttrs(eff: EffectiveLayer): string {\n const attrs: string[] = [];\n\n if (eff.opacity < 1) {\n attrs.push(`opacity=\"${eff.opacity}\"`);\n }\n\n if (eff.blendMode !== \"normal\") {\n attrs.push(`style=\"mix-blend-mode: ${eff.blendMode}\"`);\n }\n\n return attrs.join(\" \");\n}\n\n/** Escape XML special characters */\nexport function escapeXml(str: string): string {\n return str\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n","import type { Fill, LinearGradientFill, RadialGradientFill, Color, RGBAColor, HSLAColor } from \"@a-company/atelier-types\";\n\nlet gradientIdCounter = 0;\n\nexport function resetGradientCounter(): void {\n gradientIdCounter = 0;\n}\n\n/** Convert an Atelier Color to a CSS color string */\nexport function colorToCSS(color: Color): string {\n if (typeof color === \"string\") return color;\n if (\"r\" in color) {\n const c = color as RGBAColor;\n return `rgba(${Math.round(c.r)}, ${Math.round(c.g)}, ${Math.round(c.b)}, ${c.a})`;\n }\n if (\"h\" in color) {\n const c = color as HSLAColor;\n return `hsla(${c.h}, ${c.s}%, ${c.l}%, ${c.a})`;\n }\n return \"#000000\";\n}\n\n/** Generate SVG gradient defs and return the fill reference */\nexport function buildGradientDef(fill: Fill, width: number, height: number): { defs: string; fillRef: string } {\n if (fill.type === \"solid\") {\n return { defs: \"\", fillRef: colorToCSS(fill.color) };\n }\n\n if (fill.type === \"linear-gradient\") {\n return buildLinearGradient(fill, width, height);\n }\n\n if (fill.type === \"radial-gradient\") {\n return buildRadialGradient(fill, width, height);\n }\n\n return { defs: \"\", fillRef: \"none\" };\n}\n\nfunction buildLinearGradient(fill: LinearGradientFill, _width: number, _height: number): { defs: string; fillRef: string } {\n const id = `grad-${++gradientIdCounter}`;\n const rad = (fill.angle * Math.PI) / 180;\n const cos = Math.cos(rad);\n const sin = Math.sin(rad);\n\n // Map angle to x1,y1,x2,y2 (0-1 percentages)\n const x1 = 0.5 - cos * 0.5;\n const y1 = 0.5 - sin * 0.5;\n const x2 = 0.5 + cos * 0.5;\n const y2 = 0.5 + sin * 0.5;\n\n const stops = fill.stops.map(s =>\n `<stop offset=\"${s.offset}\" stop-color=\"${colorToCSS(s.color)}\" />`\n ).join(\"\");\n\n const def = `<linearGradient id=\"${id}\" x1=\"${x1}\" y1=\"${y1}\" x2=\"${x2}\" y2=\"${y2}\">${stops}</linearGradient>`;\n return { defs: def, fillRef: `url(#${id})` };\n}\n\nfunction buildRadialGradient(fill: RadialGradientFill, width: number, height: number): { defs: string; fillRef: string } {\n const id = `grad-${++gradientIdCounter}`;\n\n const cx = typeof fill.center.x === \"number\" ? fill.center.x : (parseFloat(fill.center.x) / 100) * width;\n const cy = typeof fill.center.y === \"number\" ? fill.center.y : (parseFloat(fill.center.y) / 100) * height;\n const r = typeof fill.radius === \"number\" ? fill.radius : (parseFloat(fill.radius) / 100) * Math.max(width, height);\n\n const stops = fill.stops.map(s =>\n `<stop offset=\"${s.offset}\" stop-color=\"${colorToCSS(s.color)}\" />`\n ).join(\"\");\n\n const def = `<radialGradient id=\"${id}\" cx=\"${cx}\" cy=\"${cy}\" r=\"${r}\" gradientUnits=\"userSpaceOnUse\">${stops}</radialGradient>`;\n return { defs: def, fillRef: `url(#${id})` };\n}\n","import type { ShapeVisual, Shape, RectShape, PathShape, Stroke } from \"@a-company/atelier-types\";\nimport type { EffectiveLayer } from \"@a-company/atelier-canvas\";\nimport { buildGradientDef, colorToCSS } from \"./svg-gradients.js\";\n\n/** Render a shape visual as SVG elements */\nexport function renderShapeSVG(\n eff: EffectiveLayer,\n visual: ShapeVisual,\n): { elements: string; defs: string } {\n const { shape } = visual;\n const defs: string[] = [];\n\n let fillAttr = \"none\";\n if (visual.fill) {\n const gradResult = buildGradientDef(visual.fill, eff.width, eff.height);\n if (gradResult.defs) defs.push(gradResult.defs);\n fillAttr = gradResult.fillRef;\n }\n\n let strokeAttrs = \"\";\n if (visual.stroke) {\n strokeAttrs = buildStrokeAttrs(visual.stroke);\n }\n\n const element = buildShapeElement(shape, eff.width, eff.height, fillAttr, strokeAttrs);\n return { elements: element, defs: defs.join(\"\") };\n}\n\nfunction buildShapeElement(\n shape: Shape,\n width: number,\n height: number,\n fill: string,\n strokeAttrs: string,\n): string {\n switch (shape.type) {\n case \"rect\":\n return buildRectElement(shape, width, height, fill, strokeAttrs);\n case \"ellipse\":\n return buildEllipseElement(width, height, fill, strokeAttrs);\n case \"path\":\n return buildPathElement(shape, fill, strokeAttrs);\n }\n}\n\nfunction buildRectElement(\n shape: RectShape,\n width: number,\n height: number,\n fill: string,\n strokeAttrs: string,\n): string {\n let rx = \"\";\n if (shape.cornerRadius) {\n const r = typeof shape.cornerRadius === \"number\" ? shape.cornerRadius : shape.cornerRadius[0];\n rx = ` rx=\"${r}\" ry=\"${r}\"`;\n }\n return `<rect width=\"${width}\" height=\"${height}\" fill=\"${fill}\"${rx}${strokeAttrs ? \" \" + strokeAttrs : \"\"} />`;\n}\n\nfunction buildEllipseElement(\n width: number,\n height: number,\n fill: string,\n strokeAttrs: string,\n): string {\n const cx = width / 2;\n const cy = height / 2;\n const rx = width / 2;\n const ry = height / 2;\n return `<ellipse cx=\"${cx}\" cy=\"${cy}\" rx=\"${rx}\" ry=\"${ry}\" fill=\"${fill}\"${strokeAttrs ? \" \" + strokeAttrs : \"\"} />`;\n}\n\nfunction buildPathElement(\n shape: PathShape,\n fill: string,\n strokeAttrs: string,\n): string {\n if (shape.points.length < 2) return \"\";\n\n const d: string[] = [];\n d.push(`M ${shape.points[0].x} ${shape.points[0].y}`);\n\n for (let i = 1; i < shape.points.length; i++) {\n const prev = shape.points[i - 1];\n const curr = shape.points[i];\n\n if (prev.out && curr.in) {\n d.push(`C ${prev.x + prev.out.x} ${prev.y + prev.out.y} ${curr.x + curr.in.x} ${curr.y + curr.in.y} ${curr.x} ${curr.y}`);\n } else {\n d.push(`L ${curr.x} ${curr.y}`);\n }\n }\n\n if (shape.closed) d.push(\"Z\");\n\n return `<path d=\"${d.join(\" \")}\" fill=\"${fill}\"${strokeAttrs ? \" \" + strokeAttrs : \"\"} />`;\n}\n\nfunction buildStrokeAttrs(stroke: Stroke): string {\n const parts: string[] = [];\n parts.push(`stroke=\"${colorToCSS(stroke.color)}\"`);\n parts.push(`stroke-width=\"${stroke.width}\"`);\n\n if (stroke.lineCap) parts.push(`stroke-linecap=\"${stroke.lineCap}\"`);\n if (stroke.lineJoin) parts.push(`stroke-linejoin=\"${stroke.lineJoin}\"`);\n if (stroke.dash) parts.push(`stroke-dasharray=\"${stroke.dash.join(\" \")}\"`);\n\n return parts.join(\" \");\n}\n","import type { TextVisual } from \"@a-company/atelier-types\";\nimport type { EffectiveLayer } from \"@a-company/atelier-canvas\";\nimport { colorToCSS } from \"./svg-gradients.js\";\nimport { escapeXml } from \"./svg-properties.js\";\n\n/** Render a text visual as SVG elements */\nexport function renderTextSVG(eff: EffectiveLayer, visual: TextVisual): string {\n const { style } = visual;\n\n const attrs: string[] = [];\n\n // Font attributes\n attrs.push(`font-family=\"${escapeXml(style.fontFamily)}\"`);\n attrs.push(`font-size=\"${style.fontSize}\"`);\n\n if (style.fontWeight && style.fontWeight !== \"normal\") {\n attrs.push(`font-weight=\"${style.fontWeight}\"`);\n }\n if (style.fontStyle && style.fontStyle !== \"normal\") {\n attrs.push(`font-style=\"${style.fontStyle}\"`);\n }\n\n // Color\n attrs.push(`fill=\"${colorToCSS(style.color)}\"`);\n\n // Text alignment\n const align = style.textAlign ?? \"left\";\n let textAnchor = \"start\";\n let x = 0;\n if (align === \"center\") {\n textAnchor = \"middle\";\n x = eff.width / 2;\n } else if (align === \"right\") {\n textAnchor = \"end\";\n x = eff.width;\n }\n attrs.push(`text-anchor=\"${textAnchor}\"`);\n\n // Letter spacing\n if (style.letterSpacing) {\n attrs.push(`letter-spacing=\"${style.letterSpacing}\"`);\n }\n\n // SVG text baseline: use dominant-baseline for top alignment\n attrs.push(`dominant-baseline=\"hanging\"`);\n\n return `<text x=\"${x}\" y=\"0\" ${attrs.join(\" \")}>${escapeXml(visual.content)}</text>`;\n}\n","import type { EffectiveLayer } from \"@a-company/atelier-canvas\";\n\nlet filterIdCounter = 0;\n\nexport function resetFilterCounter(): void {\n filterIdCounter = 0;\n}\n\n/** Build SVG filter definition for shadow effects */\nexport function buildShadowFilter(eff: EffectiveLayer): { defs: string; filterRef: string } | null {\n if (!eff.shadow) return null;\n\n const id = `filter-${++filterIdCounter}`;\n const { color, blur, offsetX, offsetY } = eff.shadow;\n\n const def = [\n `<filter id=\"${id}\" x=\"-50%\" y=\"-50%\" width=\"200%\" height=\"200%\">`,\n `<feDropShadow dx=\"${offsetX}\" dy=\"${offsetY}\" stdDeviation=\"${blur / 2}\" flood-color=\"${color}\" />`,\n `</filter>`,\n ].join(\"\");\n\n return { defs: def, filterRef: `url(#${id})` };\n}\n\n/** Build SVG filter definition for tint effect (feFlood + feBlend multiply) */\nexport function buildTintFilter(eff: EffectiveLayer): { defs: string; filterRef: string } | null {\n if (!eff.tint || eff.tint.amount <= 0) return null;\n\n const id = `filter-${++filterIdCounter}`;\n const { color, amount } = eff.tint;\n\n const def = [\n `<filter id=\"${id}\" x=\"0%\" y=\"0%\" width=\"100%\" height=\"100%\">`,\n `<feFlood flood-color=\"${color}\" flood-opacity=\"${amount}\" result=\"tint\" />`,\n `<feBlend in=\"SourceGraphic\" in2=\"tint\" mode=\"multiply\" />`,\n `</filter>`,\n ].join(\"\");\n\n return { defs: def, filterRef: `url(#${id})` };\n}\n","import type { Shape } from \"@a-company/atelier-types\";\n\nlet clipIdCounter = 0;\n\nexport function resetClipCounter(): void {\n clipIdCounter = 0;\n}\n\n/** Build SVG clipPath definition */\nexport function buildClipPathDef(shape: Shape, width: number, height: number): { defs: string; clipRef: string } {\n const id = `clip-${++clipIdCounter}`;\n let pathContent = \"\";\n\n switch (shape.type) {\n case \"rect\":\n if (shape.cornerRadius) {\n const r = typeof shape.cornerRadius === \"number\" ? shape.cornerRadius : shape.cornerRadius[0];\n pathContent = `<rect width=\"${width}\" height=\"${height}\" rx=\"${r}\" ry=\"${r}\" />`;\n } else {\n pathContent = `<rect width=\"${width}\" height=\"${height}\" />`;\n }\n break;\n case \"ellipse\":\n pathContent = `<ellipse cx=\"${width / 2}\" cy=\"${height / 2}\" rx=\"${width / 2}\" ry=\"${height / 2}\" />`;\n break;\n case \"path\": {\n if (shape.points.length < 2) return { defs: \"\", clipRef: \"\" };\n const d: string[] = [];\n d.push(`M ${shape.points[0].x} ${shape.points[0].y}`);\n for (let i = 1; i < shape.points.length; i++) {\n const prev = shape.points[i - 1];\n const curr = shape.points[i];\n if (prev.out && curr.in) {\n d.push(`C ${prev.x + prev.out.x} ${prev.y + prev.out.y} ${curr.x + curr.in.x} ${curr.y + curr.in.y} ${curr.x} ${curr.y}`);\n } else {\n d.push(`L ${curr.x} ${curr.y}`);\n }\n }\n if (shape.closed) d.push(\"Z\");\n pathContent = `<path d=\"${d.join(\" \")}\" />`;\n break;\n }\n }\n\n const def = `<clipPath id=\"${id}\">${pathContent}</clipPath>`;\n return { defs: def, clipRef: `url(#${id})` };\n}\n","import { readFileSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { Command } from \"commander\";\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport { parseAtelier } from \"@a-company/atelier-schema\";\nimport { exportToLottie } from \"@a-company/atelier-lottie\";\n\n/** Read and parse an .atelier file, exiting on failure. */\nfunction readAndParse(file: string): AtelierDocument {\n const absPath = resolve(file);\n let content: string;\n try {\n content = readFileSync(absPath, \"utf-8\");\n } catch {\n console.error(`Cannot read file: ${absPath}`);\n return process.exit(1);\n }\n\n const result = parseAtelier(content);\n if (!result.success) {\n console.error(\"Parse errors:\");\n for (const error of result.errors) {\n console.error(` - ${error.path}: ${error.message}`);\n }\n return process.exit(1);\n }\n\n return result.data;\n}\n\n/** Register the `export-lottie` subcommand on the Commander program. */\nexport function exportLottieCommand(program: Command): void {\n program\n .command(\"export-lottie <file>\")\n .description(\"Export a document to Lottie JSON format\")\n .option(\"-s, --state <name>\", \"State name (defaults to first state)\")\n .option(\"-o, --output <path>\", \"Output file path (default: stdout)\")\n .action(\n (\n file: string,\n options: { state?: string; output?: string },\n ) => {\n const doc = readAndParse(file);\n\n try {\n const { json, warnings } = exportToLottie(doc, {\n state: options.state,\n });\n\n // Print warnings to stderr\n for (const warning of warnings) {\n console.error(`Warning: ${warning}`);\n }\n\n const output = JSON.stringify(json, null, 2);\n if (options.output) {\n writeFileSync(resolve(options.output), output, \"utf-8\");\n } else {\n console.log(output);\n }\n } catch (err) {\n console.error((err as Error).message);\n process.exit(1);\n }\n },\n );\n}\n","import type { Color, RGBAColor, HSLAColor } from \"@a-company/atelier-types\";\n\n/** Convert an Atelier color to Lottie [r, g, b, a] format (0–1 range) */\nexport function colorToLottie(color: Color): number[] {\n if (typeof color === \"string\") {\n return hexToLottie(color);\n }\n\n if (\"r\" in color) {\n const c = color as RGBAColor;\n return [c.r / 255, c.g / 255, c.b / 255, c.a];\n }\n\n if (\"h\" in color) {\n const c = color as HSLAColor;\n const rgb = hslToRgb(c.h, c.s, c.l);\n return [rgb[0] / 255, rgb[1] / 255, rgb[2] / 255, c.a];\n }\n\n return [0, 0, 0, 1];\n}\n\nfunction hexToLottie(hex: string): number[] {\n const clean = hex.replace(\"#\", \"\");\n if (clean.length === 3 || clean.length === 4) {\n const r = parseInt(clean[0] + clean[0], 16) / 255;\n const g = parseInt(clean[1] + clean[1], 16) / 255;\n const b = parseInt(clean[2] + clean[2], 16) / 255;\n const a = clean.length === 4 ? parseInt(clean[3] + clean[3], 16) / 255 : 1;\n return [r, g, b, a];\n }\n const r = parseInt(clean.slice(0, 2), 16) / 255;\n const g = parseInt(clean.slice(2, 4), 16) / 255;\n const b = parseInt(clean.slice(4, 6), 16) / 255;\n const a = clean.length === 8 ? parseInt(clean.slice(6, 8), 16) / 255 : 1;\n return [r, g, b, a];\n}\n\nfunction hslToRgb(h: number, s: number, l: number): [number, number, number] {\n s = s / 100;\n l = l / 100;\n const a = s * Math.min(l, 1 - l);\n const f = (n: number) => {\n const k = (n + h / 30) % 12;\n return l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);\n };\n return [Math.round(f(0) * 255), Math.round(f(8) * 255), Math.round(f(4) * 255)];\n}\n","import type { ShapeVisual, Fill, Stroke } from \"@a-company/atelier-types\";\nimport type { LottieShapeItem } from \"./lottie-types.js\";\nimport { colorToLottie } from \"./map-colors.js\";\n\n/** Map an Atelier shape visual to Lottie shape items */\nexport function mapShapeVisual(\n visual: ShapeVisual,\n width: number,\n height: number,\n): LottieShapeItem[] {\n const items: LottieShapeItem[] = [];\n\n // Shape geometry\n switch (visual.shape.type) {\n case \"rect\":\n items.push({\n ty: \"rc\",\n nm: \"Rectangle\",\n d: 1,\n s: { a: 0, k: [width, height] },\n p: { a: 0, k: [width / 2, height / 2] },\n r: { a: 0, k: typeof visual.shape.cornerRadius === \"number\" ? visual.shape.cornerRadius : 0 },\n });\n break;\n case \"ellipse\":\n items.push({\n ty: \"el\",\n nm: \"Ellipse\",\n d: 1,\n s: { a: 0, k: [width, height] },\n p: { a: 0, k: [width / 2, height / 2] },\n });\n break;\n case \"path\": {\n const vertices = visual.shape.points.map(p => [p.x, p.y]);\n const inTangents = visual.shape.points.map(p => p.in ? [p.in.x, p.in.y] : [0, 0]);\n const outTangents = visual.shape.points.map(p => p.out ? [p.out.x, p.out.y] : [0, 0]);\n items.push({\n ty: \"sh\",\n nm: \"Path\",\n ks: {\n a: 0,\n k: {\n c: visual.shape.closed ?? false,\n v: vertices,\n i: inTangents,\n o: outTangents,\n },\n },\n });\n break;\n }\n }\n\n // Fill\n if (visual.fill) {\n items.push(mapFill(visual.fill, width, height));\n }\n\n // Stroke\n if (visual.stroke) {\n items.push(mapStroke(visual.stroke));\n }\n\n return items;\n}\n\nfunction mapFill(fill: Fill, _width: number, _height: number): LottieShapeItem {\n if (fill.type === \"solid\") {\n const color = colorToLottie(fill.color);\n return {\n ty: \"fl\",\n nm: \"Fill\",\n c: { a: 0, k: color.slice(0, 3) },\n o: { a: 0, k: (color[3] ?? 1) * 100 },\n r: 1,\n };\n }\n\n if (fill.type === \"linear-gradient\") {\n const stops: number[] = [];\n for (const stop of fill.stops) {\n const c = colorToLottie(stop.color);\n stops.push(stop.offset, c[0], c[1], c[2]);\n }\n return {\n ty: \"gf\",\n nm: \"Gradient Fill\",\n t: 1, // linear\n s: { a: 0, k: [0, 0] },\n e: { a: 0, k: [100, 0] },\n g: { p: fill.stops.length, k: { a: 0, k: stops } },\n r: 1,\n o: { a: 0, k: 100 },\n };\n }\n\n if (fill.type === \"radial-gradient\") {\n const stops: number[] = [];\n for (const stop of fill.stops) {\n const c = colorToLottie(stop.color);\n stops.push(stop.offset, c[0], c[1], c[2]);\n }\n return {\n ty: \"gf\",\n nm: \"Gradient Fill\",\n t: 2, // radial\n s: { a: 0, k: [50, 50] },\n e: { a: 0, k: [100, 50] },\n g: { p: fill.stops.length, k: { a: 0, k: stops } },\n r: 1,\n o: { a: 0, k: 100 },\n };\n }\n\n return { ty: \"fl\", nm: \"Fill\", c: { a: 0, k: [0, 0, 0] }, o: { a: 0, k: 100 }, r: 1 };\n}\n\nfunction mapStroke(stroke: Stroke): LottieShapeItem {\n const color = colorToLottie(stroke.color);\n return {\n ty: \"st\",\n nm: \"Stroke\",\n c: { a: 0, k: color.slice(0, 3) },\n o: { a: 0, k: (color[3] ?? 1) * 100 },\n w: { a: 0, k: stroke.width },\n lc: stroke.lineCap === \"round\" ? 2 : stroke.lineCap === \"square\" ? 3 : 1,\n lj: stroke.lineJoin === \"round\" ? 2 : stroke.lineJoin === \"bevel\" ? 3 : 1,\n };\n}\n","import type { Easing } from \"@a-company/atelier-types\";\n\nexport interface LottieEasing {\n i: { x: number[]; y: number[] };\n o: { x: number[]; y: number[] };\n}\n\n/** Map an Atelier easing to Lottie bezier easing curves */\nexport function mapEasing(easing: Easing | undefined): LottieEasing | { h: 1 } {\n if (!easing) return linearEasing();\n\n if (typeof easing === \"string\") {\n switch (easing) {\n case \"ease-in\":\n return bezierEasing(0.42, 0, 1, 1);\n case \"ease-out\":\n return bezierEasing(0, 0, 0.58, 1);\n case \"ease-in-out\":\n return bezierEasing(0.42, 0, 0.58, 1);\n default:\n return linearEasing();\n }\n }\n\n switch (easing.type) {\n case \"linear\":\n return linearEasing();\n case \"cubic-bezier\":\n return bezierEasing(easing.x1, easing.y1, easing.x2, easing.y2);\n case \"spring\":\n // Approximate spring as a cubic-bezier (lossy)\n return bezierEasing(0.25, 0.1, 0.25, 1);\n case \"step\":\n // Steps map to hold keyframes\n return { h: 1 };\n default:\n return linearEasing();\n }\n}\n\nfunction linearEasing(): LottieEasing {\n return {\n i: { x: [0.833], y: [0.833] },\n o: { x: [0.167], y: [0.167] },\n };\n}\n\nfunction bezierEasing(x1: number, y1: number, x2: number, y2: number): LottieEasing {\n return {\n i: { x: [x2], y: [y2] },\n o: { x: [x1], y: [y1] },\n };\n}\n\n/** Check if an easing is lossy (spring/step → approximated) */\nexport function isLossyEasing(easing: Easing | undefined): string | null {\n if (!easing || typeof easing === \"string\") return null;\n if (easing.type === \"spring\") return \"Spring easing approximated as cubic-bezier\";\n if (easing.type === \"step\") return \"Step easing mapped to hold keyframes\";\n return null;\n}\n","import type { Delta, AnimatableProperty } from \"@a-company/atelier-types\";\nimport type { LottieAnimatedValue, LottieAnimatedMultiValue, LottieKeyframe, LottieMultiKeyframe } from \"./lottie-types.js\";\nimport { mapEasing, isLossyEasing } from \"./map-easing.js\";\n\n/** Map deltas for a single layer+property to Lottie animated value */\nexport function mapDeltasToAnimated(\n deltas: Delta[],\n property: AnimatableProperty,\n warnings: string[],\n): LottieAnimatedValue {\n if (deltas.length === 0) {\n return { a: 0, k: 0 };\n }\n\n // Check for lossy easings\n for (const d of deltas) {\n const lossyMsg = isLossyEasing(d.easing);\n if (lossyMsg) warnings.push(`${property}: ${lossyMsg}`);\n }\n\n // If expressions, warn and use static\n for (const d of deltas) {\n if (isExpression(d.from) || isExpression(d.to)) {\n warnings.push(`${property}: Expression values not supported in Lottie, using static values`);\n return { a: 0, k: typeof d.from === \"number\" ? d.from : 0 };\n }\n }\n\n // Single delta — simple animated value\n if (deltas.length === 1) {\n const d = deltas[0];\n const fromVal = resolveValue(d.from, property);\n const toVal = resolveValue(d.to, property);\n\n if (fromVal === toVal) {\n return { a: 0, k: fromVal };\n }\n\n const easing = mapEasing(d.easing);\n const kfs: LottieKeyframe[] = [];\n\n if (\"h\" in easing) {\n kfs.push({ t: d.range[0], s: [fromVal], h: 1 });\n kfs.push({ t: d.range[1], s: [toVal] });\n } else {\n kfs.push({ t: d.range[0], s: [fromVal], e: [toVal], i: easing.i, o: easing.o });\n kfs.push({ t: d.range[1], s: [toVal] });\n }\n\n return { a: 1, k: kfs };\n }\n\n // Multiple deltas — chain keyframes\n const sorted = [...deltas].sort((a, b) => a.range[0] - b.range[0]);\n const kfs: LottieKeyframe[] = [];\n\n for (const d of sorted) {\n const fromVal = resolveValue(d.from, property);\n const toVal = resolveValue(d.to, property);\n const easing = mapEasing(d.easing);\n\n if (\"h\" in easing) {\n kfs.push({ t: d.range[0], s: [fromVal], h: 1 });\n } else {\n kfs.push({ t: d.range[0], s: [fromVal], e: [toVal], i: easing.i, o: easing.o });\n }\n }\n\n // Final keyframe\n const last = sorted[sorted.length - 1];\n kfs.push({ t: last.range[1], s: [resolveValue(last.to, property)] });\n\n return { a: 1, k: kfs };\n}\n\n/** Map position deltas (frame.x, frame.y) to Lottie multi-dimensional animated value */\nexport function mapPositionDeltas(\n xDeltas: Delta[],\n yDeltas: Delta[],\n baseX: number,\n baseY: number,\n warnings: string[],\n): LottieAnimatedMultiValue {\n const hasXAnim = xDeltas.length > 0;\n const hasYAnim = yDeltas.length > 0;\n\n if (!hasXAnim && !hasYAnim) {\n return { a: 0, k: [baseX, baseY, 0] };\n }\n\n // Collect all unique frame points\n const frames = new Set<number>();\n for (const d of [...xDeltas, ...yDeltas]) {\n frames.add(d.range[0]);\n frames.add(d.range[1]);\n }\n const sortedFrames = [...frames].sort((a, b) => a - b);\n\n if (sortedFrames.length < 2) {\n return { a: 0, k: [baseX, baseY, 0] };\n }\n\n // Build multi-dimensional keyframes\n const kfs: LottieMultiKeyframe[] = [];\n for (let i = 0; i < sortedFrames.length; i++) {\n const f = sortedFrames[i];\n const x = resolveAtFrame(xDeltas, f, baseX);\n const y = resolveAtFrame(yDeltas, f, baseY);\n\n if (i < sortedFrames.length - 1) {\n const nextF = sortedFrames[i + 1];\n const nextX = resolveAtFrame(xDeltas, nextF, baseX);\n const nextY = resolveAtFrame(yDeltas, nextF, baseY);\n\n // Find the active delta's easing\n const activeX = xDeltas.find(d => d.range[0] <= f && d.range[1] >= f);\n const activeY = yDeltas.find(d => d.range[0] <= f && d.range[1] >= f);\n const easing = mapEasing(activeX?.easing ?? activeY?.easing);\n\n if (\"h\" in easing) {\n kfs.push({ t: f, s: [x, y, 0], h: 1 });\n } else {\n kfs.push({ t: f, s: [x, y, 0], e: [nextX, nextY, 0], i: easing.i, o: easing.o });\n }\n } else {\n kfs.push({ t: f, s: [x, y, 0] });\n }\n }\n\n // Check for lossy warnings\n for (const d of [...xDeltas, ...yDeltas]) {\n const msg = isLossyEasing(d.easing);\n if (msg) warnings.push(`position: ${msg}`);\n }\n\n return { a: 1, k: kfs };\n}\n\nfunction resolveAtFrame(deltas: Delta[], frame: number, base: number): number {\n for (const d of deltas) {\n if (frame >= d.range[0] && frame <= d.range[1]) {\n const from = typeof d.from === \"number\" ? d.from : base;\n const to = typeof d.to === \"number\" ? d.to : base;\n const progress = d.range[0] === d.range[1] ? 1 : (frame - d.range[0]) / (d.range[1] - d.range[0]);\n return from + (to - from) * progress;\n }\n }\n // Hold last completed value\n let lastCompleted: Delta | undefined;\n for (const d of deltas) {\n if (frame > d.range[1]) {\n if (!lastCompleted || d.range[1] > lastCompleted.range[1]) {\n lastCompleted = d;\n }\n }\n }\n if (lastCompleted) return typeof lastCompleted.to === \"number\" ? lastCompleted.to : base;\n return base;\n}\n\nfunction resolveValue(val: unknown, _property: AnimatableProperty): number {\n if (typeof val === \"number\") return val;\n if (typeof val === \"string\" && val.startsWith(\"#\")) {\n // Color — for Lottie, colors are handled separately\n return 0;\n }\n return 0;\n}\n\nfunction isExpression(val: unknown): boolean {\n return typeof val === \"object\" && val !== null && \"expr\" in val;\n}\n","import type { AtelierDocument, Layer, Delta, State, UnitValue } from \"@a-company/atelier-types\";\nimport type { LottieLayer, LottieTransform, LottieTextData } from \"./lottie-types.js\";\nimport { mapShapeVisual } from \"./map-shapes.js\";\nimport { mapDeltasToAnimated, mapPositionDeltas } from \"./map-keyframes.js\";\nimport { colorToLottie } from \"./map-colors.js\";\n\n/** Resolve a UnitValue to a plain number (percentages treated as 0 for Lottie) */\nfunction toNum(v: UnitValue): number {\n return typeof v === \"number\" ? v : 0;\n}\n\n/** Map all layers in a document+state to Lottie layers */\nexport function mapLayers(\n doc: AtelierDocument,\n state: State,\n warnings: string[],\n): LottieLayer[] {\n const layerIndexMap = new Map<string, number>();\n doc.layers.forEach((l, i) => layerIndexMap.set(l.id, i));\n\n return doc.layers.map((layer, index) => {\n const deltas = state.deltas.filter(d => d.layer === layer.id);\n return mapLayer(layer, index, deltas, layerIndexMap, doc, warnings);\n });\n}\n\nfunction mapLayer(\n layer: Layer,\n index: number,\n deltas: Delta[],\n layerIndexMap: Map<string, number>,\n doc: AtelierDocument,\n warnings: string[],\n): LottieLayer {\n const duration = getMaxFrame(deltas, doc);\n\n const base: LottieLayer = {\n ty: getLayerType(layer),\n nm: layer.id,\n ind: index,\n ip: 0,\n op: duration,\n st: 0,\n ks: buildTransform(layer, deltas, warnings),\n };\n\n // Parent\n if (layer.parentId) {\n const parentIdx = layerIndexMap.get(layer.parentId);\n if (parentIdx !== undefined) {\n base.parent = parentIdx;\n }\n }\n\n // Blend mode\n if (layer.blendMode) {\n base.bm = mapBlendMode(layer.blendMode);\n }\n\n // Shape layer\n if (layer.visual.type === \"shape\") {\n base.shapes = mapShapeVisual(layer.visual, toNum(layer.bounds.width), toNum(layer.bounds.height));\n }\n\n // Text layer\n if (layer.visual.type === \"text\") {\n const color = colorToLottie(layer.visual.style.color);\n base.t = {\n d: {\n k: [{\n s: {\n s: layer.visual.style.fontSize,\n f: layer.visual.style.fontFamily,\n t: layer.visual.content,\n fc: color.slice(0, 3),\n j: layer.visual.style.textAlign === \"center\" ? 1 :\n layer.visual.style.textAlign === \"right\" ? 2 : 0,\n },\n t: 0,\n }],\n },\n } as LottieTextData;\n }\n\n // Image layer\n if (layer.visual.type === \"image\") {\n base.refId = layer.visual.assetId;\n base.w = toNum(layer.bounds.width);\n base.h = toNum(layer.bounds.height);\n\n if (layer.visual.spritesheet) {\n warnings.push(`Layer \"${layer.id}\": Spritesheet animation not supported in Lottie export`);\n }\n if (layer.visual.sourceRect) {\n warnings.push(`Layer \"${layer.id}\": sourceRect cropping not supported in Lottie export`);\n }\n }\n\n // Tint warning\n if (layer.tint && layer.tint.amount > 0) {\n warnings.push(`Layer \"${layer.id}\": Tint effect not supported in Lottie export`);\n }\n\n return base;\n}\n\nfunction getLayerType(layer: Layer): number {\n switch (layer.visual.type) {\n case \"shape\": return 4;\n case \"text\": return 5;\n case \"image\": return 2;\n case \"group\": return 3; // null layer\n case \"ref\": return 0; // precomp\n default: return 4;\n }\n}\n\nfunction buildTransform(\n layer: Layer,\n deltas: Delta[],\n warnings: string[],\n): LottieTransform {\n // Group deltas by property\n const byProp = new Map<string, Delta[]>();\n for (const d of deltas) {\n if (!byProp.has(d.property)) byProp.set(d.property, []);\n byProp.get(d.property)!.push(d);\n }\n\n const xDeltas = byProp.get(\"frame.x\") ?? [];\n const yDeltas = byProp.get(\"frame.y\") ?? [];\n const opacityDeltas = byProp.get(\"opacity\") ?? [];\n const rotationDeltas = byProp.get(\"rotation\") ?? [];\n const scaleXDeltas = byProp.get(\"scale.x\") ?? [];\n const scaleYDeltas = byProp.get(\"scale.y\") ?? [];\n\n // Position\n const position = mapPositionDeltas(\n xDeltas, yDeltas,\n typeof layer.frame.x === \"number\" ? layer.frame.x : 0,\n typeof layer.frame.y === \"number\" ? layer.frame.y : 0,\n warnings,\n );\n\n // Opacity (Lottie uses 0–100)\n let opacity;\n if (opacityDeltas.length > 0) {\n const raw = mapDeltasToAnimated(opacityDeltas, \"opacity\", warnings);\n // Scale 0-1 to 0-100\n if (raw.a === 0) {\n opacity = { a: 0 as const, k: (raw.k as number) * 100 };\n } else {\n const kfs = (raw.k as Array<{ t: number; s: [number]; e?: [number]; [key: string]: unknown }>).map(kf => ({\n ...kf,\n s: [kf.s[0] * 100] as [number],\n e: kf.e ? [kf.e[0] * 100] as [number] : undefined,\n }));\n opacity = { a: 1 as const, k: kfs };\n }\n } else {\n opacity = { a: 0 as const, k: (layer.opacity ?? 1) * 100 };\n }\n\n // Rotation\n const rotation = rotationDeltas.length > 0\n ? mapDeltasToAnimated(rotationDeltas, \"rotation\", warnings)\n : { a: 0 as const, k: layer.rotation ?? 0 };\n\n // Scale (Lottie uses 0–100)\n const baseScaleX = (layer.scale?.x ?? 1) * 100;\n const baseScaleY = (layer.scale?.y ?? 1) * 100;\n let scale;\n if (scaleXDeltas.length > 0 || scaleYDeltas.length > 0) {\n // Simplified: use x deltas for now\n scale = { a: 0 as const, k: [baseScaleX, baseScaleY, 100] };\n if (scaleXDeltas.length > 0 || scaleYDeltas.length > 0) {\n warnings.push(\"Scale animation partially mapped to Lottie\");\n }\n } else {\n scale = { a: 0 as const, k: [baseScaleX, baseScaleY, 100] };\n }\n\n // Anchor point\n const ax = (layer.anchorPoint?.x ?? 0) * toNum(layer.bounds.width);\n const ay = (layer.anchorPoint?.y ?? 0) * toNum(layer.bounds.height);\n\n return {\n o: opacity,\n r: rotation,\n p: position,\n a: { a: 0, k: [ax, ay, 0] },\n s: scale,\n };\n}\n\nfunction getMaxFrame(deltas: Delta[], doc: AtelierDocument): number {\n let max = 0;\n for (const state of Object.values(doc.states)) {\n if (state.duration > max) max = state.duration;\n }\n for (const d of deltas) {\n if (d.range[1] > max) max = d.range[1];\n }\n return max || 60;\n}\n\nfunction mapBlendMode(mode: string): number {\n const map: Record<string, number> = {\n normal: 0, multiply: 1, screen: 2, overlay: 3,\n darken: 4, lighten: 5, \"color-dodge\": 6, \"color-burn\": 7,\n \"hard-light\": 8, \"soft-light\": 9, difference: 10, exclusion: 11,\n hue: 12, saturation: 13, color: 14, luminosity: 15,\n };\n return map[mode] ?? 0;\n}\n","import type { AtelierDocument, State } from \"@a-company/atelier-types\";\n\n/** Check for unsupported features and collect warnings */\nexport function collectUnsupportedWarnings(doc: AtelierDocument, state: State): string[] {\n const warnings: string[] = [];\n\n // Audio not supported\n if (state.audio) {\n warnings.push(\"Audio tracks are not supported in Lottie format and will be dropped\");\n }\n\n // Expressions not supported\n for (const delta of state.deltas) {\n if (isExpression(delta.from) || isExpression(delta.to)) {\n warnings.push(`Expression values on \"${delta.layer}.${delta.property}\" not supported in Lottie`);\n }\n }\n\n // Shadow not supported in base Lottie\n for (const layer of doc.layers) {\n if (layer.shadow) {\n warnings.push(`Shadow on layer \"${layer.id}\" is not supported in base Lottie format`);\n }\n }\n\n // Motion path not directly mapped\n for (const layer of doc.layers) {\n if (layer.motionPath) {\n warnings.push(`Motion path on layer \"${layer.id}\" is not directly mappable to Lottie`);\n }\n }\n\n // Clip paths have limited support\n for (const layer of doc.layers) {\n if (layer.clipPath) {\n warnings.push(`Clip path on layer \"${layer.id}\" mapped as Lottie mask (partial support)`);\n }\n }\n\n // States/transitions\n if (Object.keys(doc.states).length > 1) {\n warnings.push(\"Multiple states flattened to single timeline in Lottie export\");\n }\n\n return warnings;\n}\n\nfunction isExpression(val: unknown): boolean {\n return typeof val === \"object\" && val !== null && \"expr\" in val;\n}\n","import type { AtelierDocument } from \"@a-company/atelier-types\";\nimport type { LottieAnimation, LottieAsset } from \"./lottie-types.js\";\nimport { mapLayers } from \"./map-layers.js\";\nimport { collectUnsupportedWarnings } from \"./warnings.js\";\n\nexport interface ExportLottieOptions {\n /** State to export (defaults to first state) */\n state?: string;\n}\n\nexport interface ExportLottieResult {\n /** The Lottie JSON animation */\n json: LottieAnimation;\n /** Warnings about unsupported features */\n warnings: string[];\n}\n\n/**\n * Export an Atelier document to Lottie JSON format.\n * This is a lossy conversion — not all features are supported.\n */\nexport function exportToLottie(\n doc: AtelierDocument,\n opts?: ExportLottieOptions,\n): ExportLottieResult {\n const stateNames = Object.keys(doc.states);\n if (stateNames.length === 0) {\n throw new Error(\"Document has no states to export\");\n }\n\n const stateName = opts?.state ?? stateNames[0];\n const state = doc.states[stateName];\n if (!state) {\n throw new Error(`State \"${stateName}\" not found`);\n }\n\n const warnings: string[] = [];\n\n // Collect unsupported feature warnings\n warnings.push(...collectUnsupportedWarnings(doc, state));\n\n // Map layers\n const layers = mapLayers(doc, state, warnings);\n\n // Map assets\n const assets: LottieAsset[] = [];\n if (doc.assets) {\n for (const [id, asset] of Object.entries(doc.assets)) {\n if (asset.type === \"image\") {\n assets.push({\n id,\n w: 100,\n h: 100,\n p: asset.src,\n e: 0,\n });\n }\n }\n }\n\n const json: LottieAnimation = {\n v: \"5.7.4\",\n fr: doc.canvas.fps,\n ip: 0,\n op: state.duration,\n w: doc.canvas.width,\n h: doc.canvas.height,\n nm: doc.name,\n layers,\n ...(assets.length > 0 ? { assets } : {}),\n };\n\n // Deduplicate warnings\n const uniqueWarnings = [...new Set(warnings)];\n\n return { json, warnings: uniqueWarnings };\n}\n","import { readFileSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { Command } from \"commander\";\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport { parseAtelier } from \"@a-company/atelier-schema\";\nimport {\n renderDocumentToPng,\n resolveExportDimensions,\n CanvasUnavailableError,\n} from \"../lib/render-image.js\";\n\n// Re-export so existing import sites (index.ts, tests) keep resolving.\nexport { resolveExportDimensions };\n\n/** Read and parse an .atelier file, exiting on failure. */\nfunction readAndParse(file: string): AtelierDocument {\n const absPath = resolve(file);\n let content: string;\n try {\n content = readFileSync(absPath, \"utf-8\");\n } catch {\n console.error(`Cannot read file: ${absPath}`);\n return process.exit(1);\n }\n\n const result = parseAtelier(content);\n if (!result.success) {\n console.error(\"Parse errors:\");\n for (const error of result.errors) {\n console.error(` - ${error.path}: ${error.message}`);\n }\n return process.exit(1);\n }\n\n return result.data;\n}\n\ninterface ExportImageOptions {\n state?: string;\n frame: string;\n width?: string;\n height?: string;\n out: string;\n}\n\n/** Parse a positive integer CLI option, returning undefined if not set. */\nfunction parseDim(raw: string | undefined, name: string): number | undefined {\n if (raw === undefined) return undefined;\n const n = parseInt(raw, 10);\n if (isNaN(n) || n <= 0) {\n console.error(`Invalid --${name}: ${raw}`);\n process.exit(1);\n }\n return n;\n}\n\n/** Register the `export-image` subcommand on the Commander program. */\nexport function exportImageCommand(program: Command): void {\n program\n .command(\"export-image <file>\")\n .description(\n \"Export a single frame as a PNG image. \" +\n \"Aspect-preserving when only one of --width/--height is set; \" +\n \"if both are set the renderer uses both verbatim (may squash).\",\n )\n .requiredOption(\"-o, --out <path>\", \"Output PNG file path\")\n .option(\"-s, --state <name>\", \"State name (defaults to first state)\")\n .option(\"-f, --frame <number>\", \"Frame number (defaults to 0)\", \"0\")\n .option(\"--width <number>\", \"Override output width (px)\")\n .option(\"--height <number>\", \"Override output height (px)\")\n .action(async (file: string, options: ExportImageOptions) => {\n const doc = readAndParse(file);\n\n const frameNumber = parseInt(options.frame, 10);\n if (isNaN(frameNumber) || frameNumber < 0) {\n console.error(`Invalid frame number: ${options.frame}`);\n process.exit(1);\n return;\n }\n\n const width = parseDim(options.width, \"width\");\n const height = parseDim(options.height, \"height\");\n\n try {\n const buffer = await renderDocumentToPng(doc, {\n state: options.state,\n frame: frameNumber,\n width,\n height,\n });\n writeFileSync(resolve(options.out), buffer);\n } catch (err) {\n if (err instanceof CanvasUnavailableError) {\n console.error(err.message);\n process.exit(1);\n return;\n }\n console.error((err as Error).message);\n process.exit(1);\n }\n });\n}\n","import { readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { Command } from \"commander\";\nimport type { AtelierDocument, ImageVisual } from \"@a-company/atelier-types\";\nimport { parseAtelier } from \"@a-company/atelier-schema\";\n\n/** Asset summary entry */\nexport interface AssetInfo {\n assetId: string;\n type: string;\n src: string;\n description?: string;\n usedByLayers: string[];\n usedByStates: string[];\n}\n\n/**\n * Extract asset info from a parsed AtelierDocument.\n */\nexport function getAssets(doc: AtelierDocument): AssetInfo[] {\n const assets = doc.assets ?? {};\n return Object.entries(assets).map(([assetId, asset]) => {\n const usedByLayers = doc.layers\n .filter(l => l.visual.type === \"image\" && (l.visual as ImageVisual).assetId === assetId)\n .map(l => l.id);\n\n const usedByStates = Object.entries(doc.states)\n .filter(([, state]) => state.audio?.src === assetId)\n .map(([name]) => name);\n\n return {\n assetId,\n type: asset.type,\n src: asset.src,\n description: asset.description,\n usedByLayers,\n usedByStates,\n };\n });\n}\n\n/**\n * Format asset info for terminal output.\n */\nfunction formatAssets(assets: AssetInfo[]): string {\n if (assets.length === 0) return \"No assets registered.\";\n\n const lines: string[] = [`Assets: ${assets.length}`];\n for (const a of assets) {\n const desc = a.description ? ` — ${a.description}` : \"\";\n lines.push(` - ${a.assetId} (${a.type}): ${a.src}${desc}`);\n if (a.usedByLayers.length > 0) {\n lines.push(` Layers: ${a.usedByLayers.join(\", \")}`);\n }\n if (a.usedByStates.length > 0) {\n lines.push(` States: ${a.usedByStates.join(\", \")}`);\n }\n }\n return lines.join(\"\\n\");\n}\n\n/** Read and parse an .atelier file, exiting on failure. */\nfunction readAndParse(file: string): AtelierDocument {\n const absPath = resolve(file);\n let content: string;\n try {\n content = readFileSync(absPath, \"utf-8\");\n } catch {\n console.error(`Cannot read file: ${absPath}`);\n return process.exit(1);\n }\n\n const result = parseAtelier(content);\n if (!result.success) {\n console.error(\"Parse errors:\");\n for (const error of result.errors) {\n console.error(` - ${error.path}: ${error.message}`);\n }\n return process.exit(1);\n }\n\n return result.data;\n}\n\n/**\n * Register the `assets` subcommand on the Commander program.\n */\nexport function assetsCommand(program: Command): void {\n program\n .command(\"assets <file>\")\n .description(\"List all assets in an .atelier file with usage info\")\n .action((file: string) => {\n const doc = readAndParse(file);\n const assets = getAssets(doc);\n console.log(formatAssets(assets));\n });\n}\n","import { readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { Command } from \"commander\";\nimport type { AtelierDocument } from \"@a-company/atelier-types\";\nimport { parseAtelier } from \"@a-company/atelier-schema\";\nimport { findTemplateVariables } from \"@a-company/atelier-core\";\n\n/** Variable summary entry */\nexport interface VariableInfo {\n name: string;\n type: string;\n description?: string;\n default?: unknown;\n referenced: boolean;\n}\n\n/**\n * Extract variable info from a parsed AtelierDocument.\n */\nexport function getVariables(doc: AtelierDocument): { variables: VariableInfo[]; undeclared: string[] } {\n const variables = doc.variables ?? {};\n const referenced = findTemplateVariables(doc);\n\n const entries = Object.entries(variables).map(([name, variable]) => ({\n name,\n type: variable.type,\n description: variable.description,\n default: variable.default,\n referenced: referenced.includes(name),\n }));\n\n const undeclared = referenced.filter(r => !variables[r]);\n\n return { variables: entries, undeclared };\n}\n\n/**\n * Format variable info for terminal output.\n */\nfunction formatVariables(info: { variables: VariableInfo[]; undeclared: string[] }): string {\n if (info.variables.length === 0 && info.undeclared.length === 0) return \"No variables declared or referenced.\";\n\n const lines: string[] = [];\n\n if (info.variables.length > 0) {\n lines.push(`Variables: ${info.variables.length}`);\n for (const v of info.variables) {\n const desc = v.description ? ` — ${v.description}` : \"\";\n const def = v.default !== undefined ? ` [default: ${JSON.stringify(v.default)}]` : \"\";\n const ref = v.referenced ? \"\" : \" (unused)\";\n lines.push(` - {{${v.name}}} (${v.type})${def}${desc}${ref}`);\n }\n }\n\n if (info.undeclared.length > 0) {\n lines.push(`Undeclared references: ${info.undeclared.length}`);\n for (const name of info.undeclared) {\n lines.push(` - {{${name}}} (not declared in variables)`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n/** Read and parse an .atelier file, exiting on failure. */\nfunction readAndParse(file: string): AtelierDocument {\n const absPath = resolve(file);\n let content: string;\n try {\n content = readFileSync(absPath, \"utf-8\");\n } catch {\n console.error(`Cannot read file: ${absPath}`);\n return process.exit(1);\n }\n\n const result = parseAtelier(content);\n if (!result.success) {\n console.error(\"Parse errors:\");\n for (const error of result.errors) {\n console.error(` - ${error.path}: ${error.message}`);\n }\n return process.exit(1);\n }\n\n return result.data;\n}\n\n/**\n * Register the `variables` subcommand on the Commander program.\n */\nexport function variablesCommand(program: Command): void {\n program\n .command(\"variables <file>\")\n .description(\"List all variables in an .atelier file with usage info\")\n .action((file: string) => {\n const doc = readAndParse(file);\n const info = getVariables(doc);\n console.log(formatVariables(info));\n });\n}\n"],"mappings":"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","names":["z","readFileSync","resolve","readFileSync","existsSync","join","resolve","resolve","join","existsSync","readFileSync","resolve","spawn","existsSync","resolve","formatResult","transcript","writeFileSync","existsSync","mkdirSync","join","resolve","join","resolve","existsSync","mkdirSync","writeFileSync","loadImage","ImageCache","resolve","createCanvas","renderFrame","mkdirSync","writeFileSync","resolve","join","basename","extname","resolve","basename","join","extname","mkdirSync","writeFileSync","readFileSync","resolve","resolve","readFileSync","readFileSync","writeFileSync","resolve","readAndParse","resolve","readFileSync","writeFileSync","createCanvas","renderFrame","spawn","resolve","spawn","preloadImages","loadImage","createCanvas","readFileSync","resolve","basename","extname","readAndParse","resolve","readFileSync","extname","basename","readFileSync","writeFileSync","resolve","readAndParse","resolve","readFileSync","writeFileSync","readFileSync","writeFileSync","resolve","r","g","b","a","kfs","buildTransform","isExpression","readAndParse","resolve","readFileSync","writeFileSync","readFileSync","writeFileSync","resolve","readAndParse","resolve","readFileSync","parseDim","writeFileSync","readFileSync","resolve","readAndParse","resolve","readFileSync","readFileSync","resolve","readAndParse","resolve","readFileSync"]}
|