Commit Graph
271 Commits
Author SHA1 Message Date
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
digital-garbageandClaude Opus 4.8 c2c9be6ce8 Remove the Scene Builder (Studio/Refiner) entirely
Deletes the FunPack Scene Builder node and the Studio Scene Builder feature
— the per-key scene database (scene_db / universal_memory / saved scenes),
the Studio "Scene" tab, scene-phrase authority over classification, and the
scene-database wildcard cleanup. It was redundant: helpful on paper but
effectively unused, undrivable from the Cutting Room, and a risk to shortcuts.

Removed:
- node registration (__init__.py, funpack.py) + web/funpack_scene_builder.js
- templates.py: scene-DB storage layer (load/save/normalize/empty_scene_db,
  SCENE_DB_VERSION/SCENE_STATE_FIELD/SCENE_CATEGORY_SOURCES, scene_store_path),
  all scene_* helpers, resolve_scene_database_wildcards, the FunPackSceneBuilder
  class, and the /funpack/scenes* routes
- conditioning.py: _v2_scene_builder_db / _v2_scene_memory_item /
  _v2_apply_scene_builder_authority / _v2_scene_builder_category_for_entry /
  _v2_sync_scene_builder_memory / _v2_resolve_scene_builder_wildcards (+ wildcard
  helpers + _v2_scene_key), the scene_db threading through classify/learning,
  the scene_category_locked phrase fields + their training branch, the
  state["scene_builder"] preservation, and the Studio scene_builder prompt mode
- web/funpack_studio.js: Scene tab, SB_MODES, scene_builder settings, renderScene,
  fetch/saveScene, the Session Scene-Builder section, and the Refiner banner/notice
- tests/test_scene_builder.py (whole file) + scene-builder tests in
  test_v2_category_alignment.py; the SceneBuilder example workflow + its doc;
  README link; Scene Builder mentions in docs/FunPackStudio.md

Kept intact: shortcuts (apply_prompt_shortcuts / shortcut DB), transitions and
the canonical split_scenes splitter, and FunPackRefinementKeyLoader. Studio now
always uses the connected positive_prompt. No new test failures (the 16/97
remaining in tests/ are pre-existing env/sampler failures); movie_editor 140 pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 22:31:31 +03:00
digital-garbageandClaude Opus 4.8 df011b927f Stage 2 Part B: "Wrong appearance" → consistency anchor
Reworks the "Wrong appearance" rating from a (now-removed) prompt-repair
signal into a conditioning-level consistency anchor (option b). "Wrong
appearance" now means "character consistency wasn't preserved" and steers
the next generation back toward the established character.

Capture (_v2_update_appearance_anchor, wired into both the single-run
learning path and the shared per-scene suite _v2_learn_scene_into_state):
  - good rating (like/nailed_it/loved_it/loved) → store the rated run's
    conditioning as the per-key "blessed appearance" (overwrite = last good)
  - wrong_appearance → store the rejected run's conditioning as the "drift"
global_state is already per-refinement-key, so both live with that key.

Apply (_v2_apply_conditioning_memory_impl, after the intent-family delta):
when the user rated the previous gen wrong_appearance, gently pull this gen
toward the blessed appearance (lerp 0.05) and repel from the drift (0.04),
reusing _v2_apply_conditioning_payload / _v2_repel_conditioning_payload. No
ramping; the existing 7.5% delta cap bounds the net effect. No-op when
nothing is stored or shapes mismatch.

Drops the dead wrong_categories field (zero consumers after Part A) and
keeps skip_value_function (the anchor is a conditioning nudge, not a reward).

Tests: 7 new unit tests (storage + overwrite + skip + pull/repel + idle +
non-trigger); updated test_wrong_appearance_rating_is_available for the new
semantics. Zero new failures vs HEAD (the 10/31 remaining are pre-existing
env failures from missing server/comfy modules).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 18:44:55 +03:00
digital-garbageandClaude Opus 4.8 e39a64de57 Stage 2 (2/3): delete dead prompt-repair methods + their tests
Removes the now-unreferenced repair-only machinery left behind after
Stage 2 (1/3) neutralized the application:
  - _v2_prompt_repair_text_allowed
  - _v2_emphasized_prompt
  - _v2_repair_prompt_for_missing_axes and the repair-candidate helpers
  - perfect_repairs / rejected_repairs storage + perfect-repair eviction
    note in the intent-family learn path
Shared helpers still used by intent-alignment (e.g. _v2_repair_intent_roots,
_v2_repair_candidate_matches_intent, _v2_prompt_contains_text) are kept, as
is the repair_feedback / active_repair_axes "what's missing" signal the
advisor reads.

