Commit Graph
1082 Commits
Author SHA1 Message Date
digital-garbageandClaude Opus 4.8 2c9755f6c8 editor: pass scene boundaries structurally — remove 'scene N' injection entirely
Root cause the user pushed on: the editor flattened all scenes into ONE prompt
string and Studio re-derived boundaries by parsing text, so a carry scene with no
transition needed an injected 'scene N' delimiter. The editor already KNOWS every
boundary (each generative unit is a scene) — it never needed to smuggle markers
into the prompt.

- timeline.build_combined_prompt: no longer injects anything (verbatim anchor +
  scene texts). New build_generation_scene_segments(project) lists the boundaries
  the editor already has (each unit's raw text, prefixed with its REAL transition
  so effects survive; carry = plain text).
- conditioning.split_scenes_from_segments: canonical split from an explicit scene
  list (reuses split_scenes per item for expansion/keys/effect, folds the anchor),
  same output shape as split_scenes. refine_v2 gains scene_segments and uses it
  when present (count-preserving: a text-less i2v scene keeps its slot, no anchor
  shift); falls back to text-splitting only for raw node-pack use.
- server/builder: editor sends scene_segments -> studio_settings.refiner.scenes.

Net: the generation prompt Studio encodes is now exactly what the user typed —
no 'scene N' anywhere, in the prompt or the conditioning. Tests updated to assert
the verbatim prompt + structural segments; new tests for split_scenes_from_segments
(boundaries, empty-scene preservation, anchor/key fold). Fallback path unchanged
(stash-verified zero regression). NOTE: montage generation needs GPU verification.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 18:50:11 +03:00
digital-garbageandClaude Opus 4.8 8dc163bca6 fix: generic 'scene N' split markers must never be encoded
Multi-scene bug: the Movie Editor injects a generic 'scene N' separator before
any scene that lacks a leading transition trigger (build_combined_prompt), purely
to force a boundary. split_scenes was splitting on those markers with placement
'start', which KEEPS the marker word in the new scene's text -> 'scene 1',
'scene 2', ... got encoded into every scene's conditioning. With a text-less
leading i2v scene this also produced a label-only first scene (renders as the
anchor with no prompt) and shifted each scene's content down by one.

Fix in the one canonical splitter: a generic 'scene <N>' label (not a real
custom trigger in the transition DB) now cuts SILENTLY -> boundary only, dropped
from both expanded (generation) and raw (editing) text. Real user/DB triggers
keep their configured placement, so 'cut'/'qcut' etc. are unaffected.

Regression test asserts the markers split but never appear in any scene's
expanded/raw text, and that a real trigger still leads its scene.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 18:25:46 +03:00
digital-garbageandClaude Opus 4.8 f513d485a9 opencut_ui: surface score_slider (FreeSliders) in Engine Settings
The Chain Sampler's Guidance section already exposes embed_guidance via the
sampler-knob path; add its score-space sibling the same way. Two new knobs in
SAMPLER_KNOBS (score_slider bool, score_slider_strength eta 0-3, dependsOn the
toggle) listed in the chain_guid section beside embed_guidance. Flows through the
existing sampler_inputs path (setSamplerInput -> _run_sampler_inputs -> builder ->
Chain Sampler node); refinement_key_input is already wired, so no backend change.
BachVid + KV-Lock need no UI (automatic, ride the refinement key).

