Skip to content

pgw#1139 (ie#657): the flow gate reads scheduler CAPABILITY, not the class name — 0.109.0 -> 0.110.0 - #656

Merged
PaulFidika merged 1 commit into
masterfrom
1139-flow-gate-capability
Aug 11, 2026
Merged

pgw#1139 (ie#657): the flow gate reads scheduler CAPABILITY, not the class name — 0.109.0 -> 0.110.0#656
PaulFidika merged 1 commit into
masterfrom
1139-flow-gate-capability

Conversation

@PaulFidika

Copy link
Copy Markdown
Contributor

The defect, measured on a billed request

3b12a2d6-b3aa-4e46-9323-03f70ae44fca (H100, whole 5B tree staged, parameters logged) raised before the first denoise step:

ValueError: objective='flow' checkpoint cannot run under sampler 'UniPCMultistepScheduler'
(UniPCMultistepScheduler is not a flow-match scheduler)

view.py:241 gated objective=="flow" on cls.__name__.startswith("FlowMatch") — a NAME test. The tree's scheduler is upstream's own Wan-AI/Wan2.2-TI2V-5B-Diffusers@b8fff731:scheduler/scheduler_config.json: UniPC with prediction_type: "flow_prediction", use_flow_sigmas: true, flow_shift: 5.0. It IS the official Wan flow solver; it just isn't spelled like one. A fatal that requeues buys a fresh H100 per attempt.

Realized blast radius, off the master stack's whole request table: wan-2.2's text-image-to-video has ONE row ever (cancelled), video-to-video and image-to-video have NONE. No TI2V-5B frame has ever been rendered. Only the -turbo siblings serve, via an endpoint-local _serving_view that bypasses the SDK.

The fork, and why this side of it

A third endpoint-local bypass would fix three call sites and leave the trap armed for every other consumer. A name test that refuses a config-declared flow sampler is a defect wherever it fires — so the gate is what changes.

flow_capable(cls, config): flow BY CONSTRUCTION (FlowMatch* has no other mode) or flow BY DECLARATION — the resolved config declares use_flow_sigmas / prediction_type="flow_prediction" and the class takes use_flow_sigmas. The capability half is the whole check: every diffusers scheduler accepts prediction_type, so a declaration alone would let a flow config carried onto EulerAncestralDiscreteScheduler read as flow while from_config silently dropped it.

What the gate still protects — tested both ways

test pre-fix post-fix
flow-capable UniPC on the verbatim upstream Wan config FAIL (production error, character-for-character) pass
flow_capable not satisfied by prediction_type alone FAIL pass
declared flow shift reaches the field the class honours FAIL pass
sampler="euler_a" over that same flow checkpoint refuses refuses
plain UniPC whose config never declares flow refuses refuses
non-diffusers scheduler declaring nothing refuses refuses

The three refusal rows passing on both sides is what proves the gate was narrowed correctly rather than opened.

ie#535's second half

shift (FlowMatch*) and flow_shift (the multistep solvers) are the same flow-sigma knob; from_config drops the spelling the target class does not take, so a repo publishing a shift onto a UniPC mirror had it ignored rather than refused. A declared shift is renamed to the spelling the class honours. Nothing is invented; a class taking neither is left alone.

The cut

0.109.0 -> 0.110.0, uv.lock relocked in the same commit. The cut also carries pgw#1132, which merged after 0.109.0 was already published. A pod run needs this number (ie#657's canary), which is the batching rule's condition.

Repin train owed: the fleet is pinned gen-worker==0.106.0 (fleet1060/ie#645). ie#657 repins wan-2.2 alone to reach a pod; the fleet train to 0.110.0 is a separate lane and is noted in the tracker.

…class name — 0.109.0 -> 0.110.0

`clone_scheduler` admitted an objective="flow" checkpoint only when
`cls.__name__.startswith("FlowMatch")`. The official Wan solver is
`UniPCMultistepScheduler(prediction_type="flow_prediction",
use_flow_sigmas=True, flow_shift=5.0)` — upstream's own scheduler_config.json,
byte-identical in our mirrors — so every request against it raised before the
first denoise step, and the fatal requeued onto a fresh H100 per attempt.
Measured blast radius on the master stack: wan-2.2's `text-image-to-video` has
ONE request row ever (cancelled), `video-to-video` and `image-to-video` have
none. A name test refuses a config-declared flow sampler for EVERY consumer, so
the fix is the gate, not a third endpoint-local `_serving_view` bypass.

`flow_capable(cls, config)` reads the facts instead: flow by construction (the
`FlowMatch*` family) or flow by declaration — `use_flow_sigmas` /
`prediction_type="flow_prediction"` in the RESOLVED config AND a class that
takes `use_flow_sigmas`. The capability half is load-bearing: every diffusers
scheduler accepts `prediction_type`, so a declaration alone would let a flow
config carried onto EulerAncestral read as flow while from_config dropped it.

What the gate still refuses is unchanged, and now tested both ways: a diffusion
sampler over a flow checkpoint, a flow-CAPABLE class its config never declares,
a non-diffusers scheduler declaring nothing. Three new tests are red on the
pre-fix tree — the acceptance one with the production error verbatim — and the
three refusal tests pass on both sides.

ie#535's second half rides along: `shift` and `flow_shift` are the same knob
under two upstream spellings and from_config drops the one the class does not
take, so a published shift was ignored rather than applied. A declared shift is
renamed to the spelling the class honours; nothing is invented.

The cut carries pgw#1132 as well (merged after 0.109.0 was already published).
@PaulFidika
PaulFidika merged commit e5cc65d into master Aug 11, 2026
3 checks passed
@PaulFidika
PaulFidika deleted the 1139-flow-gate-capability branch August 11, 2026 19:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant