You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
No restoration path in the LTX-2.5 family: Deblur and Decompression IC-LoRAs are a different trade from re-rendering #152
tool/endpoint:templates/ltx2/* — no restoration pass exists; two-stage is the only sharpening route
repro: the family's only answer to a soft or noisy render is templates/ltx2/two-stage
(eight sigmas at 768x448, 2x latent upsample, three stage-two sigmas at 1536x896) or templates/ltx2/generative-upscale. Both re-render. Neither cleans up an existing result.
what's now available: two LTX-2.5 IC-LoRAs from 2026-09-10:
why it is worth measuring rather than assuming. These are a genuinely different trade from
what the family has: restoration over a cheap low-resolution render, versus re-rendering at
higher cost. That is the exact decision that came up in practice today on the H3 side — a
grainy, mushy background at 544p, where the only routes on offer were "render bigger" (which hit
the 24 GB ceiling) or "accept it". Whether a restoration pass beats a refine pass on quality per
minute is an open question, and answering it needs a comparison, not an adoption.
proposed: one template for each, plus a measured comparison against two-stage on the same
source clip — quality and wall clock.
same cheap-plumbing point as #151:generative-upscale already runs an IC-LoRA step through LTX2ReferenceCondition / reference_conditions=, so these are templates and prompts, not
engine work.
caveats: both weights are 0.9 previews (only Clean-Plate shipped at 1.0), and both repos
are gated: auto — lem has access, but the cards could not be read unauthenticated here, so
the input format each expects is unverified.
related:#151 (Ingredients, same IC-LoRA batch); full write-up on #151.
Blocked on the same thing as #151, and parked with Don for the same reason. Worked as model opus via provider anthropic.
Neither weight is reachable. The gates on these repos have not been accepted by the account lem's Hugging Face token belongs to. Checked from lem with that token: Deblur and Decompression return 403 on both the card and a file range request, while the upscaler repo dw already uses returns 200 on both. So gated: auto is per repo, and this 2026-09-10 batch was never accepted — the inference on #151 that access came along with the upscaler does not hold.
That blocks the measurement this issue is actually asking for, not just the download. You were right that the interesting question is whether a restoration pass beats a refine pass on quality per minute, and that it needs a comparison rather than an adoption. I cannot set up a comparison against two-stage on weights I cannot fetch, and neither can the tester.
Also worth stating before anyone builds it: the input format is unconfirmed for exactly the same reason (the cards are 403). For a restoration IC-LoRA the open questions are whether the degraded clip goes in as a LTX2ReferenceCondition at reference_downscale_factor: 1 (unlike the upscaler's 2), what conditioning_attention_strength it wants, and whether the prompt should describe the clean target or the degraded source. Guessing those produces a template that validates and restores nothing in particular.
When that happens, the comparison worth running is the one you framed: a cheap low-resolution render restored, against two-stage's refine, on the same source clip, scored on quality and wall clock. I would add the same run through templates/ltx2/diffusion-decode (shipped for #153), since that is a third answer to "the picture is soft" that costs only a decode.
Unblocked and shipped. Gate accepted — verified from lem with its own token before writing anything (README 200 for Deblur and Decompression both), so the recipes below are the cards' rather than inferences from the upscaler's shape.
Two templates, because the cards are emphatic that these are not interchangeable and neither is a general restoration:
templates/ltx2/restore-deblur — spatial defocus only. The card rules out motion blur (no temporal blur in the dataset at all), compression-artefact repair, denoising, and super-resolution of already-sharp footage. Extreme blur is hallucinated rather than reconstructed.
templates/ltx2/restore-decompression — macroblocking, chroma bleed, ringing, banding. The card rules out defocus, motion blur, grain, upscaling and colorization.
Both share the shape, which is the part that answers your framing — "a different trade from re-rendering":
The reference is the caller's own clip, attached for the whole denoise, so identity, framing and background geometry are the source's and only the defect changes. These are the first templates in the family whose reference is a file dw did not generate; every other IC-LoRA use here conditions on an earlier step's output.
reference_downscale_factor1 — the reference is encoded at the output resolution. Not the upscaler's 2.
Trained bucket 960×544, 121 frames, 24 fps, which is what the defaults are. Both cards warn that generating far above the bucket weakens the effect, and the descriptions say so.
lora_scale 1.0, exposed as a variable — Deblur's card says to sweep toward 0.8 if it over-sharpens into haloing or ringing.
The prompts are the trained dual-panel forms, stored as prompts/ltx2/deblur_dual_panel and prompts/ltx2/decompression_dual_panel: "Reference shows … DEBLUR / ENHANCE QUALITY … only focus and sharpness / only compression artifacts and image quality differ". Replace both halves' scene descriptions, keep the structure.
Both weights are 0.9 previews. Said in each description.
source_video defaults to an asset: placeholder (asset:blurry.mp4, asset:compressed.mp4), the same convention assemble-and-score uses — the template is not runnable until the caller points it at their footage, which is correct for a restoration pass.
Every number above is pinned to its card by tests/test_ltx2_ic_loras.py, so a re-audit that finds the vendor has moved fails here rather than in a run.
Not measured against two-stage. Your ticket's framing is that this is a different trade and worth measuring against the refine pass — I agree, and I have not done it. Both are 0.9 previews, "better" on a grainy 544p background is a judgement about output rather than a pass/fail, and it is two GPU runs plus a look. That is a deliberate experiment for whoever has the source clip that started this, not something to spend on my say-so. The templates are there to make it cheap.
Note the plan.downloads_required fix from #151 applies here too — both LoRA repos are now named before the run rather than pulled mid-run.
Deploy path: server code plus catalog. develop at b599cf3 (the templates are a526fde), pulled on lem, dw.serve restarted in its screen session, /api/healthstatus: ok. 2026-09-14 21:07 UTC. 4862 tests pass.
Regression case — regression-suite-model-specific.md, no GPU:
list_workflows(shape="shot") includes templates/ltx2/restore-deblur and templates/ltx2/restore-decompression.
validate_workflow("templates/ltx2/restore-deblur", arguments={"source_video": "asset:<something real>"}) → valid, and plan.downloads_required names Lightricks/LTX-2.5-22b-IC-LoRA-Deblur on a box that has not pulled it.
validate_workflow(..., arguments={"num_frames": 120}) → refused (the LTX 8n + 1 grid, no snap).
Implementer agent, model opus via provider anthropic.
Verified over MCP. Ran as model opus via provider anthropic, workspace default (validate-only, nothing written).
The implementer's three proposed checks, all green:
list_workflows(shape="shot", traits="needs-input-media") lists both templates/ltx2/restore-deblur and templates/ltx2/restore-decompression, each shape: shot, traits has-audio, needs-input-media (note: notimage-conditioned — the reference is a clip, which reads correctly), constraints.num_frames: "8*n+1, 9+".
validate_workflow("templates/ltx2/restore-deblur", arguments={"source_video": "asset:qa-cast/ep13-episode.mp4"}) → valid: true, checked_arguments: ["source_video"], one step, and plan.downloads_required is exactly [{repo: "Lightricks/LTX-2.5-22b-IC-LoRA-Deblur", gb: 0.9}] on a box that has not pulled it. The LTX-2.5 has no reference/identity template, and an Ingredients IC-LoRA for it shipped 2026-09-10 #151downloads_required fix does carry here — the LoRA is named before the run, not pulled mid-run. Same for restore-decompression with arguments={"source_video": "asset:qa-cast/ep12-episode.mp4", "num_frames": 121, "lora_scale": 0.8} → valid: true, checked_arguments: ["lora_scale","num_frames","source_video"], downloads_required: [Lightricks/LTX-2.5-22b-IC-LoRA-Decompression, 0.9 GB]. So the two templates do name distinct weights — they are not one template wearing two hats.
validate_workflow(..., arguments={"num_frames": 120}) → valid: false, one error at arguments.num_frames: "must be 8 * n + 1 … Refused here instead: no 'snap'". Refused free, before anything loads. 121 validates.
Adjacent cases I added:
The asset: placeholder is a real guard, not decoration.arguments={"source_video": "asset:blurry.mp4"} → valid: false at arguments.source_video, "Asset 'blurry.mp4' not found in …". So a caller who forgets to point the template at their own footage is stopped at validation rather than burning a load.
But note the default-only path:validate_workflow("templates/ltx2/restore-deblur") with no arguments returns valid: true with nochecked_arguments key — stored defaults aren't reference-checked, so the unrunnable asset:blurry.mp4 default passes there. That is the documented contract (checked_arguments exists precisely to say what was covered), so I am not filing it; recording it because "valid with no arguments" on these two templates does not mean runnable.
The card numbers are actually on the workflow, not just in the description.get_workflow("templates/ltx2/restore-deblur", variables_only=true): width 960, height 544, num_frames 121, frame_rate 24.0, lora_scale 1.0, prompt: "prompt:ltx2/deblur_dual_panel", source_video: "asset:blurry.mp4", and constraints.num_frames = {modulus 8, remainder 1, min_frames 9} with the VAE reason inline. Matches the trained bucket as stated.
The dual-panel prompts exist and are the trained form.get_prompt("ltx2/decompression_dual_panel") returns the "Reference shows … ENHANCE QUALITY … only compression artifacts and image quality differ" text, intended_model: ltx-2.5, tags ic-lora / restoration / v2v, with a description telling the caller to replace both scene halves and keep the structure. That is the part most likely to be got wrong by a caller, and it is carried in the prompt library rather than left to the template's reader.
What I did not verify, deliberately: no GPU run. The weights are not on the box (that is what check 2 demonstrates), and the thing this ticket originally asked to measure — restoration-pass vs two-stage's refine on quality per minute — is a judgement about output on two 0.9 previews, not a pass/fail a consumer-side agent can settle. I agree with the implementer that it is a separate deliberate experiment against the clip that started this, and I am not treating its absence as blocking the templates. If that measurement is still wanted it should be its own issue with the source clip named; I am not filing it, since nobody has committed the GPU time.
Closing as completed + status:verified on what shipped: the two templates, their distinct weights, their bounds, their placeholder guard and their prompts, all confirmed by live MCP calls this session.
Regression case added to regression-suite-model-specific.md (M-F014), no GPU. It pins the two templates' distinct weights and the placeholder guard rather than the 8n+1 rule, which M-F005 already covers.
Activity
dkackman commentedon Sep 14, 2026
Blocked on the same thing as #151, and parked with Don for the same reason. Worked as model
opusvia provideranthropic.Neither weight is reachable. The gates on these repos have not been accepted by the account
lem's Hugging Face token belongs to. Checked fromlemwith that token:DeblurandDecompressionreturn 403 on both the card and a file range request, while the upscaler repo dw already uses returns 200 on both. Sogated: autois per repo, and this 2026-09-10 batch was never accepted — the inference on #151 that access came along with the upscaler does not hold.That blocks the measurement this issue is actually asking for, not just the download. You were right that the interesting question is whether a restoration pass beats a refine pass on quality per minute, and that it needs a comparison rather than an adoption. I cannot set up a comparison against
two-stageon weights I cannot fetch, and neither can the tester.Also worth stating before anyone builds it: the input format is unconfirmed for exactly the same reason (the cards are 403). For a restoration IC-LoRA the open questions are whether the degraded clip goes in as a
LTX2ReferenceConditionatreference_downscale_factor: 1(unlike the upscaler's 2), whatconditioning_attention_strengthit wants, and whether the prompt should describe the clean target or the degraded source. Guessing those produces a template that validates and restores nothing in particular.To unblock: accept the licence on
https://huggingface.co/Lightricks/LTX-2.5-22b-IC-LoRA-Deblur and
https://huggingface.co/Lightricks/LTX-2.5-22b-IC-LoRA-Decompression
as the account whose token is on
lem, then hand back withowner:implementerand no status label. Both are 0.9 previews, as you noted — I would still build them as two templates and measure rather than assume, which is what you proposed.When that happens, the comparison worth running is the one you framed: a cheap low-resolution render restored, against
two-stage's refine, on the same source clip, scored on quality and wall clock. I would add the same run throughtemplates/ltx2/diffusion-decode(shipped for #153), since that is a third answer to "the picture is soft" that costs only a decode.dkackman commentedon Sep 14, 2026
licenses accepted
feat: #151 #152 - the LTX-2.5 family gets an identity route and two r…
Merge fixes for #145 #151 #152 #161 #162 #165 - list-entry constraint…
dkackman commentedon Sep 14, 2026
Unblocked and shipped. Gate accepted — verified from
lemwith its own token before writing anything (README200 for Deblur and Decompression both), so the recipes below are the cards' rather than inferences from the upscaler's shape.Two templates, because the cards are emphatic that these are not interchangeable and neither is a general restoration:
templates/ltx2/restore-deblur— spatial defocus only. The card rules out motion blur (no temporal blur in the dataset at all), compression-artefact repair, denoising, and super-resolution of already-sharp footage. Extreme blur is hallucinated rather than reconstructed.templates/ltx2/restore-decompression— macroblocking, chroma bleed, ringing, banding. The card rules out defocus, motion blur, grain, upscaling and colorization.Both share the shape, which is the part that answers your framing — "a different trade from re-rendering":
reference_downscale_factor1 — the reference is encoded at the output resolution. Not the upscaler's 2.lora_scale1.0, exposed as a variable — Deblur's card says to sweep toward 0.8 if it over-sharpens into haloing or ringing.prompts/ltx2/deblur_dual_panelandprompts/ltx2/decompression_dual_panel: "Reference shows … DEBLUR / ENHANCE QUALITY … only focus and sharpness / only compression artifacts and image quality differ". Replace both halves' scene descriptions, keep the structure.source_videodefaults to anasset:placeholder (asset:blurry.mp4,asset:compressed.mp4), the same conventionassemble-and-scoreuses — the template is not runnable until the caller points it at their footage, which is correct for a restoration pass.Every number above is pinned to its card by
tests/test_ltx2_ic_loras.py, so a re-audit that finds the vendor has moved fails here rather than in a run.Not measured against
two-stage. Your ticket's framing is that this is a different trade and worth measuring against the refine pass — I agree, and I have not done it. Both are 0.9 previews, "better" on a grainy 544p background is a judgement about output rather than a pass/fail, and it is two GPU runs plus a look. That is a deliberate experiment for whoever has the source clip that started this, not something to spend on my say-so. The templates are there to make it cheap.Note the
plan.downloads_requiredfix from #151 applies here too — both LoRA repos are now named before the run rather than pulled mid-run.Deploy path: server code plus catalog.
developatb599cf3(the templates area526fde), pulled onlem,dw.serverestarted in its screen session,/api/healthstatus: ok. 2026-09-14 21:07 UTC. 4862 tests pass.Regression case —
regression-suite-model-specific.md, no GPU:list_workflows(shape="shot")includestemplates/ltx2/restore-deblurandtemplates/ltx2/restore-decompression.validate_workflow("templates/ltx2/restore-deblur", arguments={"source_video": "asset:<something real>"})→ valid, andplan.downloads_requirednamesLightricks/LTX-2.5-22b-IC-LoRA-Debluron a box that has not pulled it.validate_workflow(..., arguments={"num_frames": 120})→ refused (the LTX8n + 1grid, no snap).Implementer agent, model
opusvia provideranthropic.dkackman commentedon Sep 14, 2026
Verified over MCP. Ran as model
opusvia provideranthropic, workspacedefault(validate-only, nothing written).The implementer's three proposed checks, all green:
list_workflows(shape="shot", traits="needs-input-media")lists bothtemplates/ltx2/restore-deblurandtemplates/ltx2/restore-decompression, eachshape: shot, traitshas-audio, needs-input-media(note: notimage-conditioned— the reference is a clip, which reads correctly),constraints.num_frames: "8*n+1, 9+".validate_workflow("templates/ltx2/restore-deblur", arguments={"source_video": "asset:qa-cast/ep13-episode.mp4"})→valid: true,checked_arguments: ["source_video"], one step, andplan.downloads_requiredis exactly[{repo: "Lightricks/LTX-2.5-22b-IC-LoRA-Deblur", gb: 0.9}]on a box that has not pulled it. The LTX-2.5 has no reference/identity template, and an Ingredients IC-LoRA for it shipped 2026-09-10 #151downloads_requiredfix does carry here — the LoRA is named before the run, not pulled mid-run. Same forrestore-decompressionwitharguments={"source_video": "asset:qa-cast/ep12-episode.mp4", "num_frames": 121, "lora_scale": 0.8}→valid: true,checked_arguments: ["lora_scale","num_frames","source_video"],downloads_required: [Lightricks/LTX-2.5-22b-IC-LoRA-Decompression, 0.9 GB]. So the two templates do name distinct weights — they are not one template wearing two hats.validate_workflow(..., arguments={"num_frames": 120})→valid: false, one error atarguments.num_frames: "must be 8 * n + 1 … Refused here instead: no 'snap'". Refused free, before anything loads. 121 validates.Adjacent cases I added:
asset:placeholder is a real guard, not decoration.arguments={"source_video": "asset:blurry.mp4"}→valid: falseatarguments.source_video, "Asset 'blurry.mp4' not found in …". So a caller who forgets to point the template at their own footage is stopped at validation rather than burning a load.validate_workflow("templates/ltx2/restore-deblur")with noargumentsreturnsvalid: truewith nochecked_argumentskey — stored defaults aren't reference-checked, so the unrunnableasset:blurry.mp4default passes there. That is the documented contract (checked_argumentsexists precisely to say what was covered), so I am not filing it; recording it because "valid with no arguments" on these two templates does not mean runnable.get_workflow("templates/ltx2/restore-deblur", variables_only=true):width 960,height 544,num_frames 121,frame_rate 24.0,lora_scale 1.0,prompt: "prompt:ltx2/deblur_dual_panel",source_video: "asset:blurry.mp4", andconstraints.num_frames={modulus 8, remainder 1, min_frames 9}with the VAE reason inline. Matches the trained bucket as stated.get_prompt("ltx2/decompression_dual_panel")returns the "Reference shows … ENHANCE QUALITY … only compression artifacts and image quality differ" text,intended_model: ltx-2.5, tagsic-lora / restoration / v2v, with a description telling the caller to replace both scene halves and keep the structure. That is the part most likely to be got wrong by a caller, and it is carried in the prompt library rather than left to the template's reader.What I did not verify, deliberately: no GPU run. The weights are not on the box (that is what check 2 demonstrates), and the thing this ticket originally asked to measure — restoration-pass vs
two-stage's refine on quality per minute — is a judgement about output on two 0.9 previews, not a pass/fail a consumer-side agent can settle. I agree with the implementer that it is a separate deliberate experiment against the clip that started this, and I am not treating its absence as blocking the templates. If that measurement is still wanted it should be its own issue with the source clip named; I am not filing it, since nobody has committed the GPU time.Closing as
completed+status:verifiedon what shipped: the two templates, their distinct weights, their bounds, their placeholder guard and their prompts, all confirmed by live MCP calls this session.Regression case added to
regression-suite-model-specific.md(M-F014), no GPU. It pins the two templates' distinct weights and the placeholder guard rather than the8n+1rule, which M-F005 already covers.Tester agent, model
opusvia provideranthropic.