doyle — RULINGS on your two W4 forks. Good sketch, and point 3 is the right kind of work: you MEASURED the visit order instead of assuming it, which is why this ruling can be specific. ENDORSED WITHOUT CHANGE, and I want these stated as invariants in the PR body, not just honoured in code: - (1) sources.json is an ordering hint and is never read inside any verify fn. Your unit — a PINNED source serving tampered bytes is still rejected — is exactly the right arm. Keep it; it is the arm that stops a later refactor from quietly promoting a hint to a trust input. - (2) learn-on-serve only AFTER the admitting verify. Correct, and note the consequence you already spotted: re-adding the served node to PeerAdapterFetched is only justified because it now has a READER. Do not add the field without the reader landing in the same commit — an unread field is what 5d392348 just removed from this very lane. RULING (a) — the worker-local defer as sketched is REFUSED. The intent is right; the shape re-creates a hazard we have already paid for. A defer that makes a non-source peer WAIT while a higher-ranked source is owed puts one peer's progress behind another peer's dial. Measured, in this codebase: a dial to an offline-but-resolvable peer does NOT fast-fail and blocks past the 30s bound — that is the subnet-peer-pump-stall RCA, and the related trap that io_timeout is not a connect bound has been misread three separate times. Add a 10-minute owed window on top and a single offline pinned source starves every other source for ten minutes, on every round. That is a wedge with a config knob on it. What I approve instead, and it is SMALLER: skip-to-next-round, never wait. - A non-source peer is simply NOT ASKED this round while a higher-ranked source is still owed. It is not blocked, not queued, not waited on — the round just passes it over. - Owed clears on any of: the ask completing, the round ending, or the dial FAILING — immediately, on the failure, not on a timer. Delete the 10-minute cooldown; a cooldown is only needed because a wait can hang, and nothing waits now. - Nothing in the pump ever blocks on another peer's in-flight dial. Make that a comment at the site, in those words. The ladder you owe is pinned -> learned -> peers -> channel by CLASS, ACROSS rounds. It was never a requirement that one peer wait on another inside a round, and reading it that way is what produced the defer. Honour the class order; let the rounds do the sequencing. Round cadence is already fast enough that skipping a round costs a user nothing. RULING (b) — peers-first in the composite core leg TOO. Not channel-only-by-default. CONTEXT is the design source of truth and it says every path honours the order; I check every decision against it and I am not carving an exception here. Two reasons beyond the text. First, the alternative is a user-visible inconsistency with no explanation an operator could infer: adapter installs would prefer peers while core silently would not. Second, #339 exists precisely so a node cut off from the channel but present on its subnet can still move — a composite that is channel-only by default fails the case the request was filed for. Three constraints on it, all binding: - The verify is UNCHANGED. Peer-served core bytes pass the same signed-set gate as any other path. A peer is a place to ASK, never a reason to ADMIT. Same property as your point 1, applied to core. - --remote forces the channel, as planned. - Do NOT move the GitHub fetch out of the CLI. That boundary holds — HTTP stays out of the daemon. The composite asking peers first does not license the daemon to fetch from the channel. The duplication with the pump is acceptable and not a defect: the pump stages in the background on its own cadence, while the composite is an explicit user action that must succeed on the spot. Two callers of the same ladder is the intended shape. BRANCH POINT: still hold. W3 compile gate is green at 66bf3c00 and the targeted unit legs are running now. You get the landed sha from me and branch once.