Test: score_slider sampler_inputs pass through _run_sampler_inputs untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 18:05:35 +03:00
digital-garbageandClaude Opus 4.8 c25a49fb01 FreeSliders: score-space taste slider on Scene Chain sampler
Training-free concept sliders (arxiv 2511.00103) in noise-prediction space,
sourced from the learned taste (user's choice). New score_slider + strength(eta)
inputs on the Scene Chain sampler, additive/non-disruptive, reusing the same
learned liked direction + embed_guidance_source + refinement_key_input.

Mechanism: a per-scene model_function_wrapper synthesizes a +/- concept pair from
the base conditioning and the liked direction (no concept prompts), runs 3 forward
passes on quality-phase steps and combines eps_mod = eps_base + eta*(eps_+ - eps_-).
High-sigma steps stay single-pass = the paper's k-step base-only warmup, keeping the
2x cost off early steps. Video-only: +/- conds are audio-protected and the eps blend
is masked to the packed video stream. Composes with embed_guidance (its nudge cancels
in the +/- difference). Installed/torn down per scene in reverse order; threaded
through batch-training re-dispatch. Fully guarded -> falls back to base prediction.

Tests: tests/test_score_slider.py (5) — combine, warmup, eta=0 no-op, eta linearity.
Pre-existing 16 suite failures unchanged (stale-mock/splitter set); zero new.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 17:49:44 +03:00
digital-garbageandClaude Opus 4.8 56dac0a0ef KV-Lock Phase 2: variance-gated scheduler drives BachVid injection
Inversion-free adaptation of 'When to Lock Attention' (arxiv 2603.09657).
Track x0 prediction instability per step (relative step-change of the predicted
clean latent, video-masked = a cheap proxy for the paper's variance-of-x0
hallucination metric over a sliding window). High instability => the model is
still drifting => raise the shared kvlock_scale so BachVid holds the blessed
identity K/V harder; as x0 settles the multiplier relaxes toward base strength.

No DDIM inversion (LTXAV inverts poorly) — locks against the blessed K/V bank.
No-op unless a BachVid bank installed the shared scale list, so the two compose
cleanly. Wired into all three FunPack sampler loops after each model() call;
fully guarded, cannot break sampling. Tests cover capture/inject/scale + the
schedule's stable-vs-jumpy behavior and the no-bank no-op path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 17:14:06 +03:00
digital-garbageandClaude Opus 4.8 83822f3909 BachVid Phase 1: per-key raw K/V identity bank (capture + inject)
Training-free character carry across scenes/sessions (arxiv 2510.21696),
built on the existing LTXAV attn-hook infra. Capture raw K/V at IDENTITY_BLOCKS
during the mid-sigma window into a per-refinement-key temp bank; promote to a
blessed bank on liked ratings (EMA-merge, alongside bless_attn_weights). On
later runs with a blessed bank, lerp the running gen's K/V toward the blessed
identity at matched token positions (packed-/RoPE-safe analogue of the paper's
concat-attend). Wholesale inject at identity blocks (no spatial mask yet).

Exposes a shared kvlock_scale multiplier in transformer_options for the Phase 2
KV-Lock variance scheduler to drive injection strength per step (1.0 = off now).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 17:09:33 +03:00
digital-garbageandClaude Opus 4.8 9fb0ee267b path-planner Phase 2d: conditioning-variant routing
Route the conditioning variant from per-config outcome history, via the one
charter-safe surface: the INTERNAL value-function ascend+search (not user knobs,
so no WYSIWYG / hidden-settings violation). Sampler-owned visual ops stay on the
sampler (boundary law kept).

Directly serves the original complaint (Perfect not locking, Awful reproducing):
- _v2_path_conditioning_plan: matching-arm Beta posteriors -> liked-rate mean ->
  "lock" (>=0.6: hold the liked conditioning, skip the stochastic search),
  "explore" (<=0.4: widen the search to flee a disliked region), else "normal"
- value_function.search gains eps_scale to widen/tighten the search radius
- threaded conditioning_plan through ascend -> apply_scene_refinement_keys ->
  finalize; computed once per run from path_outcomes + prompt concepts; logged

Only active once the per-key VF is ready, since it rides the existing ascend path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 16:26:16 +03:00
digital-garbageandClaude Opus 4.8 b6f17f2b3b path-planner Phase 2c: Thompson/UCB explore-exploit seed routing
Upgrade the seed explore/exploit gate from a flat reuse chance to a proper
bandit over the path-outcome arms:
- _v2_path_arm_beta: Beta posterior over an arm's liked-rate (liked>=0.3 success,
  <0.0 failure, neutral ignored; Laplace prior)
- _v2_path_explore_decision: Thompson-sample theta per concept-matching arm vs a
  fresh Beta(1,1) explore arm; good arms exploit, dislike-dominated arms route to
  a fresh seed ("do something else")
- wired into _v2_choose_successful_seed (falls back to the flat gate with no data)
- shared _v2_path_matching_arms helper; _V2_KEY_REWARD + liked/disliked consts

5 tests incl. a statistical one: a strongly-liked arm rarely explores, a hated
arm almost always does.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 14:48:06 +03:00
digital-garbageandClaude Opus 4.8 2bd9318bb3 path-planner Phase 2: seed-lever avoidance routing
Make path_outcomes ACT via the one Studio->sampler lever wired today: the seed
(FunPackStudio.run -> _v2_choose_successful_seed -> seed output -> sampler). No
new data paths invented.

The existing seed chooser only exploited liked seeds with zero avoidance — the
headline gap. Now:
- recorder tags each seed sample avoid = reward<0 and not skip_value_function
  (Wrong-* excluded: the seed was fine, the words/identity were off)
- _v2_path_disliked_seeds: seeds that gave a low-quality result for matching concepts
- _v2_choose_successful_seed redraws a disliked fallback, drops liked-then-later-
  disliked seeds from reuse, and reports how many it avoided

Broader config levers (guidance/lora) need new wiring and are deferred pending
graph-topology confirmation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 13:14:40 +03:00
digital-garbageandClaude Opus 4.8 5731315b4b refiner: '-Just forget it-' truly leaves no trace
Audited every learning sink in the V2 rating flow. Rating-learning and the
Absolute store already honored skip_learning, but two feedback sinks ran gated
only by feedback_prompt — so a 'Just ignore it' run with typed feedback still
wrote advisor_feedback_history + intent_expansion_memory.