Deletes the 11 category-alignment tests that exercised the removed methods
directly. No new test failures (the 10/31 remaining are pre-existing env
failures from missing server/comfy modules).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 18:25:44 +03:00
digital-garbageandClaude Opus 4.8 65816e353a Stage 2 (1/3): remove the prompt-repair application + param
Neutralize the repair application in refine(): the intent-aligned prompt is
encoded as-is — perfect-repair phrase injection, missing-axis repair, and the
emphasis pass are gone. The advisor remains the only prompt-rewriting path, and
repair_feedback/active_repair_axes is KEPT (it's the 'what's missing' signal the
advisor still reads). Drop the prompt_repair param from refine(), INPUT_TYPES,
FunPackStudio, and both UIs (web + engine_settings).

The dead repair-only methods (_v2_repair_prompt_for_missing_axes, perfect-repair
phrases, etc.) come out in the next commit; shared helpers like
_v2_repair_intent_roots (used by intent alignment) stay.

Deleted the now-obsolete test_repair_candidates_saved_as_json_lists (tested the
removed injection). No new test failures vs dev.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 17:15:28 +03:00
digital-garbageandClaude Opus 4.8 91affc5359 Stage 1 cleanup: delete dead splitter method; preview uses split_scenes
Generation now reads split_scenes, so the duplicate _v2_split_prompt_by_transitions
method has zero callers — deleted. bridge.parse_timeline (the 'what Studio sees'
preview) now derives from split_scenes too, so the preview's scene count/boundaries
match generation exactly (no spurious 'split produced N but timeline has M' warnings).

The lossless RAW editing split (parse_timeline_verbatim / split_timeline_verbatim)
stays separate — it has a genuinely different lossless requirement (round-trips the
exact typed text). It still uses the old offset-projection path; converting it to a
lossless piece-walker is the one remaining Stage-1 loose end.

Tests: 33 + 140 pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 13:20:28 +03:00
digital-garbage 9df7c654ac Reapply "Stage 1: generation reads split_scenes too — guard removed"
This reverts commit 1b98baaa3fbcfd4e4cd6f834401b30e36afe1e1e.
2026-06-15 13:16:46 +03:00
digital-garbageandClaude Opus 4.8 2fae920839 Restore generic 'scene N' split — but literal-only (Movie Editor needs it)
Dropping the generic scene-N pattern broke the Movie Editor: build_combined_prompt
(for_generation) INJECTS 'scene N' markers into the generation prompt to force a
split for any unit whose text lacks a leading transition trigger. Without that
recognition the second unit never split -> 'scene 2 exists only on the timeline,
not generated'.

split_scenes now matches the generic scene-N label again, but ONLY in its
literal-text scanner (never over shortcut expansions). So an editor-injected /
user-typed 'scene 2' cuts, while a 'scene 2' buried inside a shortcut expansion
does not — fixing both the user's phantom split AND the broken montage.

For the reported prompt the piece-walker now returns 2 scenes (was 4), matching
the old generation splitter's 2 -> the guard should pass and keys attribute while
the chain/guides keep working.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 12:39:52 +03:00
digital-garbage 38509ea0d3 Revert "Stage 1: generation reads split_scenes too — guard removed"
This reverts commit 8fa840fd1305585b50bcc095477953a3bb9e9263.
2026-06-15 10:38:31 +03:00
digital-garbageandClaude Opus 4.8 b1e646efba Stage 1: generation reads split_scenes too — guard removed
Generation now builds its per-scene encode texts AND its per-scene keys from
the SAME split_scenes(raw) call (expanded scene text via the existing
_v2_transition_scene_texts anchor-prepend). Attribution, preview, reset and
generation are now one split, so scene count/boundaries can't disagree — the
SCENE SPLIT MISMATCH guard + diagnostic are deleted.

This also fixes WHERE generation cuts: it used to split the EXPANDED prompt
(boundaries from whatever trigger words survived expansion — e.g. the 'cut'
in 'Scene cut.'), not at your qcut/cut markers. Now it cuts at the real raw
triggers, so scene 1 = qcut..(keyA,keyB), scene 2 = ..(cs), as intended.

Behavior-changing on the generation path -> needs an in-app smoke test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 10:30:29 +03:00
digital-garbageandClaude Opus 4.8 02b2657324 Stage 1: rewrite split_scenes as a piece-walker (no offset projection)
The verbatim/offset-projection splitter mangled real prompts: long shortcut
expansions desynced the raw<->expanded offset map (empty anchor, qcut+cut
lumped), the hard-coded generic 'scene N' pattern split on incidental text
('scene 2' inside an expansion), and re-scanning expansions re-triggered on
words like the 'cut' inside 'Scene cut.' — 4 phantom chunks instead of 2.

split_scenes now walks _expand_with_map's ordered pieces ONCE: a boundary is
created only by a real transition trigger (a shortcut whose trigger word is in
the transition DB, or a literal typed trigger); expansion CONTENT is never
re-scanned; the generic scene-N pattern is dropped. Each keyed shortcut adds
its key to the current scene; the leading run is the anchor (keys fold into
all). Returns raw + expanded text + keys + effect per scene.

