# 1.2.0 — `ken-burns` easing is correct for every zoom range

Minor release. Fixes a latent easing bug in `ken-burns` discovered via a CapCut ground-truth parity audit. **Not byte-identical for zoom ranges where `to − from ≠ -0.5`** — this is an intended correctness fix, hence a minor (not a patch).

## Highlights

- 🎯 **Ken Burns easing now scales with the zoom delta.** `cmdKenBurns` wrote the start keyframe's outgoing handle `y` as a fixed `-0.47` no matter the zoom. CapCut's "Cubic Out" preset actually encodes `y = round(0.94 × (to − from), 6)`. A `1.5 → 1.0` zoom (`Δ = -0.5`) was right by coincidence (`0.94 × -0.5 = -0.47`); a `1.0 → 1.12` zoom-in was getting `-0.47` instead of `0.1128`.
- 🔒 **`Δ = -0.5` output preserved exactly.** Drafts that zoom `1.5 → 1.0` are byte-identical to 1.1.1. Only other ranges change (from wrong to correct).
- 🧪 **Locked by parity tests.** Proven against a real CapCut capture (`cubic-out-groundtruth.json`) and the cutcli-fix model; a new test set pins Δ-scaling, the `Δ=-0.5` parity, and sign symmetry.

## Bug fixed

### `ken-burns` ease-out wrote a fixed `right_control.y = -0.47`

`cmdKenBurns` read `start.right_control.y` from `CURVE_PROFILES["ease-out"].startRightY` (`-0.47`), a fixed absolute, ignoring the value delta. The proven CapCut model is `start.right_control.y = round(0.94 × (toVal − fromVal), 6)`. `-0.47` is merely the `Δ = -0.5` case.

**Fix:** `cmdKenBurns` now computes, for `ease-out`,

- `start.right_control.y = round(0.94 × (toVal − fromVal), 6)` (constant `KEN_BURNS_CUBIC_OUT_RIGHT_Y_RATIO`),

while non-`ease-out` curves keep their profile `y` (all `0`), and `x`, `end.left_control`, and the `cmdAddKeyframe` path are untouched.

## CLI surface

Unchanged. No new commands or flags:

```
capcut-david ken-burns <draft> <seg-id> --from <scale> --to <scale> [--curve <name>]
```

## Migration from 1.1.1

**No code changes required.** If you regenerate a draft with `ken-burns` and `to − from ≠ -0.5`, the resulting `start.right_control.y` will differ from a 1.1.1-generated draft — this is the corrected easing. Drafts with `1.5 → 1.0` (or any `Δ = -0.5`) are byte-identical.

## Compatibility

- CapCut ≥ 5.x desktop (Windows + macOS), JianYing 6+ unsupported — unchanged.
- Node `>= 18` — unchanged.
- Runtime dependencies: zero — unchanged.
- 3 new tests (199 tracked tests). All tracked tests pass; aggregate coverage stays above the 80% gate.

## Backlog (out of scope here)

- The incremental `add-keyframe` / `computeControlPoints` path still emits the legacy fixed profile `y` for `ease-out` (not Δ-scaled). It was deliberately left unchanged: it has no proven CapCut ground truth and correctness there requires recomputing neighbour keyframes at insertion time. Tracked in `CapCut-ZoomFX/docs/superpowers/2026-05-19-cubic-out-parity-findings.md`.

## Roadmap (1.x — non-binding)

Unchanged from 1.0.0:

- `1.x.0` — `capcut-david query` (animation / sticker / effect / filter catalogue lookup)
- `1.x.0` — `capcut-david validate <project>` (schema-invariant linter)
- `1.x.0` — JianYing 6+ research; `psycho-build` dynamic audio ducking
