> ## Documentation Index
> Fetch the complete documentation index at: https://docs.framelane.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Expressiveness contract plan

# Expressiveness Contract — API exposure plan (Task #4)

Lift render-node's `AGENT_EXPRESSIVENESS_CONTRACT.md` (§1–§6, on render-node
`main` = production) into the public API so agents can author everything the
engine renders. Production runs the **C++ engine only** — the contract's
"Rust path: warn-skip" deltas do not gate exposure, so capabilities advertise
the full contract flat (no engine-aware lower bound).

## The pipeline (every feature moves these together)

```
api/schemas/elements.py + types.py   (public snake_case schema; StrictModel → new fields must be declared)
  → api/translation/translator.py    (emit engine v4 wire: videos[]/texts[]/stickers[]/groups[]/gradients[]/shapes[]/…)
  → api/translation/maps.py          (enum → engine camelCase; UNSUPPORTED sentinel gates)
  → api/services/capabilities_service.py  (auto-advertises from schema + maps)
  → SDK regen: clients/python/scripts/generate.py + clients/typescript `npm run generate`
  → scripts/export_openapi.py (spec-sync gate) + tests (unit + golden payloads)
```

## Verification

* **Unit**: schema accepts; translator emits the contract's exact field names/values.
* **Golden payloads**: `render-node:tests/mainTests/ReferenceVideoExitTests.cpp` holds
  the exact engine JSON for the 4 target scenes — assert translator output matches it.
* **Pixel parity** (follow-up): drive render-node's headless runner + probe frames
  (needs Task #3's runner; not wired yet — noted so it isn't mistaken for done).

## Phase status

### Phase 1 — §1 common transform/looks

* [x] **Blend modes** — enum 10→17 (separable + W3C non-separable); `BLEND_MODE_MAP` → camelCase; un-rejected; emitted on video/text/sticker/progress/audioViz.
* [x] **Perspective tilt** — `rotation:{x,y,z}` object on video/sticker (overrides scalar); un-rejected.
* [x] **`maskShape`** (circle/diamond/hexagon/star/heart/triangle) — analytic SDF mask on all visual elements
* [x] **`backdropBlur`** — frosted-glass panel (radius px) on all visual elements; shared `_common_visual` helper
* \[\~] nested `shadow`/`border` already emitted; per-corner `cornerRadius` object deferred (uniform works)
* [x] **full `filters` grade** — +temperature/tint/vibrance/highlights/shadows on video+sticker

### Phase 2 — new element kinds → **milestone: 4 exit-test scenes authorable**

* [x] **`gradients[]`** (§5e — golden-payload verified) · \[x] **`groups[]`** + stack layout (§5) · \[x] **`shapes[]`** SVG path/stroke/morph/trim (§5b — golden-verified)

### Phase 3 — §4 text + §3 animations

* [x] **per-word `style`** (W3 — golden-verified, completes the 4-scene milestone) · \[x] range `selector` (W2) · \[x] value `counter` · textWrap/\[x]glow/RTL
* [x] audio generators · \[x] `customAnimations` registries · loop/calculateTimings (present) · \[x] keyframed effect intensity (§2)

### Phase 4 — §5c/5d expressive ✅

* [x] **speed ramps** (`playbackRateKeyframes`) · **motion blur** (`params.motionBlur`) · **track mattes** (`matte`) · **animated masks** (`mask`+`maskKeyframes`)

### Phase 5 — §6 canvas + §2 tail ✅

* [x] **`background.gradient`** · **aurora** + generic effect props · W3 transitions (whipPan/cinematicZoom/burnEdge/shatter/domainWarp) · watermark
* chroma\_key: already exposed via `chroma_settings` (HSV); the newer keyR/keyG/keyB YCbCr path deferred (verify before touching working code)

### Phase 6 — consolidation

* [x] **capabilities completeness audit** (verified: 7 element kinds, 17/17 blend modes, aurora, W3 transitions, gradient/shape fields — all advertised, CI-enforced by test\_capabilities)
* [x] **SDK version bump** 0.1.0 → 0.2.0
* Remaining (infra-blocked / decisions): elements reference docs; deprecate flat legacy fields (breaking — needs SemVer decision #2); **render-parity CI gate needs the headless runner (Task #3)** — interim coverage is golden-payload assertions against ReferenceVideoExitTests.cpp

## Status: Phases 1–5 complete; Phase 6 audit + version bump done. \~22 commits, full suite 1091 pass.

## Open API-design decisions

1. **Groups public shape** — top-level `groups[]` on `RenderRequest` (matches engine) vs element-nesting sugar.
2. **Legacy field migration** — deprecate-and-map the flat `x_rotation`/`border_radius`-px fields, or keep both (SemVer impact on SDK)?

See memory: `exposure-catch-up-task`, `api-engine-capability-drift`, `render-node-main-is-production`.