For the reported prompt this yields exactly 2 scenes: [keyA,keyB] and [cs],
with 'scene 2'/'Scene cut.' no longer splitting. Tests updated to use real
triggers + a regression test for the expansion-trap. 21 + 140 pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 10:28:54 +03:00
digital-garbageandClaude Opus 4.8 95c97123dd Stage 1 (diag): dump both splits on SCENE SPLIT MISMATCH
The mismatch is structural, not a transform: generation splits the EXPANDED
prompt (qcut/cut already replaced by their expansions) while attribution
splits the RAW prompt (qcut/cut still live as triggers). Dump both splits'
scene texts + keys so we can see exactly which words cause the raw split to
over-count, before building the unified raw-first splitter.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 10:05:50 +03:00
digital-garbageandClaude Opus 4.8 d1458eb681 Stage 1: repoint attribution + reset onto canonical split; remove band-aids
resolve_scene_refinement_keys now derives purely from split_scenes — drops
the scene_count parameter AND both divergence fallbacks (the band-aids).
Generation reads per-scene keys from the canonical raw split and GUARDS that
its text-split count (prompt_to_encode) matches; on mismatch it screams and
falls back to default-key attribution rather than land a key on the wrong
scene. bridge.scene_refinement_keys + the /preview callers drop scene_count.

Reset (_v2_reset_prompt_keys) now wipes refinement_key_pool_for(prompt), so
the pool is one canonical answer shared with the reset-confirmation modal.
That removes the last user of prompt_scene_shortcut_keys, so its entire
internal split is deleted (and its 3 tests, covered by split_scenes tests).

Tests: 20 refinement-key + 140 movie_editor pass. Generation path needs an
in-app smoke test (no model here) — the guard makes a desync loud, not silent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 09:52:52 +03:00
digital-garbageandClaude Opus 4.8 58a4f9b52b Stage 1a: canonical split_scenes (additive, not yet repointed)
One rich scene model {anchor, scenes:[{index,raw,keys,effect}]} that every
consumer will derive from — editing (raw), preview (raw->expanded),
attribution (keys), reset (pool = union of keys), generation. Built on the
existing shortcut-aware verbatim splitter + refinement_keys_in_text, so it
can't disagree with itself. Nothing repointed yet; consumers still on their
own splitters until the staged repointing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 09:41:09 +03:00
digital-garbageandClaude Opus 4.8 6338c39048 Refinement keys: read keys per scene, drop the count-compare guesswork
Attribution was re-splitting the raw prompt independently and comparing
scene counts, then guessing on mismatch (all-keys union -> cross-training,
or empty -> keys not detected, incl. single-scene-with-keys). Both the
80MB cross-training and Darki's "custom uploaded keys not detected" trace
to that.

resolve_scene_refinement_keys now reads each scene directly: split with
the shortcut-aware split_timeline_verbatim (same scenes generation uses)
and collect, via new refinement_keys_in_text(), the keys whose shortcuts
fired in each scene (anchor keys apply to all). No scene-count compare, no
union/empty fallback except a genuine multi-scene misalignment. Single
scene with a custom key is detected; each scene gets exactly its keys.

Reverted the original-text scan added to prompt_scene_shortcut_keys (it
desynced that splitter from parse_timeline/generation and caused the
detection regression); it's now used only for session-reset all_keys.

Training law: a scene owned by custom key(s) trains ONLY them; the project
default key is left untouched and learns solely from scenes with no custom
key. Tests added for all three behaviors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 07:47:50 +03:00
digital-garbageandClaude Opus 4.8 f23e8cd32e Stop prompt-repair ratings from poisoning the reward assets
Wrong-* ratings (appearance/details/action/combos) are prompt-REPAIR
signals — "good gen, wrong words/identity" — not quality rewards. They
were feeding their 0.0/low reward into both value-function training and
the keyless Absolute taste store, stamping visually-good conditioning as
a low-value valley. The VF ascent (now always the default key, applied to
every scene) then pushed conditioning away from good regions into drift /
wrong-character / distorted gens; Absolute stored good gens as global
bad-taste.

Wrong-* now carry skip_value_function: still drive prompt repair + the
relative per-key direction/category memory, but train no reward asset.
Quality ratings (Missing-*/Perfect/Nailed/Awful) unchanged. Gated all 3
relative VF call sites + _v2_learn_absolute. Preventative only — keys
poisoned before this fix still need reset/retrain.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 23:52:07 +03:00
digital-garbageandClaude Opus 4.8 ab4f78695d Multi-key: stop training every refinement key on every clip
Per-scene key attribution diverged from the generation split whenever the
advisor rewrote prompt_to_encode away from the raw prompt, so
resolve_scene_refinement_keys hit its all-keys UNION fallback and assigned
every key to every scene. That union got persisted into the run and read
back at rating time, training every key on every clip (value_fn bloat).

- prompt_scene_shortcut_keys now scans both expanded and original text
  (mirrors split_timeline_verbatim), so identical structure -> matching
  scene count -> precise attribution far more often.
