Commit Graph
7 Commits
Author SHA1 Message Date
digital-garbageandClaude Opus 5 71777a9f29 fix(second pass): name the upsampler ComfyUI cannot load, instead of its traceback
Core's latent-upscale loader is an if/elif with no else, so an unrecognised file
falls off the end as "cannot access local variable 'model'". The architectures it
knows are probed here first, and an unknown one is reported by name and key shape.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 23:56:10 +03:00
digital-garbage 8d4a199e1f feat(sampler): second pass and segmented detailing on any model family
Both were switched off on H3 because Lightricks' upsampler is 128-channel — a fact about
the file, not the family. They now load any upsampler ComfyUI can (core's loader handles
the rest), refuse a mismatched one by name, and never download the LTX file for H3.
2026-08-20 18:38:36 +03:00
digital-garbageandClaude Opus 5 bf73835e3b fix: wiring survives a project load; Frames says when it reaches nothing; anchor survives upscale_2x
Three unrelated reports.

Wires lost or "(not allowed)" after loading a project. /api/pipeline-ports read the
family from the GLOBAL models.json, so it described whichever project was saved last.
Open one on the other family and its saved wires point at ports that family has no rule
for. It takes ?pid= now, and the panel asks for the config before the rules that depend
on it. Reconcile also dropped a port wire when core_overrides named a deleted slot — it
cleared every other slot's wire to that port, then failed to add the replacement.

Guided mode also filtered harder than the builder validates. A node added through
"Any node…" has role `custom`, which no rule table mentions, so a custom VAE loader
could not reach the pipeline at all. A role with no rule for an output type now reaches
any port of that type; a role that HAS one keeps it, and internal links stay closed.
Both sides read the same list, since the panel hiding what the builder accepts is what
produced "(not allowed)".

Frames / scene silently missed shots. Any timeline resize, trim or split moves a scene
off project length for good, and nothing said so — typing 305 and rendering 450 read as
the edit being ignored. The Project panel now says how many shots it doesn't reach and
offers to put them back. The panel's fingerprint had to learn about scene state, or the
warning outlived the fix.

second_pass_op=upscale_2x no longer drops the i2v pin. The pinned frames in the upscaled
latent ARE the anchor — carried through the same upsampler as the rest of the clip — so
only the mask needed scaling to the new grid. Pass 2 at 4x the pixels was the run most
likely to drift off the reference, and it was the one running unpinned. The pin now
holds the upscaled anchor rather than the encoded source image, and the report says so.
Guide keyframes are still dropped: those are token indices, not pixels.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-14 02:24:53 +03:00
digital-garbageandClaude Opus 5 39533dfde4 anchor_shift: remove the shift, keep only the head cut
The two-pass shift regrew the frames it dropped, and the invented ending
consistently came out with worse or missing movement — not worth paying
steps for. What is left is the part that works: generate the scene exactly
as normal, anchor pinned at full strength the whole way, then cut the
opening off the finished clip. Nothing is regrown, so the scene comes out
that much shorter and the audio is cropped to match.

Six knobs collapse into one INT, cut_opening_frames (0 = off), in the
Editor under Chain Sampler ▸ Timing & Seed rather than Experimental.
Gone with the shift: the mid-schedule split, the rewind re-noise
(_renoise_to_sigma), the tail refill modes, the fresh-audio reset, and the
schedule_context/continue_from_state plumbing that existed only so a split
scene would not re-time the sampler inside each half.

second_pass is untouched — it never used any of that machinery.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 17:36:13 +03:00
digital-garbageandClaude Opus 5 63f225e231 second_pass: both schedules run in FULL — remove the cut I invented
User, after a live run: "First pass runs its own FULL schedule. Then 2nd pass begins.
If I want to stop 1st pass earlier - I remove sigmas from schedule... 'Continue from'
is ONLY relevant in our shifting technique which is a separate entity."

Correct, and the cut was mine, not theirs. I carried anchor_shift's cut/restart
semantics into a feature that has no use for them. Consequences they hit on the rental:

- Steps. Pass 1 was cut at the second schedule's first sigma, so a 9-step main plus a
  4-step second pass ran 3+4=7, not 13. They noticed the missing steps.
- Distortion. With the cut, the between-pass operation ran on a MID-TRAJECTORY latent,
  so "sharpen" was sharpening the noise still in it. It only makes sense on a finished
  clip.

Now: pass 1 runs the main schedule in full, exactly as written. The operation runs on
that finished clip. Pass 2 runs second_pass_sigmas in full, exactly as written, entering
the way any img2img refine does — comfy's ordinary CONST scaling on a clean latent, so
continue_from_state stays off. Total steps are the two schedules added up. To make pass 1
shorter, shorten the main schedule.

second_pass_sigma and second_pass_restart_sigma are deleted outright: with both schedules
run as written there is nothing to cut and nothing to continue from. The second schedule's
first sigma is now simply the strength dial, the way it is in every img2img refine.
_second_pass_plan is replaced by _second_pass_schedule, which only validates.

Also reported: "I have only sharpening enabled but log tells me upsampling is enabled as
well." The load line printed "[FunPackSceneChain] segmented detailing upsampler: ..."
regardless of which feature pulled it in, and sharpen legitimately loads that model —
so a sharpen-only run announced a feature that was off. Now "latent upsampler loaded".

