Files
ECC/skills/taste-application/scripts/HANDOFF-TEMPLATE.md
T
928c1dea72 feat(tasteforge): package reusable workflows and preserve native edits (#3033)
* feat: bundle standalone taste distillation and application workflows

* docs: fix imported taste skill markdown lint

* docs: align Turkish agent catalog with taste skills

* refactor: make ECC the canonical reusable video engine

* fix: preserve video duration when applying image overlays

* fix: preserve background colors in image compositing

* fix: report best-effort duration targets and shortfalls

* feat: ship verified Fusion presets with compatibility provenance

* feat(tasteforge): preserve native edits in application bundles

* feat(tasteforge): compile local preservation without hosted input

* fix: update js-yaml to patched 4.3.2

* test: report bounded Stop wrapper failure diagnostics

* fix(tasteforge): fail closed on unsafe output names, missing overlays and cadence

- cli: default report and spec paths are derived from pack name and profile
  genre; require the manifest's name pattern before using either as a
  filename part so a traversal string cannot write outside cwd/out.
- apply_local: a pack without cadence.json, or with no measured shots and
  no explicit mean_shot, raises instead of silently planning 1.0s shots and
  reporting a measured cadence.
- legacy apply: a missing overlay aborts before any paid upload; forge()
  would have rejected it after every take was generated.
- requirements-live: pin fal-client>=0.13.0, the first release whose
  subscribe() accepts client_timeout.

Addresses the five P1 findings from the independent review of #3033.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015fxHRsydPqEcYngGbqkgt1

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-10 15:31:36 +01:00

8.5 KiB
Raw Blame History

flashethereal — handoff to Resolve and Blender

Everything below is measured from your three reference clips, not chosen. Where a number appears, it came out of mint.py and is reproducible by re-running it.


1. What you have been given

File What it is
FINAL_v3.mp4 Viewing copy. 33 shots, 14.12s, 1280x720 @ 24fps. Do not grade this — every cut is baked in. Passes all 7 verification checks.
FINAL_v3.fcpxml The same 33 cuts as a real timeline. This is the working file.
FINAL_v3.edl Same timeline, CMX3600, for anything that will not take FCPXML.
out/forge_work/ The individual graded shot files the timeline points at. Deleting this breaks the timeline even though the mp4 still plays.
stylepacks/flashethereal/look.cube 33³ node LUT. Validated: 35,937 rows, in gamut, monotonic neutral axis.
stylepacks/flashethereal/plates/ Screen-blend overlay elements on black. No keying needed.
stylepacks/flashethereal/stills/ Full-res frames from the longest shots.

2. DaVinci Resolve

Import

File > Import > Timeline > Pre-Conformed EDL / FCPXML  →  FINAL_v3.fcpxml

It lands as 24 clips at 1280x720 / 24fps, contiguous, no gaps — verified: total timeline length 14.542s matches the mp4 to the millisecond, 0 dangling asset references, all 24 media files present.

Set the project to 24 fps before importing. Resolve locks timeline frame rate on first timeline creation and will silently conform the cadence if the project is at 23.976 or 30. At a 0.66s mean shot length that conform is visible.

The LUT, and where it goes

look.cube is a normalising LUT: it takes neutral footage to the reference's grade. It is not a creative look on top of a grade.

Node order on the clip:

[1] look.cube          ← 3D LUT, node 1, nothing before it
[2] your adjustments   ← exposure/balance corrections, after
[3] creative           ← anything you want on top

Put it in ~/Library/Application Support/Blackmagic Design/DaVinci Resolve/LUT/ (macOS) or %APPDATA%\Blackmagic Design\DaVinci Resolve\Support\LUT\ (Windows), then right-click node 1 → 3D LUT → flashethereal.

The shots in forge_work/ are already graded. The LUT is there for new material you cut in, and for matching. If you apply it to the supplied shots you will double-grade them.

What the grade is

Measured
Contrast (std L*) 34.55
Black point (1st pct) 0.00
White point (99th pct) 99.66
Background (share below L*10) 26.3%
Grain sigma 0.0071

Chroma by luminance zone — this is the whole identity, and it lives in the lower midtones, not globally:

Zone a* b* chroma
L*≈7.5 0.22 0.41 0.5 — neutral
L*≈25 +19.75 14.20 24.3 — violet/orchid, the signature
L*≈45 +18.16 6.75 19.4
L*≈65 +2.03 4.22 4.7
L*≈87.5 +1.16 1.08 1.6 — neutral

Near-neutral at both ends, violet through the shadows and low mids. If you pull a global tint you will destroy this — the ends are supposed to stay clean.

Accent in the palette: #2938e7 electric blue, which is a separate accent, not part of the cast.

The cut

Reference Delivered cut
Shots 77 33
Mean shot 0.78s 0.74s (5% off)
Median shot 0.47s
p25 / p75 0.33s / 0.75s
Cuts/min 77 81
Rhythm variance (std/mean) 1.06

Variance of 1.06 means this is not metronomic — long holds punctuated by very fast runs. If you retime, keep the variance; evenly spaced cuts at the same average will read completely differently.

The delivered cut runs 5% faster than the reference, which is inside tolerance.

The borrowed shots are UI-cropped. The references are screen recordings with a like button, a view counter and a comment bubble baked into the pixels; an earlier cut shipped all of it. The crop is detected per clip (74% wide x 85% tall on this one) from edge energy in the temporal median, and the result is scaled to cover rather than padded, so there are no black bars.

Overlay plates

plates/*/glow_*.png and streak_*.png are elements lifted onto black, sized so they cover 212% of frame. Composite mode Screen (or Add) — they are premultiplied against black, so the blacks drop out with no keying and no matte. They are used in the delivered cut every 3rd shot at 0.30 base opacity, each one tightened to its own content and placed at a varied scale, position and rotation. That variation is deliberate: one plate in one spot every Nth shot reads as a watermark, which is how the first cut looked.

plates/r0/grain.png is the reference's measured grain at sigma 0.0071. Use Overlay blend, not Screen. Generated footage is conspicuously clean and a clean image graded toward a grainy reference still does not read as the reference.


3. Blender

blender -b --python blender_prop.py -- \
    --pack stylepacks/flashethereal \
    --mesh stylepacks/flashethereal/props/<prop>.glb \
    --out out/prop.blend --render out/prop_frames

Drop -b to keep the UI open and keep working in the scene.

The script derives its lighting from the pack rather than guessing:

  • World is black, film transparent. The references are 26% pure black; a grey world would light the prop from all directions and kill the silhouette. Transparent film means the render composites straight over footage.
  • Key + rim, no fill. With a key alone the silhouette dies against black wherever the surface turns away.
  • Rim colour is the pack's signature zone, Lab→linear sRGB — for this pack (0.392, 0.236, 0.401), the same violet the footage is graded to. The prop picks up the cast instead of you matching it by eye.
  • View transform is Standard, not AgX/Filmic, and there is no grading in Blender. look.cube is the single source of truth; AgX would apply its own tone curve before the LUT ever saw the pixels, and grading twice compounds.

The prop that ships with this pack

props/helmet.glb is real: 300,000 faces, 168,217 verts, one geometry, full PBR material set (baseColor + metallicRoughness + normal). Minted live. Also in the folder: helmet_plate.png (the generated reference image it was built from) and helmet_preview.png. props/_dryrun_placeholders/ holds the old stub files — they are text, not meshes, and can be deleted.

turntables/helmet.mp4 is a 72-frame / 3s turntable rendered locally, and out/helmet_graded_cut.mp4 is that turntable graded with the pack and cut at the reference cadence — chroma MAE 1.21, contrast 23.21 → 31.83. That is the whole point of the 3D branch: once a prop is a turntable it is ordinary footage and every downstream stage already handles it.

To mint another (~$0.68), use the two-step path:

python mint3d.py --genre flashethereal --plate \
    --prompt "a cracked chrome visor" --render

--plate generates a clean single-object image first and meshes that. The endpoint's own guidance is "simple background, single object, object >50% of frame" — the pack's stills are glitch collages with several subjects, which is close to the worst possible input, so lifting a prop straight from them yields sculpted noise. The extra $0.15 is the difference between a usable mesh and a discarded one.

Multi-view is the other big lever, and it is named per-angle fields (back_image_url, left_front_image_url, …) — not a list. A wrong angle label is worse than omitting the view, because the model trusts it.

fal cannot render a mesh. Its 3D category only consumes 2D and emits 3D, or consumes 3D and emits 3D — there is no 3d-to-image or 3d-to-video endpoint at all. That is why rendering happens here or in taste/render3d.py, and it is not an oversight to route around.


4. Things that will bite you

Don't Why
Grade the delivered shots again They are already graded; the LUT is for new material
Apply a global tint The signature is zone-local; both ends are meant to stay neutral
Import at 23.976 or 30 fps Resolve conforms silently and the cadence goes with it
Delete out/forge_work/ The timeline references those files by absolute path
Space the cuts evenly Variance 1.06 is the rhythm; the average alone is not
Screen the grain plate Grain wants Overlay; Screen lifts the blacks you just protected
Trust the mp4 as a master It is a viewing copy with every cut baked in