- Divergence fallback is now default-key only (empty sets), not the
  all-keys union; a diverged run under-trains instead of cross-training.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 23:22:12 +03:00
digital-garbageandClaude Opus 4.8 643ca447c0 Run VF ascend+search once on the merged scene, not per key
Per-scene multi-key steering ran the value-function ascend+search inside the
per-key loop, then averaged. That injected independent search noise per key and
let a poorly-fit fresh key's VF ascend toward a bad optimum, which the averaging
baked in — a body-horror path. Now each key contributes only its learned
directions (per-prompt conditioning memory, already delta-capped); the merge is
formed and magnitude-disciplined, then a single ascend+search runs on the merged
result using the always-on project default key (the most-trained, most stable VF).
Keyed single-key scenes also now ascend with the default VF rather than that one
key's, for the same stability reason.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 18:58:27 +03:00
digital-garbageandClaude Opus 4.8 bc0d035125 Bound multi-key scene merge to the single-key magnitude regime
Per-scene multi-key steering averaged each key's independently steered (and
VF-ascended/searched) conditioning with no magnitude discipline. Averaging
tensors that point different directions shrinks per-token magnitude — and
collapses it toward zero when keys disagree — leaving multi-key scenes weaker and
further-drifted than the validated single-key path, which free-ran into warped /
body-horror output (worst on simple prompts, fresh keys).

Re-impose the single-key tail on the merged result: cap the delta vs the raw
scene encode to 8%, then renormalize to its per-token norm. Capping before renorm
is what keeps a near-zero (disagreeing-keys) mean from being amplified into noise;
single-key scenes are unchanged. Does not address the separate question of
ambiguous "wrong appearance" ratings poisoning a key's value function.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 18:47:53 +03:00
digital-garbageandClaude Opus 4.8 2934afec7e Store refinement keys as readable <key>.json (no hashing); overwrite-or-cancel on import
The key name is now the filename: a key "123" is refinements/123.json, listed by
stem and resolved directly by name everywhere (Studio, loader, Editor, sampler).
This fixes shortcuts spawning ghost keys — a dropped/loaded <key>.json is found
by the refiner's own path lookup with no scanning or adoption needed. Sidecars
keep a <key>.<mode> suffix (value function, sampler context, latents); only keys
that aren't a valid filename fall back to the old <prefix>_<md5> hash.

Clean break: legacy hashed files are not migrated (and are hidden from the key
list rather than shown as hash names). Exports now download as <key>.json so a
re-dropped export is already canonical — no tolerant filename/inner-field
reconciliation layer needed.