Add _v2_rating_is_discard (forget rating or auto-discarded refusal) and gate
both feedback sinks on it, without touching the active continue/fresh_prompt
modes that legitimately keep feedback.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 13:10:12 +03:00
digital-garbageandClaude Opus 4.8 99afd9cef7 path-planner Phase 1: per-scene path-outcome memory
Reframe ratings from local steering into global routing: every rating —
not just successful ones — is recorded as a labeled outcome on the per-scene
config "arm" that produced it, so a later planner can route away from arms
that keep generating disliked results.

- _v2_path_signature: arm = family + concepts + guidance config, seed EXCLUDED
  (seed is the random draw within an arm); md5 arm_id collapses identical configs
- _v2_update_path_outcomes: learns from EVERY rating, decaying counts so recent
  behavior dominates; records seed-level samples for later seed routing
- hooked at the shared per-scene learning hub + single-run path; stored in
  per-key state under "path_outcomes"

Pure instrumentation — no generation behavior change yet (Phase 2 = Studio planner).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 05:59:49 +03:00
digital-garbageandClaude Opus 4.8 89945bdb5e tools: showcase generator — auto gallery + walkthrough video from the tour
Drives the editor's built-in tour (?mode=tour, fully mocked — no backend/models/
GPU) with Playwright: serves the static frontend, walks window.TourGuide, and
screenshots each step (annotated with its spotlight + caption) while recording a
walkthrough video. Emits NN-*.png stills, an index.md gallery, and
walkthrough.webm/.mp4. Self-maintaining: new tour steps appear automatically.

No more screenshotting each button by hand. node_modules/ and out/ are gitignored.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 04:39:04 +03:00
digital-garbageandClaude Opus 4.8 e4e2f90484 tests: _FakeRoutes mock covers put/patch so the full suite can collect
The fake routes object installed into sys.modules as `server` only defined
get/post/delete; server.py also registers put (models) and patch (media), so
importing the real server.py during collection (e.g. test_server.py) raised
AttributeError and aborted the whole run. Add put/patch to the mock.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 04:28:25 +03:00
digital-garbageandClaude Opus 4.8 fa3a884528 Merge dev into main — Release 3.1.0
Brings the OpenCut Cutting Room rebuild, Anchor-as-guide, Mixed self-image
guide, autocomplete, and the Scene Builder / character / NormalizingSampler
removals onto main. Tree matches dev exactly (discards the obsolete
cutting_edge README doc link).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
v3.1.0
2026-06-21 04:17:13 +03:00
digital-garbageandClaude Opus 4.8 cdc3085ac1 Release 3.1.0
OpenCut-style Cutting Room rebuild, Anchor-as-guide source, Mixed self-image
guide, prompt autocomplete, Composer floating window + file management,
canonical scene splitter, Scene Builder / character / NormalizingSampler
removals. See CHANGELOG.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 04:16:24 +03:00
digital-garbageandClaude Opus 4.8 573e5f26eb README: rename 'Dev and Cutting Edge branches' → 'Dev and other non-main branches'
The cutting_edge branch is gone; generalize the section to cover short-lived
non-main branches without the 'cutting edge' branding, same warning.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 04:14:37 +03:00
digital-garbageandClaude Opus 4.8 0624341995 opencut_ui: show the anchor-image picker for Mixed scenes in the inspector
Mixed scenes never rendered an inspector image picker — renderSourceField only
called renderImageSource for eff === "image", even though renderImageSource has a
dedicated mixed branch ("Anchor image (mixed i2v)"). So a Mixed anchor could only
be set by dragging onto the timeline clip, unlike image/anchor_guide. Render the
picker for eff === "mixed" too, giving Mixed the same on-timeline + inspector image
visibility as the other anchor modes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 04:08:00 +03:00
digital-garbageandClaude Opus 4.8 3b1eeee130 opencut_ui: fix autocomplete Tab (trailing space) + orphaned menu in the corner
Two bugs from the Tab update:

1. Tab didn't finish the trigger at end-of-text. The skip-space regex included `$`,
   so when the caret was at the end of the field (the common case) NO trailing space
   was added — the menu then re-opened on the just-accepted trigger (it matches
   itself) and appeared stuck. Drop `$`: always add the space unless a space/delimiter
   already follows.

2. Orphaned menu stranded in the top-left with no way to dismiss it. The menu lives in
   document.body; when a panel re-render removes its host textarea, removal doesn't fire
   blur, so the menu was never cleaned up and a later scroll repositioned it against a
   detached element (rect 0,0 → corner). Now: open() sweeps stray .ac-menu (single menu
   app-wide) and bails if the textarea is detached; refresh()/position() close on a
   detached textarea; and a MutationObserver closes + disconnects when the textarea
   leaves the DOM, so it hides on its own.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 04:08:00 +03:00
