- services.py: normalize an href before handing it to Subdevice.to_actual.
That transform is textual and rewrites only a trailing '0' segment, so
'/mode/vs/0/' passed through it untouched and normalized downstream to
the master's '/mode/vs/0' -- landing the write on the wrong oven cavity
while still answering 2.04, with nothing in the response to give it
away. Same order now on the read path.
- services.py: key `verified` off those same normalized canonicals. It was
built from un-normalized to_actual output against the coordinator's
normalized hrefs, so a non-canonical input missed the lookup and handed
back actual hrefs where the documented contract promises canonical ones.
- coordinator.py: report `held: None` when the verify re-read itself
didn't come back. A non-2.05 yields an empty rep, against which every
payload comparison is False, so a 4.04 or dropped read was reported as
`held: false` -- indistinguishable from the board reverting the write,
which is the one distinction verify_after exists to draw.
- coordinator.py: on a mid-sequence failure, say how many writes landed
and which, and still kick the refresh. Raising bare threw that away, and
the appliance is left holding a partial sequence.
Also documents why `settle` waits inside the session lock while
verify_after's wait deliberately doesn't: a poll landing between two
writes is exactly what the sequence exists to rule out, and the caps
bound the worst case at 10 x 30s.