Kept: the malformed-schedule refusals (ascending, or not ending at 0) — both are silent
in the output rather than loud at runtime, which is how the distorted run read.

tests/test_second_pass.py rewritten around the corrected shape, including that a 9-step
main plus a 4-step second pass is 13. Suites at baseline: 22 pre-existing failures, 467
passing. Verified live that typing a schedule sets second_pass with no cut knob leaking.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 13:55:48 +03:00
digital-garbageandClaude Opus 5 16045e086c second_pass: optional latent operations between the passes (none by default)
Per the user's reminder that these are OPTIONS, not defaults: second_pass_op is a
combo defaulting to "none", and nothing runs unless it is picked. The expensive one
is therefore not a tax on anything — it costs what it costs only when chosen.

- "sharpen": one forward of Lightricks' trained 2x LatentUpsampler, resampled straight
  back to the original size. No video-model calls, so a fraction of a step; pass 2 then
  re-denoises the sharpened latent, which is what makes it stick. Adds detail consistent
  with what is there and CANNOT fix wrong structure — the same limit segmented
  detailing's sharpen mode documents.
- "upscale_2x": same upsampler, result KEPT at 2x, so pass 2 runs at 4x the pixels and
  the scene decodes at double resolution. 3-5x the second half's cost.

Reuses detailing.py's _run_upsampler / _downscale_to and its lazily-loaded upsampler
(same model, same detail_upsampler knob, "auto" downloads the official file) rather
than adding a second copy of any of it.

Ordering that matters: the op runs BEFORE the rewind re-noise, because sharpening a
latent that has just had noise added back sharpens the noise.

Two failure modes handled rather than left implicit:
- upscale_2x changes the latent resolution, so the chunk's i2v anchor and mask are the
  wrong size. Rescaling them would be inventing an anchor, so the pin is dropped and
  the scene report SAYS the pass runs unpinned and may drift from the reference image.
- A missing or throwing upsampler degrades to "second pass, no operation" with the
  reason, instead of killing a whole montage over an optional sharpen.

Found while writing the tests: an unrecognised op name was validated only AFTER the
upsampler forward had already run, so a typo paid full price and then reported the
wrong reason. Name is checked first now.

Editor + Easy Gen get the combo under Engine > Experimental; verified live that it
renders with none/sharpen/upscale_2x and defaults to none. Suite at baseline: 22
pre-existing failures, 306 passing.

Not built: downscale-then-rescale (DeepShrink-shaped). It is not a between-passes op —
pass 1 itself has to run at reduced resolution, which means downscaling the chunk, its
mask and the anchor before pass 1, so it needs its own insertion point rather than
this hook.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 13:35:29 +03:00
digital-garbageandClaude Opus 5 b7fa3756f1 Chain Sampler: general "Enable second pass", with an optional separate schedule
anchor_shift built the two-pass machinery — stop the schedule, hand the state over,
re-enter exactly (_sample_chunk continue_from_state, _renoise_to_sigma, _schedule_view).
The user's point: that is generally useful, not anchor-specific. This exposes it on its
own, and keeps the two features independent as they asked: reaching the second_pass
branch means anchor_shift did not act on this scene, so they can never nest.

  second_pass                 stop partway and finish in a second pass
  second_pass_sigma           where pass 1 stops (walked against the real schedule)
  second_pass_restart_sigma   where pass 2 re-enters; 0 = carry straight on
  second_pass_sigmas          OPTIONAL SIGMAS socket: pass 2 runs THAT schedule instead

At restart 0 with no second schedule the split is behaviour-neutral by construction —
pass 2 resumes from the exact handed-over state, nothing added, and 5+4 steps on a
9-step schedule is still 9. It earns its keep when the second half is made different:
re-entering higher (the model reworks what it committed to) or finishing on a different
schedule entirely, so the tail can have its own step count, spacing or shift.

Two things a split gets silently wrong if you let it, both handled:
- The i2v anchor. _sample_chunk drops noise_mask from what it returns, so pass 2 would
  run UNPINNED and re-denoise the reference frame. anchor_shift wants exactly that;
  a plain second pass must not. _restore_pinned_prefix puts the mask back AND restores
  the pinned frames from the original chunk, since a rewind re-noise adds noise
  everywhere including frames that are meant to be frozen.
- The sampler's own phases. Pass 2's schedule_context is the alternate schedule at
  offset 0 when one is connected, or the main schedule at the slice offset when not —
  so quality steps / final-correction window / AB2 ramp are measured against whichever
  schedule pass 2 is actually running.

Every refusal names its fix (cut outside the schedule, entry below the cut, a
single-sigma SIGMAS input that is not a schedule) and lands in the scene report as
second_pass(SKIPPED: ...) — never a silent no-op.

Editor + Easy Gen get the three widgets under Engine > Experimental. The SIGMAS socket
is node-graph only for now: the Editor's fixed graph takes sigmas from ("studio", 5) and
has no second scheduler node, so exposing it there is a graph-topology change I have not
made unilaterally.

Latent/pixel-space pass-2 operations (sharpen, downscale->rescale, upscale) are next,
as opt-in options with nothing on by default.

New tests/test_second_pass.py: 10 tests over the split, the separate schedule, the
refusals and the pin. Suite at baseline: 22 pre-existing failures, 299 passing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 13:31:07 +03:00