digital-garbageandClaude Opus 4.8 c6e5e5f2a5 opencut_ui: Anchor-as-guide keeps the image as a real anchor (timeline + pipeline)
The first cut withheld the anchor_guide image (set_primary=False) to get an
empty latent "for free". That broke real (custom) pipelines: the image vanished
from the timeline and never reached the graph, so a downstream Image Transform
node — which derives width/height from the input image even when i2v is
bypassed — had no input and generation failed.

Corrected model: the image flows into the pipeline like any anchor (copied as
primary -> source_image / image_processing), shows on the timeline, and is
required. The EMPTY LATENT comes from bypassing the i2v node (the value-only
node_overrides), not from withholding the image. On the built-in pipeline there
is no bypassable i2v node, so it runs as a normal i2v anchor + frame-0 guide;
the inspector warns when no i2v node is declared.

- timeline: anchorMediaRef / SRC_ICON / appendSrcBadge show the anchor_guide
  thumbnail + a "guide" badge.
- store: _anchorAvailable / _continuesChainRun treat it as an anchor; drop keeps
  guide mode instead of forcing plain image.
- backend: _prepare_media / scene_anchor_media_refs / _anchor_media_ref /
  source_needs_anchor_media include anchor_guide; removed the now-dead
  anchor_guide_media_refs guide-only copy path (image is a normal anchor now).
- inspector: relabel to "Anchor image (guide mode)", warn when no i2v node set.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 04:00:19 +03:00
digital-garbageandClaude Opus 4.8 2f55814b6c opencut_ui: node search/filter available in every Add-Model mode
The "Filter nodes…" box only showed for "Any node" mode; role-based modes
filled the dropdown directly with no way to search. Now the filter is shown
for any selected model type and applies to role candidates and Any-node alike
(applyFilter drives both paths).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 03:47:42 +03:00
digital-garbageandClaude Opus 4.8 4f153cee99 opencut_ui: Mixed mode also attaches the scene's own image as a frame-0 guide
Mixed scenes carried prior-scene guides but the FIRST scene (nothing prior to
carry) got no guide attention at all — only the i2v anchor. Generalize the
anchor_guide self-image guide path to also cover mixed: each mixed scene's own
image is added as a reinforcing frame-0 guide (strength 0.35), merged on top of
the carried prior guides. Renamed build_anchor_guide_guides ->
build_self_image_guides. Mixed images are already copied as anchors, so guide
refs resolve via funpack_scene_media_refs with no extra media prep.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 03:46:14 +03:00
digital-garbageandClaude Opus 4.8 1a2b4636eb opencut_ui: add "Anchor as guide" scene source (image steers, empty latent)
New scene Source mode: the image is applied as a frame-0 guide via the
existing guide-attention path while the latent fed to the sampler stays empty
(text-to-video). The image is never the i2v anchor, so frame 0 is not locked.

Backend (timeline.py / server.py):
- SceneSource.guide_strength (0..1, per-scene; default 0.35).
- build_anchor_guide_guides() emits a frame-0 self-image guide per anchor_guide
  scene; merge_scene_guide_payloads() overlays it onto continuity/manual stacks.
- anchor_guide images are copied guide-only (set_primary=False) so source_image
  is never wired -> empty latent comes free in the built-in pipeline.
- _apply_node_overrides(): force widget inputs on built-graph nodes from a
  client-supplied node_overrides list (the optional custom-i2v bypass).

Frontend:
- inspector: Source option + guide image picker + strength slider.
- editor_settings: per-browser "Anchor as guide" section — declare a custom
  i2v node and the input/state to force on those runs (value-only). Built-in
  pipeline needs none of this.
- store: sends node_overrides only for runs containing an anchor_guide scene;
  pipeline_caps: anchor_guide is chain-only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 03:43:29 +03:00
digital-garbageandClaude Opus 4.8 ac0e4edd37 opencut_ui: roll-up Composer minimize in place + autocomplete finishes on Tab
Minimize now collapses a FloatingWindow to its title bar where it sits (a
window-shade), instead of sending a pill to a bottom-left dock. The button
toggles +/—; double-click the bar also expands. Removed the dock/pill code
and CSS.

Autocomplete accept (Tab/Enter/click) now appends a trailing space so the
trigger is "finished" and the menu doesn't re-open on the just-completed
trigger (it matched itself); skips the space when a space/delimiter follows.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 03:43:12 +03:00
digital-garbageandClaude Opus 4.8 886a2bb3a9 opencut_ui: fix styled text-overlay crash on newer Pillow (float bbox -> int)
multiline_textbbox() returns float coords on Pillow >= 10, so tw/th flowed into
Image.new() as floats -> "TypeError: 'float' object cannot be interpreted as an
integer" the first time a styled text overlay was exported. Round the bbox coords
to int before using them for sizes and offsets. Surfaced by running the (previously
PIL-skipped) test_render_text_overlay_styled in the ComfyUI venv; all overlay tests
now pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 17:04:50 +03:00
digital-garbageandClaude Opus 4.8 9d69f4bef8 opencut_ui: split_scenes cuts on expansion-keyed transitions (scene-drop fix)
The canonical generation/preview/key splitter (split_scenes) only treated a
shortcut as a scene cut when the shortcut's TRIGGER word was a key in the
transition DB. But split markers are commonly keyed by the EXPANSION phrase: a
"cut" shortcut expands to "Scene cut.", and the split marker is "scene cut.".
So the lookup `custom_map.get(_norm(raw))` missed, the shortcut was treated as
plain content, and NO cut was made — split_scenes returned one scene for
"A cut B cut C" while the verbatim editor split returned three. That disagreement
collapsed the timeline's middle scenes (and would have generated one scene).

