Which skip seeds are real — the ones nothing still reaches.
The invariant. A task may be marked Skipped only when EVERY route into it has been cut.
The dispatcher already enforces that for ordinary dropped edges (its stillReachable set), and
ComputeSkipCascade's own contract promises it for joins: "a join that is also reachable
from the winning branch therefore survives — which is the entire point, since a fork that
reconverges must still run its join." Exclusive losers bypassed both and were written Skipped
directly.
The shape that breaks: A →(cond)→ Review → Publish and A →(else)→ Publish. With the condition
true, the losing edge A→Publish seeded Publish as Skipped while Review was still running.
Review then completed, Publish was already terminal, Skipped satisfies dependents — and the
graph settled Complete with the publish step never executed. No error and no stall, which is
why it needed a test rather than a bug report.
Why the cascade cannot do this job.ComputeSkipCascade decides over node STATUS — "every
gating predecessor is Skipped". A genuine XOR loser's origin is Complete, not Skipped, so the
cascade would refuse every legitimate loser. Seed confirmation is a question about EDGES: is any
gating edge into this task still live? The two rules are complementary, and this is the one the
cascade is missing.
Which skip seeds are real — the ones nothing still reaches.
The invariant. A task may be marked
Skippedonly when EVERY route into it has been cut. The dispatcher already enforces that for ordinary dropped edges (itsstillReachableset), and ComputeSkipCascade's own contract promises it for joins: "a join that is also reachable from the winning branch therefore survives — which is the entire point, since a fork that reconverges must still run its join." Exclusive losers bypassed both and were writtenSkippeddirectly.The shape that breaks:
A →(cond)→ Review → PublishandA →(else)→ Publish. With the condition true, the losing edgeA→Publishseeded Publish as Skipped while Review was still running. Review then completed, Publish was already terminal,Skippedsatisfies dependents — and the graph settled Complete with the publish step never executed. No error and no stall, which is why it needed a test rather than a bug report.Why the cascade cannot do this job.
ComputeSkipCascadedecides over node STATUS — "every gating predecessor is Skipped". A genuine XOR loser's origin isComplete, notSkipped, so the cascade would refuse every legitimate loser. Seed confirmation is a question about EDGES: is any gating edge into this task still live? The two rules are complementary, and this is the one the cascade is missing.