Import now prompts overwrite-or-cancel on a name collision (409 -> confirm ->
retry with overwrite), in both the Editor and the Refinement Key Loader node.
413 chunked upload (Vast.ai / Runpod proxy body caps) retained.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 18:05:53 +03:00
digital-garbageandClaude Opus 4.8 2fde2e8506 Fix editor timeline losing scenes when a trigger is also a shortcut
split_timeline_verbatim expanded shortcuts before detecting transitions, so
a cut marker that is ALSO a shortcut (e.g. qcut/cut, common now that cut
markers carry refinement keys) had its trigger word replaced before
detection -> the split was lost or misplaced ("scene 2 removed, scene 1
shows scene 2's prompt"). It now ALSO scans the original verbatim text for
triggers and merges with the expanded scan; trigger-shortcuts are caught at
their true offset, shortcut-driven splits and plain triggers are unchanged,
and the dedup collapses duplicates. Lossless round-trip preserved.

- conditioning.py: original-text trigger scan in split_timeline_verbatim.
- tests: user's qcut/cut case (2 scenes, actions 10|20,30, lossless) +
  shortcut-driven split still works.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 10:27:57 +03:00
digital-garbageandClaude Opus 4.8 3b719d098e Revert over-aggressive verbatim-split guard
The shortcut-internal-cut guard disabled the supported 'shortcut whose
expansion resolves to a transition' splitting (see project prompt model),
so scenes stopped splitting at all. Reverts split_timeline_verbatim to the
prior behavior; the real drop/shift bug needs a targeted fix with the
user's actual prompt + shortcut definition.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 10:17:55 +03:00
digital-garbageandClaude Opus 4.8 209466995b Fix editor timeline dropping scenes on shortcut-internal cuts
split_timeline_verbatim detected scene cuts in EXPANDED text and projected
them back onto the original. A cut living inside a shortcut's replacement
got projected onto the shortcut's edge; colliding/early boundaries were then
deduped away, dropping a scene and shifting the rest ("scene 2 removed,
scene 1 shows scene 2's prompt") until reload. This surfaced more once
shortcuts could carry refinement keys (more key-bound shortcuts in prompts).

The editor treats shortcuts as opaque (they only expand for preview/
generation), so the verbatim splitter now ignores any transition match that
starts inside a shortcut expansion. Literal user-typed markers still split;
generation still expands and splits unchanged. Result round-trips losslessly.

- conditioning.py: _starts_in_shortcut guard in split_timeline_verbatim.
- tests: shortcut-internal cut is ignored + lossless; literal cuts still split.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 10:11:51 +03:00
digital-garbageandClaude Opus 4.8 c8ec0e3d55 Session Reset wipes all prompt keys; warn with the key list
Per-scene multi-key learning trains every refinement key whose shortcut
fired in the prompt, so a reset must clear them all — not just the
project/default key, which left stale per-key state behind.

- conditioning.py: _v2_reset_prompt_keys() — on reset_session, union the
  non-default keys from the raw positive + intent prompts and reset/save
  each (primary key excluded; main flow already handles it). Reported in
  the state status string.
- store.js: "Reset Studio session" now confirms before arming, listing
  every key it will wipe (default + non-default keys in the prompt, from
  the preview's scene_refinement_keys). Disarming does not re-prompt.
- tests: union/primary-exclusion + no-op cases.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 09:53:40 +03:00
digital-garbageandClaude Opus 4.8 b78de23ccd Show per-scene refinement keys in the Movie Editor preview
Surface, before generation, which refinement key(s) each scene will steer
with — exactly matching the generation-time resolution.

- conditioning.py: extract resolve_scene_refinement_keys() as the single
  source of truth; FunPackVideoRefinerV2._v2_scene_refinement_keys now
  delegates to it (no behavior change).
- bridge.scene_refinement_keys(): preview payload per scene — explicit
  non-default keys, or the project default key when none fired.
- server /preview: attach scene_refinement_keys (both gen and non-gen
  branches), resolved against the project's refinement_key.
- inspector.js + styles.css: per-scene key chip in the timeline preview
  (avg when >1; greyed "(default)" fallback).
- tests: resolver/Studio parity + bridge preview payload.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 09:46:21 +03:00
digital-garbageandClaude Opus 4.8 1a475f73d4 Add multi-refinement-key support to the Movie Editor
- Shortcuts carry an optional refinement_key (templates model + expansion);
  editor gains a "Use non-default refinement key" checkbox + field.
- Project-level Refinement key field (Studio engine card) wired through
  server -> builder into FunPackRefinementKeyLoader (settable in any mode).
- Per-scene key attribution (prompt_scene_shortcut_keys): keys whose shortcuts
  fired in a scene; anchor keys count for every scene; union fallback on
  rewrite/count mismatch.
- Per-scene conditioning merge: steer with each participating key's state and
  average (one key = substitute, none = default), replacing the default-key
  relative steering for keyed scenes.
- Multi-key rating: full per-scene learning suite + value fn trained into each
  participating key's state.
- Tests for shortcut key surfacing, expansion tagging, per-scene attribution,
  fallback, and keyloader injection.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 00:01:35 +03:00
digital-garbage df4e7b4a9c Movie Editor: per-scene Refiner ratings, clip export trim, NLE polish.
Editor chain runs pass multiple scene ratings to Refiner for per-scene learning;
export trims chain output to the selected scene. Also includes parse bridge fixes,
timeline NLE gaps, and seam UI cleanup.
2026-06-11 14:14:43 +03:00
digital-garbage b72878f866 Add Pulse temporal style with per-scene ease-down segments
Introduces a new temporal_style option that cycles motion→hold ramps
across each scene's denoise trajectory via a segmented frame_rate wrapper.
Wired through Studio, engine settings, chain sampler conditioning tags,
and build_enhancements for single-scene workflows.
2026-06-10 16:50:19 +03:00
digital-garbage ee9edb30c9 Move seed to Chain Sampler and randomize by default
Remove project-level seed from the inspector; resolve a fresh random seed
on each Generate unless sampler_inputs.seed is set. Preview and validation
use the optional fixed seed for shortcut expansion only. Default prompt
repair to off after action-bleeding reports.
2026-06-10 16:19:47 +03:00
digital-garbage 524ff4906f Fix Movie Editor queue: allow __funpack_continue__ in Studio rating combo
ComfyUI /prompt validation requires rating overrides to be in V2_RATING_LABELS.
The editor sends MOVIE_EDITOR_CONTINUE_RATING when no scene is rated; add it to
the combo list (no |loved variant) so generation queues without value_not_in_list.
2026-06-10 15:22:28 +03:00
digital-garbage f25cad5a3d Movie Editor: continue Studio refinement when scene is unrated
When the user regenerates without rating, send a continue-refinement token
instead of "-Just forget it-" so Studio still applies session memory and
active repairs. Learning is skipped until the user rates; first runs with
no prior session still use Initial discovery.
2026-06-10 14:36:49 +03:00
digital-garbageandClaude Opus 4.8 99449e33ac Movie Editor: verbatim split via expand -> split -> compact-back
Previous splitter tried to detect transitions WITHOUT expansion, so prompts whose
transitions come from shortcuts (e.g. qcut -> '...cuts to the next scene') never
split — everything landed in one scene.

Now split_timeline_verbatim follows the correct order internally:
1. _expand_with_map() expands shortcuts exactly like apply_prompt_shortcuts while
   recording a position map (expanded offset -> original span).
2. detect transitions + placements in the EXPANDED text and split as Studio does
   (text before the first transition = anchor).
3. compact boundaries back onto the ORIGINAL via _project_offset(): a boundary inside
   a shortcut expansion moves the WHOLE original trigger token to one side per
   placement (start -> leads next scene; end/silent -> trails previous).

Result is lossless verbatim chunks. Verified: 'CHAR: a woman, man qcut hug cut hug
kiss' -> anchor 'CHAR: a woman, man', scene1 'qcut hug cut', scene2 'hug kiss'.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 10:17:52 +03:00
digital-garbageandClaude Opus 4.8 b3daa8dab9 Movie Editor: verbatim global prompt as source of truth (lossless split)
The global prompt is now the verbatim source of truth. New conditioning helper
split_timeline_verbatim() splits it into anchor + scene chunks using shortcut-aware
transition boundaries but WITHOUT expanding shortcuts or dropping any word, so
anchor + scene texts concatenated reproduce exactly what the user typed. A 'start'
trigger leads the new scene; 'end'/'silent' trails the previous chunk.

- build_combined_prompt is now a pure join (anchor + scene texts, single spaces) —
  no injected scene markers. Generation sends this verbatim prompt to Studio, which
  expands shortcuts / splits by transitions / applies the anchor as it always does.
  So editing a scene rewrites only its chunk and the global prompt = concatenation
  (nothing un-typed ever reappears).
- bridge.parse_timeline_verbatim + parsed_verbatim on /parse and /preview.
- applyGlobalPrompt / syncFromPreview consume parsed_verbatim (authoritative).

Example: 'CHAR: a woman, man qcut hug cut hug kiss' -> anchor 'CHAR: a woman, man',
scene1 'qcut hug cut', scene2 'hug kiss'.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 09:50:37 +03:00
digital-garbageandClaude Opus 4.8 480e3620a1 Temporal styles: automatic per-scene 'auto' director (heuristic baseline)
Adds temporal_style='auto': Studio classifies each scene's prompt for motion
energy and bakes a continuous frame_rate multiplier into that scene's
conditioning metadata; the Scene Chain Sampler applies it per scene via a
layered model_function_wrapper (composes with embed guidance, restored in
install order). Concrete styles keep the global build_enhancements path
unchanged.

- ltx_enhancements: TEMPORAL_STYLES gains 'auto'; single-source TEMPORAL_STYLE_MULT
  table; classify_temporal_intent() keyword director (energy->punchier mult<1,
  stillness->hold mult>1, loop flag); factored make_temporal_wrapper() shared by
  global + per-scene paths; build_enhancements skips the global wrapper for auto.
- conditioning: _v2_apply_auto_temporal() bakes funpack_temporal_mult/label/loop
  into each entry inside the single finalize hook; both refine_v2 returns pass
  temporal_style + the run prompt as per-scene fallback text. 'auto' added to V2
  node dropdown.
- samplers: _scene_temporal_mult() reader + per-scene temporal wrapper around
  _sample_chunk in the scene loop.
- web: 'auto' in the Studio dropdown + hint text.

Heuristic is the baseline director, structured so a reward-driven override can
replace the multiplier per intent-family later. loop's RoPE coordinate trick is
still unimplemented (inert flag only); auto detects loop intent but does not yet
honor it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 17:58:48 +03:00
digital-garbageandClaude Opus 4.8 88a226da93 Session Reset: clear keyless 'default' bucket + Absolute global store
clear_refinement_data() early-returned on an empty refinement_key, but a
keyless run stores its blessed/attn maps, creativity latent and velocity-bias
trajectories under the 'default' bucket. So a keyless Session Reset no-opped
and those disk-persisted stores survived restart too -- the first fresh run
felt cleaner than every later run. Normalize empty key to 'default' (matching
the write side) so reset actually wipes that bucket.

Also wire the keyless Absolute taste store (FUNPACK_ABSOLUTE_KEY) into reset:
it learns from every rated run regardless of steer_mode but had no clear path,
so it would survive reset + restart forever. Delete its state json + value fn
on reset_session.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 17:35:59 +03:00
digital-garbageandClaude Opus 4.8 e4a74dc3b9 Interactive Guessing: make noise-seed freezing optional
Add guess_freeze_seed (default True) threaded refine_v2 -> _v2_pack_batch
-> _v2_pack_guess_ladder and the Studio refine_v2 call. Frozen = every rung
shares one seed (only conditioning strength varies; cleanest for learning).
Off = distinct seed per rung (varied compositions too). New "Freeze seed"
toggle in the Interactive Guessing config; persisted on Arm.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 15:48:01 +03:00
digital-garbageandClaude Opus 4.8 c8e4f2c404 Interactive Guessing: UI trigger + Phase-3 learning & dual auto-cap
UI: Batch Training tab gains Mode (Regular / Interactive Guessing),
Direction, Range, and a Learning toggle; Arm sets refiner.guess_* +
batch_learning; auto-disarm clears guess_mode; rating list shows each
rung's [x factor]; Submit passes the learn flag.

Learning (batch_training.py): submit honors learn=false (pure generation,
no training). Guess batches detected via guess_factor -> _learn_guess_ceiling
finds the furthest-pushed acceptable rung before quality broke and stores a
per-key safe ceiling (absolute spread + factor) via _store_guess_ceiling.

Dual auto-cap (refine_v2, normal runs only): soft pre-limit on
absolute_strength + hard clamp of the output conditioning's video-channel
spread to the learned-safe value in _v2_finalize_conditioning. Skipped
during the guessing ladder itself. Helpers conditioning_spread /
scale_conditioning_spread.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 15:35:58 +03:00
digital-garbageandClaude Opus 4.8 7a6821930a Interactive Guessing engine: conditioning-spread ladder (Phase 2)
New variant producer for Batch Training that, instead of seed/shortcut
variation, scales the conditioning's spread (sigma) on VIDEO channels by a
linear ramp across N rungs, freezing everything else including the noise
seed so the only variable is conditioning strength. Up amplifies toward
overbake, down dampens. Each rung records funpack_guess_factor (in cond
meta + batch manifest) so the ladder is interpretable and Phase-3 learning
can read each rung. Audio channels untouched (scale_conditioning_spread
reuses the LTXAV channel split). Wired refine_v2 -> _v2_pack_batch
(guess_mode branch -> _v2_pack_guess_ladder) and the Studio refine_v2 call
(guess_mode/direction/range from refiner settings).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 15:27:30 +03:00
digital-garbageandClaude Opus 4.8 ef04c21a5a Stack latent normalization onto Hybrid + Distilled samplers (opt-in)
Reuse _normalize_video_denoised in _sample_const_rf_full (Hybrid CONST/RF
path) and sample_funpack_distilled_flow: new normalize_strength /
normalize_start_sigma (default 0 = off). Applied to the denoised after
rescue/quality-sharpness, video-only, so audio is never touched and the
samplers keep AB2/Heun/velocity/rescue. Wired node INPUT_TYPES (appended)
-> get_sampler -> Studio _build_one_sampler + JS panels for both.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 15:11:10 +03:00
digital-garbageandClaude Opus 4.8 49e7517389 Add FunPack Normalizing Sampler (video-only latent normalization)
New SAMPLER for distilled LTXAV at CFG=1: deterministic 1st-order euler
base (clean ddim look + clean audio) plus per-step video-only latent
normalization to counter overbaking / oversaturation / colour drift at
~zero overhead. Tracks the video latent's robust spread, anchors a
reference once x0 is meaningful (normalize_start_sigma), and compresses
inflated later steps (normalize_strength). Benefit-only, no-op when
healthy, audio never touched (whole-latent for single-stream LTXV).
Velocity bias + rescue included, video-only.

Node FunPackNormalizingSampler + Studio sampler option ("Normalizing")
wired through _build_one_sampler and the JS panel. Registered in __init__.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 12:07:39 +03:00
digital-garbageandClaude Opus 4.8 951c61953d Distilled Flow: graduated 2nd order (AB2 ramp, opt-in)
Instead of full AB2 on every step, optionally ramp the AB2 contribution
linearly 0->1 across the schedule: denoised_eff = lerp(raw, ab2, i/(N-1)).
Early/high-sigma steps stay near 1st-order euler (less overshoot); late
steps get full AB2. Reuses the computed AB2 estimate -> no extra model
evals. Aimed at low-step distilled quality. No-op at order=1; audio still
rides plain euler. Wired node -> get_sampler -> Studio panel (+ JS toggle).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 11:42:25 +03:00
digital-garbageandClaude Opus 4.8 ee66e4ec1e Report audio split on every Absolute steer (not once per process)
The conditioning-dim diagnostic logged once per process via _FUNPACK_AV_LOGGED,
so after the first generation it went silent — easy to read as "it never ran".
Fold the detected split into the per-run "Absolute steer applied" line so every
generation states whether audio is PROTECTED (video[:v] of D) or NOT split
(unrecognised width -> steering all channels, audio unprotected). Makes the
no-op case visible instead of silent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 10:48:22 +03:00
digital-garbageandClaude Opus 4.8 dd8da50153 Audio-safe conditioning steering on LTXAV (video-only channel-slice)
LTXAV splits one conditioning tensor into video|audio channel-slices
(av_model _prepare_context: torch.split(context,[v_dim,a_dim],-1)) and
cross-attends each stream to its own slice. Steering the whole tensor
corrupted the audio's text conditioning -> degraded audio (observed live).

Add protect_audio_channels: restore the audio channel-slice from the
unsteered conditioning so every edit moves video only. Applied at all
steering chokepoints:
- _v2_apply_conditioning_memory (per-prompt: liked/axis/concept/vf-grad)
- _v2_apply_absolute (global taste pull)
- _v2_ascend_conditioning (relative VF ascend+search)
- attn2 K/V direction patch + phrase emphasis
- FunPackConditioningAdjust (manual)
- sampler embed_guidance wrapper + per-scene VF ascend

Split auto-detected from width (7680->3840, 6144->4096); logs once.
Single-stream LTXV / unknown width = no-op (no regression).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 10:34:08 +03:00
digital-garbageandClaude Opus 4.8 c823d5bf3e Refiner V2 + Studio: add Absolute / Relative steer mode
Relative (default, unchanged) = per-prompt steering. Absolute = a keyless,
prompt-agnostic "global taste" prior that pulls conditioning toward generally-
liked directions regardless of the prompt; Both layers them.

- New keyless Absolute store (FUNPACK_ABSOLUTE_KEY): pooled liked/disliked
  direction + global value function, learned across every rated generation.
- Absolute rating semantics: a rating means "details I like in general" (not
  prompt adherence) — reward-driven liked/bad-dir storage, axis attribution
  bypassed. Perfect = "more of this everywhere".
- _v2_finalize_conditioning replaces the per-key ascend hook on both returns;
  pure Absolute also bypasses per-prompt conditioning memory.
- Scene Chain sampler: embed_guidance_source (relative/absolute) lets the
  per-step nudge draw from the global direction/value function.
- Studio popup + V2 node expose Steer mode + Absolute strength.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 10:06:56 +03:00
digital-garbage ea602f9de0 Revert "Distilled Flow: add Karras stochastic churn (zero-overhead variability)"
This reverts commit b47452e76e7fdfb8204051f2888d95d85e60816c.
2026-06-04 02:02:59 +03:00
digital-garbageandClaude Opus 4.8 e56dcf2c39 Distilled Flow: add Karras stochastic churn (zero-overhead variability)
Adds s_churn/s_tmin/s_tmax to sample_funpack_distilled_flow: optionally
re-noise the latent within [s_tmin, s_tmax] before each eval, then denoise
from the bumped sigma_hat. No extra model calls (still one eval per step,
at a higher noise level). Fights stale/frozen distilled output (more motion)
and can sharpen by letting the model re-resolve. sigma_hat is clamped to the
schedule start so the model never sees a higher-than-trained noise level, the
final jump-to-zero detail step is never churned, and the default 0.5-1.0 band
protects the sub-0.4 detail finish per the empirical sigma findings.

Churn supersedes the legacy s_noise ancestral path while active and is
video-stream-only on packed LTXAV latents. With s_churn=0 the sampler is
byte-identical to the previous deterministic ODE. Wired into the node and
Studio's Distilled Flow config panel.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 01:54:36 +03:00
digital-garbageandClaude Opus 4.8 40fe867dac Distilled Flow sampler: velocity bias + reactive rescue
Port the Hybrid/RF velocity-bias capture/apply and rating-gated reactive
rescue into sample_funpack_distilled_flow, reusing the shared trajectory
memory helpers. Adds velocity_bias_mode/strength/source/key and
rescue_mode/threshold/strength to the FunPackDistilledFlowSampler node and
wires them into Studio's Distilled Flow config panel (same blank/'default'
velocity-key -> refinement-key fallback as Hybrid). Steering is
magnitude-preserving and, on packed LTXAV latents, video-stream only
(audio-safe). With all controls off the sampler is byte-identical to the
previous deterministic ODE.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 01:42:04 +03:00
digital-garbageandClaude Opus 4.8 aa4a7f643c Batch Training: remove debug diagnostics; bump version to 2.7.7
Batch Training confirmed working end to end (controlled batch with transitions, distinct
per-variant seeds, node rating ignored during a batch, per-entry rating + VF/axis learning
on submit). Stripped the temporary trace prints (Batch Training check / Batch check / ACTUAL
scene seeds), keeping clean progress logs. Gitignore the local .testvenv.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 00:29:11 +03:00
digital-garbageandClaude Opus 4.8 ad9e171e4f Batch Training: distinct per-variant seeds in the SINGLE-scene path too (real cause of identical videos)
The live log showed the single-scene path: 'packed 3 variant conditioning(s)' with ACTUAL
scene_seeds identical across all 3 (all inherited the base entry's funpack_scene_seed). My
earlier seed fix only covered the multi-scene duplication path. When a prompt resolves to one
scene (common), _v2_build_batch_variants reused the base scene seed for every variant ->
identical noise -> identical videos (only tiny diffs from VF ascent).

Fix: _v2_pack_batch now assigns a fresh, well-spread per-variant scene seed (gen-seeded RNG,
reproducible, per-scene offset) to the packed entries in BOTH paths, after building them.
Verified in venv: single-scene 3 variants -> 3 distinct seeds.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 00:18:16 +03:00