Fix: when the trigger word isn't in the DB, also match the shortcut's EXPANSION
(`custom_map.get(_norm(exp))`). The generic "scene <N>" label is still NOT matched
on expansions, so an incidental "scene 2" inside a content shortcut never cuts.
Verified against the user's on-disk cut/qcut defs: split_scenes now agrees with
the verbatim split (2 scenes for cut x2 / qcut x2 / mixed). Added regression tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 17:03:28 +03:00
digital-garbageandClaude Opus 4.8 7ed0717f73 opencut_ui: fix shortcut autocomplete never suggesting in prose prompts
The query was the whole token since the last , ; \n delimiter, and a trigger only
matched if that entire token was a substring of it. Typing a normal multi-word
prompt grew the token past any short trigger, so suggestions never appeared.

Now match TRAILING WORD-RUNS of the token, longest first ("golden ho" before
"ho"), keeping substring matching so "@golden" still matches "golden". The longest
run that hits any trigger wins; its span is what acceptance replaces, so completing
a multi-word trigger can't duplicate words. Verified the matching across start-of-
field, mid-prose partials, post-comma, and no-match prose cases.

Also lifted .ac-menu z-index (9000 -> 99999) so it can never render behind the
Composer floating window when completing in the Compose tab.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 11:22:33 +03:00
digital-garbageandClaude Opus 4.8 247ab84e34 opencut_ui: inline clip reorder controls on the timeline
Reordering was Edit-menu-only (Move Clip Left/Right). Added ◀ ▶ buttons to each
clip's head bar (next to Remove) that call the same moveTimelineClip, disabled at
the ends. Works for both generative and video clips. (Add was already on the
timeline toolbar via + Add → Clip.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 11:12:05 +03:00
digital-garbageandClaude Opus 4.8 a534f8bb6f opencut_ui: hard-remove the character feature (no UI surface remained)
The rebuilt editor never exposed character creation/assignment, so the feature
was vestigial: dead frontend plumbing plus generation branches that only fired
for legacy/imported projects. Removed it wholesale per decision.

Backend:
- Deleted movie_editor/backend/characters.py and the /library/characters routes.
- timeline.py: dropped normalize_character_bible / build_characters_anchor /
  _load_character_map / _scene_character_prefix / character_media_refs_for_project
  and friends. effective_anchor/effective_negative_prompt now return the project's
  manual text; resolve_scene_identity_pin(cs) returns the project-level identity
  pin only. Removed Scene.character_ids and Project.character_bible fields and the
  character_ids fingerprint key.
- Continuity auto-guides keep working off continuity_settings.identity_pin_ref.

Frontend:
- store.js: removed state.characters, the character preview-key plumbing,
  load/save/deleteCharacter, sceneCharacterIds/toggleSceneCharacter, character_ids
  in patch/archive paths and exports.
- timeline.js: dropped clip-char badge rendering; api.js: dropped character routes;
  view_bus.js: dropped chars fingerprint; tour.js: dropped demo characters + copy;
  styles.css: dropped .clip-chars/.clip-char.

Tests: removed test_characters.py and the character-bible timeline tests; added
manual-anchor / manual-negative / project-identity-pin tests. 133 passed, 4 skipped.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 11:08:48 +03:00
digital-garbageandClaude Opus 4.8 41e0cc48d5 opencut_ui: drop dead .char-* / .plan-* CSS
Both class families had zero JS references in the rebuilt UI. Removed all of
.char-* (character inspector/chips — no surface in the new editor) and the
.plan-* plan-strip styling (plan UI is gone). Kept the two still-live classes
that share neither prefix's full set: .clip-chars/.clip-char (clip badges) and
.clip.off-plan (removed_from_plan marker).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 10:44:48 +03:00
digital-garbageandClaude Opus 4.8 a9001123bd opencut_ui: Composer file management — Replace/Merge import, Delete-all, Files tab
Composer pt.2 backlog (#6/#7/#8):
- Import now asks Merge (overlay, name-overwrite) vs Replace all (wipe first),
  for both shortcuts and split markers. Backend import_* gain a replace flag;
  routes read ?mode=replace.
- Delete-all buttons clear every shortcut+category / every split marker, via new
  clear_shortcuts / clear_transitions bridge fns + /clear routes.
- New Composer "Files" tab: on-disk file manager over the prompt-library JSONs and
  the refinement-key store (keys + sidecars + value/latent .pt) with size, per-file
  delete, and per-group delete-all. Path-traversal-safe (basename-only, root-checked).
  Deleting library JSONs reloads Shortcuts/Splits so no stale entries linger.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 10:41:32 +03:00
digital-garbageandClaude Opus 4.8 0dbeadec74 opencut_ui: richer text overlay styling (bold/italic/align/outline/shadow/box)
Centralized text styling in OverlayUI (applyTextCss + textStyleControls) shared by
the program monitor, the Add-text modal, and the inspector. Pillow export renderer
honors every prop (real bold/italic faces or faux stroke/shear).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 01:00:38 +03:00
digital-garbageandClaude Opus 4.8 df3ac62e46 opencut_ui: shortcut autocomplete, Add-shortcut picker, anchor toggle + Editor settings
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 22:57:06 +03:00
digital-garbageandClaude Opus 4.8 a1bf407e39 opencut_ui: fix image-drop anchor, preview stick, t2v removal, full rewiring
1. Image drop → i2v anchor: re-wire S.assignMediaToScene onto the timeline clip
   (it was orphaned when the Plan card, its only caller, was removed).
2. Full rewiring in Full control: nodes.core_producers() now enumerates every
   installed core node's outputs (Studio model/conditioning/sigmas, sampler
   latent/images…), so a custom slot (e.g. a replacement sampler) can source
   them via input_sources. core_graph() tags each output with source_id + lists
   slot consumers; Models shows all core outputs (tappable in Full control).
3. Preview stuck on the media-bin preview ('anchor'): clear the transient
   mediaPreviewId on transport scrub/seek (_seekNow), play (_play), and clip
   selection (selectScene) so the program resumes following the playhead.
4. Remove t2v ('empty') as a selectable scene source; default new scenes to i2v
   anchor. Anchorless scenes still fall back to t2v in the engine.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 20:07:18 +03:00
digital-garbageandClaude Opus 4.8 114e20ac48 opencut_ui: slim Scene options, Composer polish, managed category list
- Scene properties: 'More editing' → slim 'Scene options'; Frames/FPS hoisted
  to the always-visible body; effects (blur/fade/zoom) dropped here (now applied
  from the timeline + Add → Effects, same scene.effects); source trim, i2v
  guides, and Exclude kept.
- Composer: shortcut editor modal now stacks above the floating window (z-index).
- Composer button restyled to match the neighbouring panel tabs.
- Categories/sub-categories: persisted managed list (nested) in templates.py;
  shortcut editor uses Category/Sub-category dropdowns with inline '+ Add new…'
  mini-modals; Shortcuts '+ Add' is now a dropdown (Shortcut/Category/Sub-category).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 19:53:16 +03:00
digital-garbageandClaude Opus 4.8 1a1e3b5e77 opencut_ui: shortcuts gain Category / Sub-category (for the Compose tab)
- templates.py: persist category + sub_category on each shortcut (normalized,
  free-text; sub-category nests under category).
- Composer shortcut editor: Category + Sub-category inputs; list rows show a
  "category · sub" tag and filter on it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 15:43:48 +03:00
digital-garbageandClaude Opus 4.8 98a76a94f1 opencut_ui: Composer revamp pt.1 — Compose tab, drop Characters, declutter Properties
- Composer button moves next to the Assets/Preview/Properties tabs (was in the
  menu bar).
- Remove Characters entirely from the UI (Composer tab + the scene inspector's
  character chips). Backend character code left dormant.
- New "Compose" tab hosts the Global prompt (moved out of the inspector); stays
  in sync with the timeline, never clobbers active typing.
- Properties decluttered: drop Video transition, Blend length, Generation split
  marker and "Pause before next clip" from a scene, and "Split before scene 1"
  from the project — these are driven by the global prompt and timeline.
- Swap Import/Export arrows in Shortcuts & Splits (Import ↓ "to me", Export ↑).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 15:39:39 +03:00
digital-garbageandClaude Opus 4.8 499a68abde opencut_ui: Media Browser (Assets) is now media-only
Strip the five non-media tabs from the left panel — it shows projects + the
media bin and nothing else:

- Characters / Shortcuts / Split markers already live in the Composer window.
- Effects / Transitions are edited per-clip in the Properties inspector
  (Video effects + Outgoing seam), so the preset-apply tabs were redundant.

Removed the orphaned tab renderers and their helpers (editors, modal,
search/filter, characterForm). Updated the welcome tour: the old "Media
libraries / .bin-tabs" step now points at the Composer button, and the
split-marker hint points to the Composer.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 15:24:23 +03:00
digital-garbageandClaude Opus 4.8 a0afb9e906 opencut_ui: borrow OpenCut shell — 3-column NLE + floating Composer window
Reshape the editor frame to OpenCut's layout (Assets | Preview | Properties
over a full-width Timeline), keeping every panel's mount point so existing
modules keep working:

