← Back to home
Changelog
All notable changes to CUTFORGE are documented in this file.
Fixed
- Public site - pricing/changelog segmented toggles readable; Fonctionnalités nav links to `/#why` with sticky offset.
Changed
- Public site (cutforge.app) - migrate to Next.js 15 (App Router) + Tailwind with an Apple-style marketing landing (EN/FR/RU); keep API contracts via `pages/api/`; restyle pricing, manual, changelog, and legal pages; minimal `/ops` dashboard.
- Landing principles copy - clearer local-disk / honest-pricing lines; drop the FFmpeg tagline (EN/FR/RU).
- Landing motion - full-bleed hero with scroll scale, two sticky feature moments, cinematic reveals on principles and sections.
[0.9.15] - 2026-07-09
Fixed
- Trim undo/redo - keep `trimClip` delta ops on the opposite stack (was converting to slim checkpoints and dropping waveforms / live fields); restore face-filter and linked captions with the trim patch.
- Start-handle trim at 0s - dragging the left handle left when the clip is already at timeline 0 no longer expands/pushes the clip to the right (clamp order: source head before timeline edge).
Changed
- `src/lib` modularization (phases 2-8) - `ui-shell/`, `telemetry/`, `export/`, `media/`, `face-filter/`, `preview/`, `project-io/`, `timeline/` (hub + leaves) with shims at old `@/lib/*` paths (ADR 010).
- Domain timing/mask - pure implementations in `src/lib/domain/` (`reverse-source-time`, dual-versus geometry, mask geometry); face-filter mask re-exports domain.
- Undo history - dynamic depth by snapshot size; v2 typed ops (`checkpoint` + `trimClip`); trim drag and playhead trim push compact `trimClip` ops.
- Export compositor - full-timeline audio, face-mask inputs, HW helpers, and video/sticker layer chains extracted from `render.rs` (`audio.rs`, `mask_inputs.rs`, `render_helpers.rs`, `video_layers.rs`).
- Shared types codegen - production TS re-exports generated `FaceFilter` (full object), `FaceFilterPoint` / `FaceFilterKeyframe`, and `TextClipWord`; Rust field-name parity tests (structs still hand-written).
- Domain shims - removed flat `@/lib/reverse-source-time` shim (imports use `@/lib/domain/reverse-source-time`).
[0.9.14] - 2026-07-09
Fixed
- FFmpeg auto-install loop - invalidate status cache after managed install / path changes so a successful download is recognized in the same session (was stuck on Configuration FFmpeg after download).
Changed
- R2 private channel - latest only - after each upload, purge older objects so only one app installer (plus `latest.json` / checksums) and one tracking/STT pack version remain (`purge-stale`).
[0.9.13] - 2026-07-09
Fixed
- FFmpeg auto-install - bump pinned BtbN win64-gpl zip (`autobuild-2026-07-09-14-21`); previous June pin returned HTTP 404 after BtbN pruned the release.
Changed
- Private channel downloads (R2-only) - installer TEST, tracking pack, STT pack, and updater `latest.json`: gate on `cutforge.app`, 307 redirect to Cloudflare R2 only (no GitHub `releases-private` stream/fallback). Publish scripts upload directly to R2 (`CUTFORGE_RELEASES_CHANNEL=r2`). See `docs/R2-PRIVATE-ASSETS.md`.
- Pack download pins (CI) - shared URL policy + live gate/R2 checks for tracking and STT (same resilience pattern as FFmpeg pin); FFmpeg Rust↔sidecar sync test; publish script defaults aligned to embedded pack versions; docs/Rules aligned to R2-only private channel.
- Gated pack APIs - `Cache-Control: no-store` on tracking/STT download redirects so CDN cannot cache a 307 without the gate.
[0.9.12] - 2026-07-09
Changed
- FFmpeg PATH (docs + regression tests) - release PATH gate documented for bundled builds; contract test asserts debug-only PATH probing; Rust regression `path_fallback_disabled_in_release_builds`.
Fixed
- Undo history - regression tests lock the 100-entry cap and heavy-project (STT words + face-filter keyframes) serialization.
- Export / tracking cancel - additional Rust tests for mid-job `EXPORT_CANCELLED` / `FACE_TRACKING_CANCELLED` and isolated cancel flags; export hook test asserts `exportJob` cleared after cancel.
- Media probe edge cases - regression tests for zero dimensions, corrupt stream JSON fields, and scrubbed invalid-JSON errors (no panic on import).
- Rotated phone media (displaymatrix) - `probe_media` and tracker `probe_dimensions` store display-oriented width/height from ffprobe rotation metadata; preview face pick and tracker RGB pipe aligned with WebView / FFmpeg autorotate.
[0.9.11] - 2026-07-09
Changed
- Site machine_id validation - checkout, Paddle fulfillment, and app-event accept only hashed machine id (64-hex) or legacy UUID, aligned with `/api/license` and `/ops`.
- Face tracking vs privacy blur - SMART DETECT / Analyze store track-only keyframes (`amount: 0`) by default so smart reframe no longer implies blur; privacy blur is an explicit opt-in in the Face filter panel (kind/intensity when enabled). Preview skips the blur replica when `amount ≤ 1` and still shows the tracking outline.
Fixed
- Face filter preview playback - when the active video visual is not loaded (`readyState < 2`), the playhead no longer advances on wall-clock time (mask/badge no longer animate while the frame stays frozen).
- Face blur replica sync - blur duplicate video receives its ref before `useFaceBlurMediaSync` attaches, so playback stays aligned with the sharp preview.
- Face blur layout - nested `.preview-media` fills the contain box (`object-fit: fill`); blur replica matches so the oval stays on the face instead of drifting right.
[0.9.10] - 2026-07-09
Added
- Preview↔export parity (Phase 0-1) - inventory and export golden luma fixtures under `fixtures/parity/` (color, opacity, reverse, dual-versus, face-filter), `npm run test:parity:export` in `test:ci`.
- Preview↔export parity (Phase 2) - TS↔Rust contracts for reverse source-time and dual-versus geometry; `merge_segments` keeps keyframe subdivision cuts.
- Preview↔export parity (Phase 3) - soft parity without WebView: CSS color contract locks, reverse preview product-decision tests, dual-versus preview uses shared slot geometry helpers, `npm run test:parity:soft` (FFmpeg filter-chain luma vs Phase 1 color golden).
[0.9.5] - 2026-07-08
Fixed
- WebM / VP9 import - waveform peak extraction no longer panics on `i16::MIN` PCM; `probe_media` catches waveform failures without crashing the app.
- Face blur preview - ellipse mask from tracked bbox (not tiny landmark polygon); clipped duplicate video blur in WebView2; playback sync via `useFaceBlurMediaSync`.
- Face tracking `--all-faces` - dev tracker binary probe + friendly error when an outdated pack lacks the flag; falls back to installed pack when needed.
- Preview playback - pause guards (`shouldResumePreviewPlayback`) and overlay video sync reduce double-audio / stale autoplay after pause.
- STT trim - caption `text` / `words` stay aligned when trimming linked text clips to the playhead.
Added
- Tests - face blur preview media, dual versus / frame fit / smart reframe UI, `useFaceBlurMediaSync`, `project-meta`, playback pause; extended caption-sync and video-seek coverage.
[0.9.4] - 2026-07-07
Fixed
- STT pack download (private builds) - `stt-pack-index.json` again uses `cutforge.app/api/download-stt-pack` (gate header) instead of a direct `releases-private` GitHub URL that fails without GitHub auth in-app.
Added
- Regression - `scripts/stt-pack-index-url.mjs` + contract/gate tests lock STT proxy URL policy before every `test:ci`.
[0.9.3] - 2026-07-07
Added
- Caption re-sync - STT captions stay aligned after media split/trim and global silence cut (`caption-sync.ts`, `sourceClipId`).
- YouTube chapters - generate timeline markers from subtitle gaps; export `MM:SS` chapter file from the Pro panel.
- Speaker zoom - auto keyframes punch-in on speech segments (waveform VAD + face center when available).
- Multi-face blur - `all-faces` mode blurs every detected face per frame (crowd anonymization).
Docs
- Phase B differentiation items #8, #10, #11, #12 marked complete in product TODO and status docs.
[0.9.2] - 2026-07-07
Added
- Captions word-pop export - ASS `\t` bounce transform on active words (export parity with preview pop).
- Caption word editor - merge adjacent words and split a word (text + timings) in the Text inspector.
- Timeline silence markers - shaded regions on the ruler from waveform peaks; click to seek.
- STT on public builds - `stt-pack-index.json` uses direct GitHub Releases URL so `downloadReady` works without the private gate.
- Dual versus layout - split preview (top/bottom tracks), inspector section, export compositor path.
- Transcript edit - remove spoken ranges from the transcript panel; ripple cuts on linked clips.
- Clip frame fit - contain vs pan for aspect mismatch; preview drag pan; export compositor support.
- New project templates - Shorts 9:16, YouTube 16:9, podcast audio picker on File -> New.
Fixed
- E2E - `new-project.e2e.cjs` dismisses template dialog after the picker assertion (unblocks second test).
- Deps - `crossbeam-epoch` 0.9.20 (RUSTSEC-2026-0204); document `memmap2` transitive ignore in `.cargo/audit.toml`.
Docs
- Phase A short-form items marked complete in product TODO and status docs.
- Doc hub: docs index, decisions, research, refreshed roadmap and V1 checklist.
[0.9.1] - 2026-07-05
UI
- Frameless window (Windows) - custom title bar with minimize, maximize, close, and drag; Tauri ACL permissions for window chrome IPC
- Smart reframe - disabling "Follow face on 9:16 export" restores project preview/export aspect to 16:9 when no other clip uses smart reframe
- STT progress - subtitle generation overlay shows per-phase status (module check, download, install, audio extract, WhisperX load / transcribe / word alignment)
Fixed
- Startup - remove React `StrictMode` in production (avoided double FFmpeg bootstrap on launch)
- i18n - `windowChrome.*` message keys typed in `MessageKey`
- STT (WhisperX) - skip `__pycache__` / `.pyc` in pack integrity checks so Python imports no longer invalidate the installed pack and force a full re-download on every subtitle run; stream WhisperX stderr for live progress; `stt` app log lines per step
Tests / dev
- E2E - `window-chrome.e2e.cjs` (launch, minimize, maximize, drag, close when isolated); `test:e2e:window-chrome` script
- Startup profiling - dev-only `[startup]` marks; Rust `check_ffmpeg_tools` wall-clock regression test (~337 ms budget)
[0.9.0] - 2026-07-04
Security (audit v6)
- CSP / theme - anti-flash script moved to `public/theme-init.js` (no inline script in `index.html`); `theme.css` design tokens loaded before `App.css`
- FFmpeg PATH - release builds no longer fall back to system `PATH` unless `CUTFORGE_ALLOW_PATH_FFMPEG=1`
- License machine id - SHA-256 hashed id (`machine_id.rs`) with legacy UUID compatibility; revocation check uses `X-Cutforge-Machine-Id` header (site coordinated)
- Activation - refuse license activation when machine uid cannot be resolved
- Private download gate - STT/tracking pack URLs no longer append `?k=` query; header auth only
- Repo hygiene - `target-karaoke-test/` gitignored; smart-reframe e2e writes to OS temp
- IPC / media - path traversal guard comments; `probe_media` errors when duration missing (no silent 5s default); extra extensions in `guess_kind_from_path`
- Progress events - Tauri progress channels suffixed by request session id (`progress_events.rs`, frontend `invokeWithProgressSession`)
- FFmpeg tooling - undated git snapshot builds no longer assumed year 2024
UI
- Appearance - View menu: Dark, Light, and Auto (follow OS `prefers-color-scheme`); choice persisted in `localStorage`
- Light theme - full Slate Canvas palette (soft #F8F9FA canvas, white surfaces, blue accent family shared with dark); timeline lanes, menus, modals, inspector, and media bin tokenized
- Stickers (light theme) - darker SVG fills for sparkle/thumbs-up/camera/music; drop-shadow on preview overlays
- Sticker drag - pointer mapping uses export canvas (1:1 with preview); stickers always composited as overlays (draggable even without V1 video); hit-testing on sticker pixels only (selected sticker on top)
[0.8.84] - 2026-07-03
Export
- Face mask encode progress - `export-progress` events during face-mask FFmpeg prep (`Encoding face mask N of M (P%)`) update overlay bar + phase text
Tracking quality (cutforge-tracker)
- Analyze loop - full-frame `detect_rgb` on every sampled frame; removed adaptive ONNX skip, ROI cascade, and fast letterbox helpers (~12 s vs ~8 s on Oies-multi-1.mp4, still ~5× faster than pre-RGB JPEG path)
Tracking pack Phase 2 (cutforge-tracker, local dev)
- RGB prefetch - background ffmpeg decode thread (`CUTFORGE_RGB_PREFETCH=0` to disable)
- Skin mask - BiSeNet every N frames (`CUTFORGE_SKIN_MASK_EVERY`, default 2) with mask reuse
- ORT EP features - optional `cuda` / `tensorrt` Cargo features + `CUTFORGE_ORT_EP`
- Benchmarks - `npm run benchmark:tracker` on reference clips (face / object / click-box)
Tracking stability (P1)
- Export cancel - no longer cancels unrelated UI face/object analyze (`request_export_cancel` decoupled from face-tracking cancel)
- Progress poll - `get_face_tracking_progress` reports idle unless a UI tracking session is active
- Mask engine - changing engine in Face filter clears persisted filter until re-analyze (draft vs export mismatch)
- Job store - reject overlapping `runFaceTracking` while `faceTrackingJob` is set; progress updates ignore stale clip ids
- Mask cache - deduplicate parallel prep by cache key; publish via `.mp4.part` + rename with per-key generation lock
Tracking stability (P0)
- UI session mutex - reject concurrent `run_face_tracking` invokes; export tracker spawns use per-thread wait + export PID registration (parallel-safe)
- ONNX inference errors - exit `MODEL_ERROR` after 3 consecutive SCRFD/YOLO failures instead of silent empty detections
[0.8.83] - 2026-07-02
Inspector & preview
- Face filter - single Face tracking card (SMART DETECT, pick, analyze); smart reframe 9:16 checkbox only (no duplicate subject pick)
- Montage - Object / animal tracking card + smart reframe 9:16 for non-face subjects (YOLO)
- Preview - smart-reframe zoom applies immediately after tracking ends; detection % badge counter-scaled in 9:16 preview
[0.8.82] - 2026-07-01
Smart reframe & subject tracking
- GPU object tracking (pack 1.4.0) - `--track-mode object` runs YOLOv8n on DirectML; Choose subject in Face filter tracks animals/objects without CPU template matching
- Two-step subject pick - crosshair + dashed box in preview; reposition by clicking, then Start tracking (no auto-start on first click)
- Reset subject - clears smart reframe keyframes, UI pick state, and restores project aspect to 16:9 when no other reframe is active
- Face filter panel layout - SMART DETECT / pick face at top; Smart reframe 9:16 block (enable, pick subject, headroom, static building) below; blur/warm effect controls last
- Progress overlay - Object tracking title/messages for subject runs vs Face tracking for face filter
- Preview fix - clear stale smart-reframe zoom transform after reset so the subject pick box stays the correct size
Tracking pack 1.4.0
- Embeds `yolov8n.onnx` (~12 MB) alongside SCRFD; index on private channel (`tracking-pack-index.json`)
- Tracker modes: `face`, `object`, `click-box`, `static-subject`
Smart reframe (Phase B1 - carried from 0.8.80+)
- Decoupled subject track from face blur - `smartReframe.keyframes` with legacy `faceFilter` fallback
- Fix first-second crop offset - anchor keyframe at clip-local time, not forced `timeMs: 0`
- Export cleanup - delete `sr_*.sendcmd` scratch after each segment
- Preview export parity - sequence preview zooms to tracked 9:16 crop when reframe is active
[0.8.81] - 2026-07-01
Face filter / tracking
- SMART DETECT - auto-pick the primary face (size + center) without a preview click; manual pick remains available in the Face filter panel
- Tracking pack 1.3.3 - `cutforge-tracker` supports `--click auto`; embedded index points to the new pack on the private channel
- Pack manifest repair - if only `cutforge-tracker.exe` or `whisper-cli.exe` was replaced locally, the app refreshes the worker SHA256 in `manifest.json` instead of re-downloading the full pack on every analyze/transcribe
- Dev helpers - `npm run patch:tracking-tracker`, `install:tracking-pack:local`, `install:stt-pack:local` (both `com.cutforge.studio` and `com.cutforge.studio.private` app data folders)
- Clearer outdated-pack error when SMART DETECT runs against an old tracker (no more misleading "Video file not found" for clap `--click auto`)
[0.8.80] - 2026-07-01
Smart Reframe
- Smart Reframe 9:16 - face-centered vertical export (1080×1920): blue crop preview, single continuous MP4 with per-frame `sendcmd` crop (validated); requires face analysis + Montage toggle; export FPS follows resolved timeline rate
Tracker / face filter
- Face tracking UI - progress overlay stays visible through post-analyze steps (parse, cache, apply); tracker stderr capped at 90% so 91-100% cover Rust finalize; `faceFilter` returned over IPC (no asset fetch on the UI thread); mask warm-up still skipped at analyze time
- Fix multi-minute freeze after analyze - the tracker's ~10 progress events/s were flooding Tauri's global event system (`emit`/`listen`), queueing ahead of the command response so the `run_face_tracking` `invoke` only resolved minutes after the Rust work finished (observed ~15 s of work -> ~240 s until the UI regained control). Progress now streams over a per-invocation Tauri channel instead, and mid-analysis emits are throttled (~1 per 300 ms, deduped; boundary/finalize percents always sent), so the response returns promptly.
Inspector
- Clip FPS - inspector shows probed source frame rate for the selected video clip (below Resolution)
[0.8.74] - 2026-06-30
Captions
- Animated captions polish - ASS export parity for caption box fill, drop shadow, and word-pop scale (`\fscx`/`\fscy` on active syllable); inspector word-by-word editor (text + start/end ms); `updateTextClip` accepts `words` patch with auto-sync on text/duration edits; split/trim partition per-word timings; preview karaoke/word-pop syncs to decoded audio/video clock with `sourceClipId`; STT audio extract uses sample-accurate FFmpeg trim (`-ss` after `-i`) so Whisper word timings match preview playback.
STT
- WhisperX sidecar (pack v2) - optional STT pack engine `whisperx`: embedded Python + torch + WhisperX with forced word alignment (wav2vec2) for karaoke-grade `words[]` timings; Rust dispatch in `transcribe_clip_sync`, manifest `engine`, build via `npm run build:stt-pack:whisperx`; dev override `CUTFORGE_WHISPERX_PYTHON`.
- STT pack 2.0.1 - fixes portable Python runtime (`pyvenv.cfg` / embed layout); published on `releases-private` (`stt-2.0.1`, WhisperX, ~579 MiB); replaces broken 2.0.0.
Hygiene
- Remove unused STT pack placeholder / `whisper_model_path`; `install_stt_pack_from_file` returns `()`; drop `normalizeClipWords` re-export; STT pack gate live test reads `packVersion` from embedded index (fixes 502 after latest-only purge).
[0.8.73] - 2026-06-29
Tracker / face filter
- SCRFD - letterbox padding uses normalized `0.0` (neutral gray) instead of raw `127.5`
- ONNX - register DirectML execution provider with CPU fallback (`onnx_session`)
- Skin mask - decode source segment via single FFmpeg RGB pipe (no per-frame JPEG spawns)
- Robustness - UltraLight output shape validation; `SparseKeyframe` struct; densify O(n) prepass
- Dead code - remove unused tracker APIs (`has_landmark_outputs`, `from_bbox`, `MaskEngine::as_str`)
Export / backend
- Export progress UI - parallel segment exports track completion by timeline index (not finish order); overlay shows completed count, active segment %, and global bar without duplicate phase %
- Export hardware - AMF/QSV encoder support, NVIDIA multi-GPU index, `get_export_hardware_profile` IPC, hardware summary in export settings
- Segment merge - collapse text-only boundaries on a single video track (one render job instead of per-subtitle segments)
- Filter graph - long graphs use `-filter_complex //?/path` on Windows (FFmpeg 62+)
- Face filter export - fix invalid FFmpeg graph when face blur chains into overlay fades (empty `[vlface]` pad)
- Export profiler - `ExportProfile` on every `export_timeline` (raw/merged segments, boundary breakdown, phase timings, per-segment stats); optional JSON via `CUTFORGE_EXPORT_PROFILE`
- Single-pass export (opt-in) - `CUTFORGE_EXPORT_SINGLE_PASS=1` renders eligible timelines in one full `filter_complex` job (`exportMode: singlePassComposite`); segmented pipeline stays default (faster on DJI workflow benchmark)
- Face mask cache - key v7 includes `export_fps` and export dimensions; warm uses probed source size
- Manifests - strip UTF-8 BOM before JSON parse (tracking + STT packs)
- Downloads - reject non-HTTPS zip URLs; fix RFC1918 `172.16-31` check (no `172.2` over-block)
- Capabilities - remove unused `default` / `desktop-capability` Tauri configs
Preview / frontend
- Toolbar layout - customizable quick and timeline toolbars (minimal / standard / full presets, per-action checkboxes); default production layout is minimal (export + split + zoom); Edit -> Customize toolbar...; persisted in `localStorage`; E2E builds keep full toolbar via `VITE_E2E`; `EditorPage` falls back to menu when toolbar buttons are hidden
- Inspector - drag-reorder section blocks (Montage, Pro, Text, ...); order persisted in localStorage
- STT captions - `caption-clips` pipeline with word-level timings for karaoke / word-pop presets
- Playback - `useSequencePlayback` uses memoized `TimelineIndex` (parity with RAF loop)
- Playback engine - `computePlaybackTick` / handoff helpers use indexed timeline resolution (closes R3-1 residual)
- IPC progress - scoped listeners ignore events after invoke completes
CI / hygiene
- E2E workflow benchmark - `test:e2e:workflow-dji` (DJI + wife, FX max, phased JSON report); offline `build:benchmark-dji-60s` / `export:benchmark-dji-60s`
- Remove accidental `$s/` stub directory from the repo
- Contracts - `mask-geometry-contract` + repo `$` path guard in `test:export-contracts`
[0.8.72] - 2026-06-19
Editor (beta UX)
- Inspector - subsection headers fully clickable (`InspectorSubsection` on Pro, Montage, Text, Sticker, Face filter, Audio, Image, main inspector)
- Inspector cards - Pro and Montage panels use bordered `InspectorCard` groups (keyframes, effects, proxy, SRT, STT, silence; speed, transition, transform)
- Timeline toolbar - compact grouped actions, icon-only undo/redo, abbreviated labels with shortcuts; zoom slider (5%-400%) centered in the toolbar row
- Timeline tracks - + / − on the last overlay, audio, and text track (remove only when empty; at least one track per kind kept)
- Timeline layout - text tracks (T1, T2, ...) displayed above the video stack (subtitles on top, V3->V1 below)
Tests
- Component tests for `InspectorSubsection`, `InspectorCard`, Pro/Montage card layout, compact timeline toolbar
- `inspector-ux-visual` CSS contract + `inspector-visual-contract` test ids
- E2E `inspector-ux.e2e.cjs` + static spec test
[0.8.71] - 2026-06-25
Editor (STT - Phase 1)
- Subtitles - local Whisper pack (optional download): transcribe selected audio/video clip -> text clips on T1
- Inspector (Pro) - "Generate subtitles" button with install/transcribe progress overlays
- Privacy - speech never leaves the machine (whisper.cpp in `%APPDATA%/stt`)
Editor (styled subtitles - Phase 2)
- Subtitle presets - viral styles (box, bold, neon, minimal, pop) with live preview and matching FFmpeg `drawtext` burn-in
- Caption box - semi-opaque background (`box=1`) on export when preset uses `boxColor`
- Inspector (Pro) - pick preset before STT generation; Apply to T1 restyles all subtitles on the text track
Editor (multi-export batch - Phase 3)
- Export settings - "Export for all networks" produces 4 MP4s (YouTube, Shorts, TikTok, Instagram) in one folder
- Progress - batch overlay shows platform index (e.g. 2/4) with combined progress bar
- Resilience - partial batch failure continues remaining presets and reports summary
Editor (podcast assistant - Phase 4)
- Wizard - File -> Podcast assistant: 6-step flow (project template -> import -> silence cut -> ducking -> local STT captions -> batch export)
- Skippable steps - each stage can be skipped; summary before export
- Orchestration - reuses podcast template, global silence cut, subtitle presets, and multi-export batch from Phases 1-3
- Wizard STT - inline errors and unpublished-pack hint on the captions step
Editor (STT pack - private channel)
- STT pack - `stt-1.0.1` on `releases-private` (Whisper 1.9.1 + ggml-small + whisper.cpp runtime DLLs)
- Download proxy - `GET /api/download-stt-pack?pack=1.0.1` (private gate, same as tracking pack)
- Pack download - append private gate `?k=` on cutforge.app STT/tracking proxy URLs (fixes HTTP 401)
- Gate resolution - runtime `PRIVATE_UPDATER_GATE_TOKEN` fallback for dev builds; compile-time gated pack URLs in `build.rs`
- Gate source - read private updater `?k=` from embedded Tauri config (CUTFORGE-TEST installs)
- Gate bundle - ship `private-gate.embed` in CUTFORGE-TEST; wizard blocks subtitle generation on public CUTFORGE with a clear PRIVÉ message
- Catalog - `downloadReady` flag on STT pack catalog
- Errors - block ungated pack downloads with a clear CUTFORGE PRIVÉ message instead of opaque HTTP 401
- Wizard - fix duplicate error toast on subtitle generation failure
- Transcript - clamp whisper segment timestamps to clip duration
- Smoke - `npm run smoke:stt` (wife-front.mp4 fixture)
- Subtitle length - max on-screen duration presets (Short 3 s / Medium 5 s / Long 10 s / Auto) in Pro inspector and podcast wizard; reflow after Whisper
- STT pack - manifest integrity fixes (no self-hash in `files[]`); regression tests for repack and manual manifest edits
Fixes
- STT sync - subtitle cues follow speech timing: Whisper full JSON (`-ojf`) per-token timestamps; reflow splits on word timings instead of character-length ratio
[0.8.70] - 2026-06-19
_Thank you to ṪëṄäḲïṄṾḞẌ for the beta feedback._
Editor (beta UX)
- Timeline - ruler and playhead no longer select timecode text while scrubbing (`user-select: none`)
- Inspector - all numeric sliders (audio, image, text, sticker, montage, chroma, effects, face filter, silence cut) accept typed values beside the range control
- Montage - clip rotation range extended to ±360° (preview + FFmpeg export)
- Keyframes - translated property labels, seek on list/timeline click, enriched guidance hint
FFmpeg
- First launch - setup dialog retries automatic FFmpeg download (BtbN GPL build into `%APPDATA%`) before manual gyan.dev steps; clears broken saved paths before install
- Auto-install - bump pinned BtbN autobuild URL (upstream purged the previous pin -> HTTP 404 on fresh install)
[0.8.69] - 2026-06-19
Security (code audit W1-W5)
- Tracking pack - download proxy requires private gate header; install IPC gated in release builds
- Telemetry - desktop `app-event` posts require gate token (compile-time + site validation)
- Stickers - export path validation rejects traversal outside allowed directories
- Tauri - splash window capability split from main IPC surface
- Ops - timing-safe bearer check for cron dashboard routes
Performance (code audit W6-W9)
- Undo - history stores serialized project snapshots (lower RAM on large timelines)
- Media library - no longer subscribes to live playhead ticks
- Playback - timeline index cache for RAF hot-path clip lookups
- Face filter - mask cache pre-warmed after tracking analyze completes
Editor (code audit W10-W15)
- Preview audio - all dedicated audio tracks (A1, A2, ...) play together in preview
- Waveforms - peaks extracted during media probe on import
- Preview - export frame keeps correct 16/9 aspect ratio when resizing the preview panel
- Menus - keyboard navigation in menu bar and dropdown menus
- Timeline - focusable scroll area; arrow/Home/End scrub; clips selectable from keyboard
- i18n - English `a11y.inspector` label (no French fallback)
[0.8.68] - 2026-06-19
Added
- Media library - user-created bins (chutiers) to organize assets; imports go into the active bin
- Edit menu - customizable keyboard shortcuts (saved per device)
Changed
- Effects - stronger vignette and warm LUT at the same slider value (preview + export)
[0.8.67] - 2026-06-19
Added
- Editor - classic menu bar (File, Edit, Timeline, View, Help) with keyboard hints; quick toolbar keeps Save / Import / Export
- Media import - native Tauri drag-drop on the main window (`dragDropEnabled`) with Explorer file routing to timeline lanes or media library
Fixes
- Playback - preview embedded video audio sync via decoded-time state (no ref read during render); RAF loop resync tolerance for V1 handoff
[0.8.66] - 2026-06-18
Added
- Timeline - NLE track order (V1 bottom, overlays above); OS file drag-drop onto lanes; playhead seek by frame (`←/->`), 1s (`Shift`), 5s (`Ctrl`); timeline gutter wheel 1s (Shift 10s)
[0.8.65] - 2026-06-17
Fixes
- Face analyze - tracking pack 1.3.2 fixes FFmpeg 7+ JPEG frame extraction (`yuvj420p`) for phone/webcam sources
[0.8.64] - 2026-06-17
Fixes
- Inspector - Text and Stickers panels always visible in the right sidebar (restore default picker UX after lazy-mount regression)
[0.8.63] - 2026-06-17
Security
- IPC paths - sticker cache limited to canonical app-data directory; media path traversal rejected; relink paths validated on blocking pool
- Media scope - `register_media_paths` failures reported to Sentry and surfaced in UI (i18n toast)
Editor
- Autosave recovery - startup dialog to restore or ignore recovered project (no silent auto-restore)
- Undo history - lighter snapshots via `projectForHistory()` (exclude waveformPeaks, thumbnailPath, proxy)
- Accessibility - toast dismiss `aria-label`; preview splitter keyboard resize
Fixes
- Error boundary - unexpected crash message uses i18n `error.unexpected`
[0.8.62] - 2026-06-16
Editor
- Global silence cut - remove internal silences across unlocked audio/video tracks with ripple; toolbar action and speech-segment helpers on waveform peaks
- Face filter preview - overlay driven from playhead bus at 60 Hz during playback; backdrop blur skipped while playing for smoother motion
- Preview text layers - position updates at playhead-bus rate instead of per-frame React state
- Face filter score badge - throttled to 10 Hz during playback
- Timeline ruler - adaptive tick density on long projects
- Inspector - lazy-mount panels by selection type
- Trim drag - clip geometry via DOM during drag; store commit on mouseup; text clips use CSS transform like media
- Face mask export - per-clip progress in export overlay (EN/FR/RU)
Fixes
- Face filter / tracking pack - embedded index points to `cutforge.app/api/download-tracking-pack` (proxies private GitHub release); fixes HTTP 404 when downloading models without GitHub auth
- ClipProPanel - removed FREE tier gate (full editor on FREE; PRO = watermark removal only)
- FREE watermark - preview alignment with FFmpeg overlay math
- License API - fail-closed Paddle idempotency, upsert-before-email, subscription revoke; 503 on DB errors
- IPC - sticker and media path handlers on `spawn_blocking`
Site
- Tracking pack API - `GET /api/download-tracking-pack?pack=` streams `tracking-*` assets from `releases-private` via server token
- Windows download - homepage card and `/api/download-windows` show Coming soon (same as macOS); public GitHub releases repo emptied and set private; default channel `releases-private`; public app releases only from v1.0.0+
- Built-in updater - disabled in stock `tauri.conf.json` (private gate unchanged on site)
Architecture
- Codegen - manifest-driven TS/Rust shared types; sync gate in `test:export-contracts`
- Timeline - `timeline-clip-timing` contract JSON; shared `isTimeInsideClip`; Rust cross-ref in `timeline_resolve`
- Contracts - `ProjectSnapshot` asserts `textClips` and `beatMarkers`; notify inject for tests
- Playhead bus - playback drops 60 Hz `displayMs` React state; preview transforms subscribe to bus
Tests & CI
- E2E face-filter export (analyze fixture, MP4 + corner luma guard); `test:e2e:long` in CI; macOS WDIO smoke job
- P1 e2e verify script; updater E2E available path; webhook idempotency env tests
[0.8.61] - 2026-06-14
Sentry
- Handled errors - `captureAppException` normalizes non-Error rejections; wired for export, import, project session, autosave, stickers, and missing media
Editor
- Feature split - timeline, inspector, and export logic moved into dedicated `src/features/editor` modules
Site
- Changelog build - repair corrupted user release notes; normalize em dashes, arrows, and narrow spaces in published HTML bodies
[0.8.60] - 2026-06-14
Face filter (Phase 5)
- Temporal mask smoothing - EMA on skin-engine masks (alpha=0.4) for steadier blur during motion
- Tracking pack 1.3.1 - rebuilt tracker; catalog zipSha256 aligned with GitHub release; minAppVersion 0.8.59
[0.8.59] - 2026-06-14
Face filter - dual engine (MVP)
- Engine selector - `standard` (landmark polygon mask) / `skin` (BiSeNet face parsing) on clip `FaceFilter`
- Skin export - `smartblur` when FFmpeg supports it; `gblur` fallback (~15% higher sigma)
- Re-analyze gate - engine change invalidates cached masks/keyframes until re-analyze; localized UI prompt (EN/FR/RU)
- Tracking pack 1.3.0 - adds `face_parsing_resnet18.onnx`; `minAppVersion` 0.8.59; index SHA updated locally (GitHub publish pending)
Tests
- Dual-engine unit/contract coverage; skin export E2E via `npm run test:face-filter-export-e2e` (FFmpeg + fixtures)
[0.8.58] - 2026-06-13
Face filter (Phase 8)
- Analyze progress - real `%` from `cutforge-tracker` stderr (`cutforge-progress:`) -> `face-tracking-progress` -> overlay
- Cancel polish - cancel during tracking-pack download; localized cancel toast; overlay tests
- Preview pick - `preview-media-pick.ts` maps clicks through clip scale/crop/position (`useFaceFilterPick`)
- Detection model - default `fetch:tracking-model` = SCRFD 2.5G bn kps (bbox + keypoints)
- Manual - SmartScreen / Authenticode note for `cutforge-tracker.exe` (EN/FR/RU)
Tests & CI
- Vitest 80 % branches thresholds on `face-filter.ts` / store actions
- Knip clean; `cargo fmt` / clippy on tracking modules
- E2E tracking install - local zip IPC skips catalog SHA pin (fixture rebuild)
[0.8.57] - 2026-06-13
Security
- Tracking pack local install - SHA-256 pin, path validation, IPC gated to debug/E2E
- External URL allowlist - hardened against backslash/userinfo bypass
- FFmpeg directory selection - native dialog only (no arbitrary IPC paths)
- Production CSP - `base-uri`, `object-src`, `frame-ancestors`, `form-action`; removed `style-src unsafe-inline`
- Telemetry IPC - event allowlist + field sanitization
- Error messages - scrub absolute paths from export and `probe_media` errors
Export
- Face mask encode - stream frames (lower memory), stderr drain, cancel/kill improvements
- Export watchdog - before mask prep; parallel bounded mask generation
- Render cache - serialized prune, atomic writes, skip cache on direct-output single pass
- Cancel PID - race fixes
UI
- Modal accessibility - focus trap, Escape, `aria-labelledby`
- Editor store - narrower subscriptions (fewer re-renders)
License
- Offline revocation grace - reduced to 3 days; clock rollback detection
[0.8.56] - 2026-06-10
Changed
- Contact email - app, site, legal docs, and license fulfillment now use `info@cutforge.app` (Proton custom domain)
[0.8.55] - 2026-06-12
Fixed
- Face filter export - installed builds no longer panic with `CARGO_MANIFEST_DIR: NotPresent`; face-blur curve JSON is baked in at compile time
[0.8.54] - 2026-06-12
Fixed
- Face tracking / export - hide Windows console windows when spawning `cutforge-tracker` and FFmpeg mask encode (`CREATE_NO_WINDOW` via `hidden_command`)
- Face tracking UI - localized progress messages (preparing / analyzing) in EN, FR, and RU
[0.8.53] - 2026-06-12
Added
- Face blur curve contract - shared `face-blur-curve.json` for preview CSS and FFmpeg `gblur` sigma (wider 80-100 % range)
- FREE watermark preview - overlay in sequence preview aligned with export layout
- GitHub releases cleanup - publish scripts purge older `v*` / `tracking-*` tags (latest-only policy)
Changed
- Face filter export - landmark polygon mask at encode (parity with preview); mask cache key v5
- Face filter UI - intensity slider label + hint (EN/FR/RU); preview blur follows export curve
- Face filter export E2E - fixture fallbacks (`wife-front.mp4`) and on-the-fly mask generation
Fixed
- Face filter export - scale before `gblur` to avoid OOM on long clips; mask pipe drain / keyframe-only cache
[0.8.52] - 2026-06-12
Added
- Face tracking module uninstall - Help -> Privacy -> remove the optional tracking pack from `%APPDATA%\com.cutforge.studio\tracking\`
- Preview clip transform - face-filter pick, mask, and score follow clip scale/crop/position in the sequence preview
- Confidence score on preview - detection score badge anchored at the nose landmark (red when below 50%)
- E2E tracking install - local fixture zip (`tracking-pack-e2e.zip`) avoids GitHub download in CI
Changed
- Tracking pack index - embeds `tracking-1.1.0` (landmarks + Kalman + landmark masks from 0.8.52)
- User manual - face filter section updated (cancel, uninstall, preview ~ export)
- Face filter hints - preview copy reflects landmark mask parity with export
[0.8.51] - 2026-06-12
Changed
- FREE export watermark - updated branding asset (`Cutforge.app` logo PNG, bottom-right overlay)
[0.8.50] - 2026-06-12
Changed
- Telemetry consent - one-time opt-in banner shown after the first successful export (not at launch); rating prompt unchanged
- Telemetry decline - banner accept and decline both POST `telemetry_opt_in_changed` (`source: banner`) even when full telemetry is off (`consentOnly` allowlist)
Added
- Ops dashboard - post-export telemetry KPIs: opt-in % (banner accept rate), banner decline %, prompted machine counts (`telemetryBannerPromptedMachines`, `telemetryBannerDeclinedMachines`, `telemetryBannerDeclineRate`)
- Face filter unit tests - `src/lib/face-filter.test.ts` (normalize/merge helpers, `TrackingAnalyzeOutput` fixtures)
Docs
- Analytics - document post-export consent flow and ops KPI definitions in internal analytics docs
[0.8.38] - 2026-06-11
Fixed
- Face filter export - bind source video to FFmpeg input 0 (was using mask input -> black background + wandering ellipse)
- Face filter export - fix empty FFmpeg filter segment before `[vpre]` label
- Face filter analyze - pass app FFmpeg sidecars to tracker; remove unsupported `-hide_banner` in worker
- Face filter preview - pick coordinates in letterboxed media contain box (resize / fullscreen)
- Face filter preview - frosted overlay effect (reliable vs `backdrop-filter` on `
Added
- Face filter panel - inline analyze error message; detection confidence % after tracking
- Face filter export E2E - `npm run test:face-filter-export-e2e` (`ref-face-front.mp4`, luma corner check)
Changed
- Export render cache - bump generation `render=v16-face-filter-source-input`
[0.8.37] - 2026-06-11
Fixed
- Tracking pack download - correct GitHub URL (`/releases/releases/download/...`) for repo `CUTFORGE-VIDEO/releases` (was HTTP 404)
- Face analyze - UI analyze no longer passes `--mask-out` (compatible with pack 1.0.0 during tracking; mask at export only)
- Face filter panel - effect kind/strength editable before first analyze; show pack status hint when module missing
[0.8.36] - 2026-06-11
Added
- Face filters (filtres visage) - inspector panel: pick face in preview, analyze, live bbox overlay, blur/warm sliders
- Face filter export - precomputed mask video (`--mask-out`) + FFmpeg `alphamerge` with `gblur` / `eq` on export (simple + compositor paths)
- Face tracking pack 1.0.1 - republished with mask generation support (`tracking-1.0.1` tag)
Changed
- Tracking pack index - `packVersion` 1.0.1, `minAppVersion` 0.8.36, updated zip SHA256
[0.8.35] - 2026-06-11
Added
- Face tracking pack 1.0.0 published on GitHub Releases (`tracking-1.0.0` tag) - `cutforge-tracking-1.0.0-win64.zip` (~17 MiB)
- Build scripts `npm run build:tracking-pack` and `npm run publish:tracking-pack`
Changed
- Tracking pack index - real download URL and SHA256; `minAppVersion` 0.8.34; manifest lists `DirectML.dll` (ONNX Runtime statically linked in worker)
[0.8.34] - 2026-06-11
Added
- Face tracking pack - installer module (download, SHA256 verify, extract, manifest check) mirroring FFmpeg install; dev toolbar button + progress overlay
- Tracking IPC - `check_tracking_pack`, `ensure_tracking_pack_installed`, `tracking-install-progress` events
Fixed
- Face tracker - decode Ultra-Light RFB-320 bboxes as normalized 0-1 coords (M1 real-video validation)
[0.8.33] - 2026-06-11
Fixed
- Stickers export - accept `sticker-cache` PNG asset paths at export validation (regression from FABLE v4 `validate_export_media_paths`); regenerate from bundled SVG when cache file is missing
[0.8.32] - 2026-06-11
Security
- Clip effects & chroma key - validate chroma hex and effect parameters at the IPC boundary (FABLE v4 audit)
Added
- Cross-lang contracts - clip effects and chroma key FFmpeg filter JSON fixtures verified in TypeScript and Rust
Fixed
- Keyframes - aligned scale bounds across preview, IPC, and export
- Install attribution - atomic write for consumed marker file
- Editor - remove preview splitter listeners on `EditorShell` unmount; export cancel telemetry fallback when session missing
Tests
- CI - clip-effects contract fixtures typecheck; validate test formatting
[0.8.31] - 2026-06-11
Added
- Cross-lang contracts - timeline active clips and clip color / FFmpeg filter JSON fixtures verified in TypeScript and Rust (audit C10)
- Ops dashboard - export timing heatmaps (`cacheHitRateBucket`, `maxSegmentRenderMsBucket`)
- Project backup - `.cutforge.bak` written atomically before overwrite on save
Security
- License IPC - 64 KiB cap on `activate_license` body before JSON parse
- Telemetry - `post_app_telemetry` async (non-blocking reqwest)
- Config I/O - atomic writes for `launch_guard` and `ffmpeg_config`
- Stickers - 2 MiB cap before SVG rasterization; watermark temp file uses random name
Changed
- Timeline - memoized `
` per track (fewer re-renders during edit) - Export - thread-local `asset_fingerprint` cache before parallel segment render; `commitGesture` avoids double project stringify
Tests
- CI - `test:timeline-contract` and `test:clip-color-contract` in `test:export-contracts`
- OSV - Windows-target allowlist for GTK/Linux transitive advisories (`audit:osv`, informational)
[0.8.30] - 2026-06-11
Added
- Export errors - typed `CUTFORGE_EXPORT:
` from Rust with localized UI messages (en/fr/ru) - Keyframe contract - shared opacity interpolation JSON verified in TypeScript and Rust
Changed
- Timeline drag - CSS preview during mousemove; store and undo history commit on mouseup only (no `updatedAt` churn mid-gesture)
- FFmpeg - per-segment thread budget aligned with rayon parallelism (replaces `-threads 0`)
- Export keyframes - subdivision interval 500 ms -> 2000 ms (fewer segments on long spans)
- Waveform - extraction capped at asset duration (max 300 s)
Tests
- CI - `test:export-contracts` and sticker export e2e in `test:ci`
- Timeline - drag keeps store unchanged during mousemove; gesture `updatedAt` behavior
[0.8.29] - 2026-06-11
Added
- Export telemetry - per-segment render duration and cache hit/miss in Rust logs; `app_export_timing` includes cache hit rate and segment render buckets (audit v3 §7.4)
Tests
- Timeline - component test: drag clip then undo restores original position (audit v3 §7.2)
[0.8.28] - 2026-06-11
Security
- Asset protocol - narrower `asset://` scope; per-file registration with path canonicalization (no whole-parent directory grant)
- Export paths - validate media paths before render; guards on proxy and waveform IPC
- Telemetry - pin `cutforge.app` origin in release builds (debug override only)
- External links - host allowlist for `open_external_url`
- FFmpeg download - pinned BtbN build with SHA-256 verification (no rolling `latest` tag)
- IPC - bound `volume_gain`, `playback_rate`, `opacity`, and keyframe values at project validation
Fixed
- Export - atomic finalize via `.part` rename; Windows staging uses `out.part.mp4` so FFmpeg accepts the muxer
- Export - render watchdog during parallel segments; license revocation no longer blocks export start on HTTP
- Export - reject concurrent `export_timeline` calls; stable cancellation error code
- Stickers - accept bundled sticker paths at export validation
- FFmpeg install - reject zip-slip paths when extracting the GPL archive
- Keyboard - Q/W/S timeline shortcuts ignore Ctrl/Alt combos
- Undo - `beginGesture` / `commitGesture` for drag and trim (replaces scattered `commitHistory` flag)
- License tests - skip remote revocation checks when unit-test machine id is set
Changed
- Export cache - segment cache key built from serialized render inputs (full fingerprint matrix)
- Playback - consolidated ref bag into `PlaybackRuntime`; named A/V resync thresholds
- Timeline - O(1) asset and per-track clip lookups during render
- FFmpeg install - stream GPL zip to a temp file instead of buffering in RAM
- Export UI - warn when motion interpolation (`minterpolate`) is enabled
- CI - `cargo fmt --check` and `clippy -D warnings` in `test:ci`
[0.8.27] - 2026-06-10
Fixed
- Preview stickers - stack stickers above PiP/image overlays (export compositor parity); raise preview z-index so WebView2 video no longer paints over sticker overlays
[0.8.26] - 2026-06-10
Fixed
- Stickers - resolve bundled SVG paths from exe directory and manifest (export, preview, and rasterization no longer fail with `resources/stickers/*.svg` not found in debug/no-bundle runs)
Added
- E2E - `export-sticker.e2e.cjs` (export + center luma verification); stage stickers beside E2E binary; `addStickerAt` on E2E bridge
[0.8.25] - 2026-06-10
Fixed
- Export cache - segment cache key fingerprints text content/style, reversed, playback rate, keyframes, effects, chroma key, and strip-metadata so re-exports stay correct after edits
- Project I/O - atomic writes for save project, autosave session, and license files (crash-safe)
- Undo - drag/trim gestures snapshot state at pointer-down; Ctrl+Z restores the pre-gesture position
- Keyboard - skip global undo/redo while typing in inputs; Ctrl+Shift+Z redo works with uppercase key
- FFmpeg install - reject zip-slip paths when extracting the GPL archive
- Export - reject concurrent `export_timeline` calls (shared cancel/PID state)
- QA - gesture undo skips no-op drags; E2E text export fixtures and peak-luma assertion
[0.8.24] - 2026-06-10
Fixed
- Export keyframes - subdivide long keyframe spans (500 ms steps) and sample transforms at segment midpoint for smoother motion at export
- Export text E2E - verify title visibility window via frame luma sampling (not only file size)
- License revocation - background check on startup; export uses cached status; offline grace reuses last successful result for 7 days
- Release hardening - debug-only env overrides for license path, machine id, export timeout
Added
- Tests - `ffmpeg-frame` E2E helper, keyframe subdivision/opacity sampling, `split_transform_montage` compositor unit test, offline grace cache test
Changed
- Compositor - shared `fps_interpolation_part` / `split_transform_montage` helpers (sticker + overlay chains)
[0.8.23] - 2026-05-30
Fixed
- Export keyframes - segment boundaries follow clip keyframes; transform sampling uses segment start (not mid-segment) so motion no longer freezes between keyframes
- Autosave (large projects) - payloads above the 1.5 MB localStorage cap persist in `app_data_dir` via backend session commands
Added
- E2E - long export with live progress and cancel; export with text offset from clip cuts
- Tests - Rust coverage for keyframe segment boundaries, hostile `drawtext` escaping, and autosave backend round-trip
[0.8.22] - 2026-06-10
Fixed
- Export text timing - titles use segment boundaries and `enable=between(t,...)` so preview matches export when text is not aligned on clip cuts
- UI freeze - heavy Tauri commands (`export`, probe, proxy, waveform, license, project I/O) run on the async blocking pool
- License signing - canonical JSON key order aligned with Node; golden vector cross-check in CI
- FFmpeg process I/O - stdout drained concurrently; stderr decoded as UTF-8
- Autosave - warn when project exceeds local size cap; no longer re-triggered on timeline scrub
- Updater notes - download dialog shows full changelog entries between installed and target version
Security
- Validate text clip styles on export/load; hardened `drawtext` escaping; non-recursive asset scope; embedded FREE watermark bytes
[0.8.21] - 2026-06-10
Fixed
- Rating prompt - shown after first export even without full telemetry opt-in; rating events stored via `consentRating`
- Ops opt-in KPI - counts `app_launch` and explicit toggles (rate capped at 100%)
- Site deploy (Vercel Hobby) - ops CSV export merged into `GET /api/ops/dashboard?export=csv`; desktop telemetry routed via `/api/event?target=app` rewrite (12-function limit)
Added
- Ops test coverage - KPI normalizers, mocked `fetchOpsDashboard`, CI Postgres e2e gate
[0.8.20] - 2026-05-30
Added
- Analytics P0-P3 - ops KPIs (opt-in %, weekly active machines, activation J+7, feature adoption, launches by country, rating summary); email on `app_export_failed`; weekly ops report cron
- Desktop telemetry - `app_feature_used` (SRT, silence trim, proxy, ducking), session summary on close, export abandon detection, 1-5 rating prompt after first export
[0.8.19] - 2026-05-30
Changed
- Toolbar - Help and language menus grouped on the right next to FFmpeg status
[0.8.18] - 2026-05-30
Changed
- Help menu - log mode (Normal / Debug), privacy, license, and check for updates moved from the toolbar into Aide
[0.8.17] - 2026-05-30
Changed
- Help menu - single entry point for feedback and logs; removed duplicate beta feedback panel in the inspector and the toolbar Open logs button
[0.8.16] - 2026-05-30
Added
- Help menu (toolbar) - manual (site), write to team (prefilled mailto + diagnostics), open logs; always available (including post-1.0); `app_feedback_opened` with `source: toolbar_help`
[0.8.15] - 2026-06-08
Added
- Product analytics (opt-in) - desktop telemetry P0-P2: export lifecycle, project/feature usage, updater, FFmpeg, license, session heartbeats, export timing, beta feedback; enriched `/ops` dashboard (in-app funnel, D1/D7 retention, heatmaps, time-to-first-export)
- Site - `hero_cta_click` on Windows download CTA
[0.8.14] - 2026-06-07
Fixed
- License revocation - forced server check on status read; background poll every ~2 min while app is open (second OPS revoke no longer stuck on PRO)
- OPS dashboard - `ops.js` crash (`escapeHtml` duplicate) caused black login page; token paste/hash login and restore (test) button
Added
- `scripts/setup-ops-dashboard-token.mjs` - rotate `OPS_DASHBOARD_TOKEN` on Vercel (`--force`)
[0.8.13] - 2026-06-07
Added
- Remote license revocation (desktop) - `GET cutforge.app/api/license?machine_id=...` on startup and before export; clears local PRO + toast when revoked (fail-open offline, 5 min cache)
- Site (already deployed) - `license_entitlements` table, unified `/api/license` (check + OPS revoke), Paddle fulfillment records entitlements; license ops runbook (internal)
[0.8.12] - 2026-06-07
Fixed
- Export audio - embedded video audio follows the top overlay (V2/V3), not V1 underneath (preview parity)
- Dev launch - Rust export compile fix; `devCsp` for Vite HMR while production CSP stays strict
- Updater toolbar - status colours in `tauri dev` (green / blue after silent check)
- Empty timeline - 30 s ruler on first launch, zoom fits lane width
Security
- Production CSP: removed `unsafe-eval` from `script-src`; Sentry ingest allowed in `connect-src`
- `test:security` gate: npm + cargo audit (OSV optional)
Added
- OPS dashboard: `updaterChannel` on `app_launch` (public vs PRIVÉ)
- Sentry `captureAppException` on export, import, and project I/O failures
- Tests: export audio stack V1/V2/V3, updater dev, timeline empty layout, CSP `devCsp`
Added (historical - pre-0.8.10 draft notes)
Added
- Paddle Billing checkout via `GET /api/checkout` (`variant=monthly|yearly|choose`, `machine_id`)
- Paddle setup - Vercel env vars, sandbox vs live, price IDs
- App Passer en PRO opens `cutforge.app/api/checkout?variant=...&machine_id=...`
- Site pricing buttons wired to the same checkout API
- GitHub Releases publish script + `npm run release:github`
Changed
- License dialog (PRO): primary Fermer button; Retirer / Importer secondary; machine ID hidden when tier is PRO
- i18n: `common.close`; license hints reference Paddle checkout via cutforge.app
- Legal docs: Paddle as Merchant of Record
- `site/config.js`: `checkoutApi` replaces `checkoutBase`; `releasesUrl` -> `github.com/CUTFORGE/releases`
Notes
- Vercel: `PADDLE_*`, webhook (`PADDLE_WEBHOOK_SECRET`), license keys, `RESEND_API_KEY` - see Paddle setup notes (internal)
- Fallback: manual `scripts/sign-license.mjs` if webhook or email fails
- Installed app builds predating this work still use old checkout URLs - rebuild required
[0.8.10] - 2026-05-30
Fixed
- Desktop telemetry delivery - POST via Rust (`reqwest`) instead of WebView `fetch`; session launch flag only set after successful send
[0.8.9] - 2026-05-30
Fixed
- Desktop telemetry - public Windows build CSP blocked `fetch` to `cutforge.app` (`connect-src`); opt-in events were silently dropped
[0.8.8] - 2026-05-30
Fixed
- Privacy toolbar button (always visible) - telemetry opt-in was unreachable in 0.8.x because the License dialog is hidden before v1.0
[0.8.7] - 2026-05-30
Added
- Telemetry toggle in License dialog - re-enable or disable anonymous usage stats after declining the first-run banner
[0.8.6] - 2026-05-30
Added
- Auto-install FFmpeg on first launch (Windows): silent download of BtbN GPL build into `%APPDATA%\com.cutforge.studio\ffmpeg\bin\` with progress overlay; manual setup dialog only if auto-install fails
- FFmpeg GPL compliance: `licenses/` notices, site `/third-party` (FR/EN/RU), in-app Open-source licenses link, written source offer
- Timeline bar: Undo/Redo with ←/-> icons, zoom centered in toolbar
- Global shortcuts: Space play/pause, ←/-> seek ±5 s, ↑/↓ track navigation
- Ctrl + mouse wheel zoom on timeline scroll area
- Sticky track label column when scrolling timeline horizontally
- Site user manual (`/manual`, FR/EN/RU) linked from download section
- v1.0.0 checklist - must-have vs nice-to-have for v1.0.0 (internal)
Changed
- Zoom scale: 100 % = 60 s visible, 200 % = 30 s; minimum zoom 5 % (was 25 %); viewport-based `pixelsPerSecond`
- Undo/Redo moved from main toolbar to timeline bar
- Site header: brand icons and top-left label removed
- Neutral brand icon (OG + Tauri app icons regenerated from master artwork)
Fixed
- Legal page build template: header no longer re-adds brand icon on `build:legal`
- Fresh Windows installs without admin rights no longer block on FFmpeg setup when network is available
[0.8.5] - 2026-06-04
Added
- Hardware HEVC decode for export: CUDA -> D3D11VA (Windows) / VAAPI (Linux) -> CPU fallback; `hwdownload` formats fixed for 8-bit (`nv12`) and 10-bit (`p010le`)
- Export setting Hardware decode (`exportHwDecode`: auto / off) in export dialog + i18n
- `hasAudio` on import (probe) - video files without an audio track no longer break compositor export
- Segment export progress (`ffmpeg_progress.rs`, overlay UI) and clearer FFmpeg stderr in logs on failure
- E2E benchmark-classic-fx export spec (optional, replaces long-video)
Fixed
- Session restore: register media paths before autosave restore so preview video loads (not black) after app restart
- Preview seek on load when paused (`onVideoLoaded` applies playhead position)
- Compositor export for video-only sources: skip embedded-audio duplicate input; optional `-map N:a?`
- Removed dead compositor/util code; Rust warning cleanup
Changed
- Export performance - hardware decode chain and troubleshooting (internal)
- Vitest branch coverage threshold and additional unit tests
[0.8.3] - 2026-05-31
Added
- Export watermark `CUTFORGE-WATERMARK.png` (FFmpeg overlay, 30 % opacity, bottom-right)
- Buy PRO button in license dialog -> cutforge.app/#pricing
- Site pricing section (FREE vs PRO, €1/mo · €10/yr, manual activation note)
- Tests: `LicenseDialog` component, `license-urls`, E2E license dialog smoke, watermark FFmpeg E2E
Changed
- Watermark asset: classic logo PNG instead of text `drawtext` / FREE icon
- License / export i18n aligned with PNG filigrane wording
[0.8.2] - 2026-05-31
Added
- Phase 1 licensing: Ed25519 signed `license.json`, machine-bound activation, FREE/PRO badge in toolbar
- FREE export watermark (PNG overlay, bottom-right, enforced in Rust/FFmpeg)
- License dialog (import `.json`, copy machine ID), `scripts/sign-license.mjs`, `scripts/generate-license-keys.mjs`
- Splash screen fixed 3.33 s minimum while main window loads in background
- Branding icons FREE/PRO (`public/branding/`)
Changed
- Inspector clip tools panel label PRO -> Avancé (commercial PRO is separate `license` namespace)
- App/window icons aligned on FREE badge; neutral icon archived under `public/branding/archive/`
[0.8.0] - 2026-05-29
Added
- Landing site (`site/`) for cutforge.app (v0.8.0, i18n, Vercel config)
- Single-pass project normalization (`normalize-project.ts`)
- E2E Page Object (`e2e/pages/EditorPage.cjs`) and specs: export-cancel, relink-media, undo-redo (12 specs total)
- Quality toolchain: `typecheck`, ESLint 9, Prettier, Vitest coverage thresholds in CI
- `scripts/sync-version.mjs` propagates version to Tauri, splash, site, and E2E
Changed
- Split `export/compositor.rs` into `compositor/` module (policy, render, filters, audio, inputs, util, tests)
- Split `useSequencePlayback.ts` into orchestrator + `hooks/playback/` (RAF loop, media sync, preview style)
- E2E bridge gated (`DEV` or `VITE_E2E`); dedicated `build:e2e` mode
- Rust: `total_cmp` for f64 ordering (no `partial_cmp().unwrap()`)
Fixed
- `duplicateTextClip` guard when source clip missing
- Prettier/format consistency on playback hooks and new E2E specs
[0.6.7] - 2026-05-28
Added
- Sticker test suite: store placement, timeline compositing, preview overlay layers, FFmpeg rgba export chain
Fixed
- Sticker default position: first sticker on a track uses layout index 0 (was offset by one)
[0.6.6] - 2026-05-28
Version sync (no functional changes beyond v0.6.5).
[0.6.5] - 2026-05-28
Added
- Second text track (T2) on the timeline - subtitles/captions on two layers
- Double-click a text lane to add a title on T1 or T2
- Drag text clips between T1 and T2 with lane-accurate positioning
Changed
- New titles use the selected clip's text track, or T1 when none is selected
- Overlap rules apply per text track (same time allowed on T1 and T2)
- Older projects gain T2 automatically via `ensureDefaultTracks`
[0.6.4] - 2026-05-28
Changed
- Inspector panel renamed PRO (was « Phase C - Pro »)
- Dev launcher script renamed `CUTFORGE.bat` (was `lancer-cutforge.bat`)
Added
- PRO polish: keyframe list + timeline ticks, chroma sliders, warm LUT effect, SRT file import/export, silence trim preview with thresholds, 720p proxy generation, beat snap (B) / Shift+click delete, GPU encoder in export settings dialog
Fixed
- Phase C panel crash (invalid GPU i18n keys) - `0bf4fd3`
- Timeline clips misaligned when dragging between video tracks (V3 -> V2 / V1)
[0.6.3] - 2026-05-28
Added - Phase C (CC parity foundation)
- Keyframes - opacity, scale, position X/Y on clip timeline (preview + FFmpeg export)
- Effect stack - blur, sharpen, vignette per clip
- Chroma key - green-screen colorkey on export
- Beat markers - timeline markers + snap helper
- SRT import - subtitles to T1 text track
- Silence trim - suggestion from waveform peaks
- Proxy media - optional proxy path on assets (4K workflow)
- Export GPU preference - auto / software (x264) / NVENC
- Platform flags - cloud, mobile, marketplace (beta toggles)
- AI tools - STT / background removal planned (SRT + chroma available now)
- Inspector Phase C panel, Vitest + Rust tests, E2E `phase-c.e2e.cjs`
[0.6.0] - 2026-05-28
Fixed
- Export presets - aspect ratio from the settings dialog (e.g. Instagram 1:1) is applied on export instead of a stale project snapshot
- `normalizeProject` - preserves `exportPresetId`, ducking, and other optional meta fields sent to FFmpeg
Added
- Tests for Instagram / all social export dimensions (Rust + Vitest)
- `scripts/test-export-aspects.cjs` - optional ffmpeg/ffprobe smoke test for 16:9, 9:16, 1:1, 4:3
[0.5.0] - 2026-05-28
Added
- Text track UX - drag, trim handles, snap, overlap avoidance on T1
- Text clipboard - copy, cut, paste; split at playhead; duplicate
- Text inspector - position X/Y, timing (ms), fonts, outline, shadow, style presets
- Preview - drag selected text overlay to reposition
- Export - FFmpeg drawtext with font file, border, shadow on Windows
- E2E - WebDriver scenarios for text track (`e2e/specs/text-track.e2e.cjs`)
[0.3.0] - 2026-05-28
Added
- Phase B: social export presets (YouTube, Shorts, TikTok, Instagram)
- Project templates (vertical short, YouTube, podcast) on new project
- Text track T1 - static titles, inspector, timeline blocks, preview overlay, FFmpeg `drawtext` on export
- Sticker pack - SVG stickers on overlay track (V3)
- PiP transform - position X/Y, uniform crop, clip opacity (preview + FFmpeg export)
- Audio ducking - lower music on audio tracks when video dialogue is present
- Q / W - trim clip start/end to playhead on selected clip
- Preview crossfade - optional fade at clip end in sequence preview
- Roadmap - Phase B/C CC parity plan (internal)
[0.2.1] - 2026-05-28
Added
- Phase A montage: per-clip speed (0.25×-4×), reverse on export, transitions (fade / wipe / slide), scale & rotation
- Inspector Montage panel, color presets in Image, timeline snap (grid, playhead, clip edges)
- Playback shortcuts J / K / L (scrub back, play/pause, play)
- Rust export: `clip_montage` (speed, transform, per-junction xfade kinds)
- Tests: montage store/UI, snap, playback keyboard, `clip_montage` unit tests (Vitest + `cargo test --lib`)
Changed
- Preview respects clip playback rate and transform; scaled media clipped inside the preview pane
Fixed
- Preview overflow when clip scale > 100% (video no longer covers toolbar, timeline, or inspector)
[0.2.0] - 2026-05-28
Added
- App icon asset `public/cutforge-icon.png` (window title bar, favicon, splash screen)
- Tauri splash window at launch; closes when the editor shell is ready
- FFmpeg setup dialog and persistent user paths (`%APPDATA%\com.cutforge.studio`)
- Export segment disk cache and single-pass export for one merged segment
- Release scripts: `npm run fetch:ffmpeg`, `npm run release:win`, `sign-windows-release.ps1`
- Preview/export fidelity banners and localized export phases
- E2E: FFmpeg staging beside app binary, precheck before WebDriver run
Changed
- Version bump to 0.2.0 (package, Tauri, Cargo)
- stricter FFmpeg readiness: requires libx264 + HEVC decode for "ready" status
Fixed
- TypeScript build (i18n locales, `ToastKind`, unused imports)
- Crossfade no longer forces per-segment `filter_complex` (faster export)
- Export cache module compiles in release builds
[0.1.0] - 2025
Initial MVP: timeline editor, FFmpeg export, FR/EN/RU, Windows desktop (Tauri 2).