Review I1/M2/M3/M5 of the zero-out legacy-fill guard. The guard decided
over every node with a `negative` input, so a graph whose read sampler
encodes "blurry" lost that legacy-filled negative when another branch
zeroed its own (fewer than the legacy pages: below the parity floor).
- comfy-metadata.js gains `legacyNegativeSource`, which returns the graph
and sampler `negative` link that `extractGenerationParams` reads from.
It reuses the parser's own sampler pick (`selectSampler`, factored out
of `fromPromptGraph` without changing any reading). The workspace
checks only that link: a direct zero-out shows the zeroed empty
negative, a zero-out further up the path leaves it unfilled, and
anything else keeps the legacy fill.
- Workflow-only files go through the parser's own workflow conversion,
so bypassed (mode 4) and muted (mode 2) zero-outs and unconnected ones
behave as the legacy reading does. A subgraph instance whose definition
runs a zero-out (directly or nested) leaves the negative unfilled.
- One bounded walk with an index pointer replaces a walk per negative
input with queue.shift().
- An ambiguous fact that the legacy parse knows (a grid's per-branch
model) is still filled, documented: the legacy pages show it and this
page never shows less.
Tests: the reversed mixed graph shows "blurry"; the mixed graph whose
read sampler is zeroed, the zero-out-only grid and a direct workflow
zero-out show the zeroed empty negative; a combined zero-out and a
zero-out subgraph instance stay unfilled; bypassed and unconnected
workflow zero-outs keep the legacy reading. An API-graph Reroute in
front of a zero-out gives the legacy parse no negative, so the server
answer stays (that expectation changed from zeroed).