- index.html: single horizontal main-row of three resizable columns; preview
  is the flexible center, Assets/Properties flank it. Plan strip removed
  (recipe now lives in the Properties column per the one-timeline model).
- styles.css: new workspace layout + graceful column-toggle degradation;
  floating-window + Composer-button styling.
- app.js / layout.js: rewire splitters (--media-w / --properties-w / --timeline-h)
  and column-visibility chips for the new arrangement.
- floating_window.js: reusable OS-style window (drag / minimize-to-pill /
  maximize / close); foundation Models & Engine settings can adopt later.
- composer.js: Composer window hosting Characters / Shortcuts / Split markers,
  toggled by a header "Composer" button.
- remove plan_strip.js (superseded).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 15:18:47 +03:00
digital-garbageandClaude Opus 4.8 a303052941 opencut_ui: credit OpenCut in README Thank You section
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 14:53:39 +03:00
digital-garbageandClaude Opus 4.8 ea20c018f8 Movie Editor: removing a scene from the plan keeps its generated clip on the timeline
'Remove from plan' (plan card) now: if the gen-unit has a render, mark it excluded
(so generation + prompt skip it everywhere — reuses every existing !excluded filter,
no audit) plus removed_from_plan (hide from the plan strip, override the single export
skip so the clip still renders, and skip the 'excluded' dim styling). Ungenerated
scenes are still a plain delete. Inspector shows a 'Restore to plan' banner on an
off-plan scene; timeline marks it with a subtle dashed outline.

This retires ghosts for the plan-removal path: the removed scene persists as a real
result clip in the cut, not a separate ghost. New Scene.removed_from_plan field
(persisted). Backend tests green (62).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 10:22:26 +03:00
digital-garbageandClaude Opus 4.8 07eaec5690 Movie Editor: timeline cut order independent of plan order
The timeline is the result; its order is now project.timeline_order (scene ids),
which plan reorder never touches. buildPreviewSegments + _renderClips (export) read
this cut order via orderedTimelineScenes(); it's self-healing (drop gone ids, append
new scenes in plan order) and maintained on load + structure change, with a backend
field so it persists.

- Menubar 'Move Clip Left/Right' reorders the CUT (moveTimelineClip → timeline_order).
- Plan-card '← Plan / Plan →' reorders the PLAN (moveScene → scenes / generation order)
  without moving the timeline clip.
- view_bus fingerprints include timeline_order so a cut reorder re-renders.

Reordering the plan no longer moves or alters already-generated videos on the
timeline. Backend tests green (62). Empty timeline_order falls back to plan order
(back-compat). Still TODO: 'remove from plan keeps the clip on the timeline'
(ghost retirement) — entangled with generation/export skip semantics, do next.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 10:16:28 +03:00
digital-garbageandClaude Opus 4.8 93c8068b90 Movie Editor: i2v anchors drop on the Plan, not the timeline
The timeline is the rendered result, so setting up a generation must not touch it.
Removed the clip-level anchor drop and the timeline track's image->anchored-scene
drop. Image media now drops onto Plan cards (sets that scene's i2v anchor) or onto
empty Plan space (creates a new anchored scene). Video clips (finished results)
still drop on the timeline track. Plan-only image filter; teal drop-target hint.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 10:01:21 +03:00
digital-garbageandClaude Opus 4.8 4f562cf0ff Movie Editor: timeline clip shows what it was generated with, not live plan text
Completes untying plan edits from the rendered result on the timeline. The clip
is the RESULT, so it now labels itself from the frozen render prompt
(renderPromptForScene) instead of the live scene text — editing a scene's prompt
in the plan no longer mutates the already-generated clip's identity here (it just
shows 'edited' until you regenerate). Falls back to live plan text only when the
scene isn't generated yet. Video clips unchanged.

With the earlier immutable-length fix, a plan edit (prompt/length) now leaves an
existing generated video's content, duration, AND label on the timeline alone;
only regeneration updates it. Editorial props (effects/trim/audio) stay live.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 09:53:41 +03:00
digital-garbageandClaude Opus 4.8 af07b7bb25 Movie Editor: add Plan strip (scene recipes above the result timeline)
New plan_strip.js band (#plan-zone) above the timeline: compact recipe cards
(anchor thumb + prompt + status: not generated / in sync / edited), click to
select, chevron opens a full-width inline editor (prompt, source, anchor picker,
Generate this scene, Remove, Advanced -> inspector). Collapsible. Placed above
#split-bottom so the timeline splitter / --timeline-h math is untouched; it's a
bounded, additive band (dock flex:1 absorbs it).

Plan = 'what will generate'; the timeline below is the immutable rendered result.
Edits are quiet/debounced and the band won't rebuild while a field is focused
(no input disruption). Selection syncs with the timeline.

Phase 1 / additive: the inspector's per-scene panel is intentionally kept as the
full editor + fallback (the plan can be Hidden) — retiring/merging it and removing
ghosts are the next steps.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 14:00:46 +03:00
digital-garbageandClaude Opus 4.8 4fb7e66759 Movie Editor: remove 'Convert to video/scene' buttons from the UI
The convert verbs don't fit the revamped plan/result direction and need a
rethink (see deferred notes). Remove the toolbar buttons now and the two
inspector hints that pointed at them, so nothing references a control that's
gone. The convertToVideo/convertToScene store functions are left intact and
callable — only the UI entry points are removed; the rework comes later.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 13:48:51 +03:00
digital-garbageandClaude Opus 4.8 0c7fe14b79 Movie Editor: generated renders are immutable, full-length (no truncation by plan changes)
A render never recorded the length it was actually made at — sceneDurationSec
recomputed from the LIVE plan every time, so changing project/scene length
retroactively truncated already-generated videos and made their tail unreachable
in the preview, player, and final export alike.

Now each render freezes its real length at generation time (durationSec). A
generated scene in project (default) frames mode plays/lays-out/exports at that
frozen length; the project/scene default only drives the NEXT generation.
Explicit per-scene length (timeline/custom), slip-trim, and splits still win
(a split clears the frozen length so both halves revert to plan layout).

- store: renderDurationSec + _planDurationSec; sceneDurationSec is render-aware;
  _recordSegment freezes durationSec on scene renders and ghosts; trim/resize
  measure from the shown length; segmentDurationSec delegates ghost length to
  _ghostDurationSec (de-dupes the inline calc).
- inspector: scene duration hint shows 'Rendered ~Xs - plan Ys - Regenerate to
  apply' when a render is frozen at an older plan length.

Centralized in sceneDurationSec so timeline, player, audio offsets/durations and
the final stitch all agree. No-op in the common case (plan == render). Renders
made BEFORE this change have no frozen length and stay plan-driven until
regenerated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 13:33:57 +03:00
digital-garbageandClaude Opus 4.8 6d25c8c1c5 Movie Editor: real min/max/step on exposed controls + stop autosave from eating input
Exposed node controls (e.g. a LoRA strength in project settings) now carry the
node's actual min/max/step/default from object_info instead of step=1/no bounds:
- capture numeric widget meta at expose time and on link creation (models.js)
- apply it in the Models node editor and the inspector's Exposed controls
- backfill meta onto pre-existing exposures when Models is opened / refreshed

Typing an exposed value no longer gets disrupted: the field now carries a data-k
so the edit guard protects it, and setModelInput/setModelLink update in place +
debounce the server save (was one saveModels POST per keystroke, notifying twice
and rebuilding the field mid-type). Pending model saves flush on blur and before
generate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 12:38:22 +03:00
digital-garbageandClaude Opus 4.8 94ffbb3cda Movie Editor: fix inspector input/label/control UX papercuts
- Rebuild guard now protects only typed/dragged fields (text/number/range),
  not selects/checkboxes — so dependent controls (custom length input, Ken
  Burns knobs, Steer mode 'absolute', Embed/Mid-scene guide) reveal on the
  toggle instead of only after blur (inspector.js + engine_settings.js).
- Tag blend-length and video 'Source in' fields so non-quiet patchScene no
  longer yanks them mid-type.
- Blur % and Zoom amount % slider labels update live while dragging.
- Surface Width/Height in the Project Output section (out of the collapsed
  Advanced fold); leave Max scenes in Advanced.
- Custom scene length reflects its snapped value back into the field on commit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 12:28:31 +03:00
digital-garbageandClaude Sonnet 4.6 0d909f4b18 Fix: single-transition 'silent' split leaked the trigger word into conditioning
With exactly one transition trigger in the prompt (one "cut", one "qcut", etc.),
split_scenes produced anchor + 1 scene — so len(canon_scenes) == 1. The
previous guard `> 1` skipped the clean-text encode path, leaving
output_conditioning built from the raw prompt_to_encode which still contained
the trigger word. The CLIP encoder received "cut" and the model generated it
in audio.

Changing to `>= 1` ensures any split with at least one clean scene uses the
properly stripped scene text, even when there's only one scene to encode.
The chain sampler receiving a single conditioning entry is fine — it just
renders a single pass with no chaining.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 20:18:21 +03:00
digital-garbageandClaude Sonnet 4.6 ec61f169fe Remove FunPackNormalizingSampler (redundant)
Normalization is now available in both Hybrid Euler 2S and Distilled Flow
samplers, making the standalone Normalizing sampler redundant. Removes the
node class, its sampler function, two private helpers (_parse_norm_factors,
_apply_av_norm_factors), the Studio/Movie Editor "Normalizing" type option,
and the defaultNormalizing() factory. Stale "same as the Normalizing sampler"
tooltip references in both sampler nodes are updated.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 19:05:11 +03:00