Resumes work left mid-session on the M1 hostile-mode matrix. download_task.cpp:
- Replace the old cancel-then-clear teardown (cancel_all_transfers_locked /
start_assembly_locked) with a single begin_drain_locked()/PendingAction
mechanism: cancel every live worker, remember what to do (verify / fail /
auto_pause / demote), and let whichever worker's seg_finished finds the
worker map empty carry it out. Every sibling still flushes its buffer on
the way out, so no buffered-but-unflushed tail is lost when a download
finishes or fails while other segments are still mid-transfer.
- A 200 where 206 was expected (wrong_status) now checks the response's
ETag/Last-Modified against the probe's: a real mismatch asks the user
(server_file_changed, "ask, never silently corrupt" -- docs/04 §5); a match
means the server just stopped honouring Range for this connection, so
demote to one segment and keep going without a round trip (docs/04 §7).
- 416 mid-download (stale range metadata) now surfaces as a decision instead
of retrying the same now-invalid range to exhaustion.
- do_decide's abort path surfaces the actual reason a decision was asked
for (last_error) instead of hardcoding server_file_changed, which was
mislabeling a 416 abort.
engine_test.cpp adds the four hostile modes where a bug means silent
corruption rather than a visible failure: etag-changes, 416-always,
lies-about-accept-ranges, content-length-mismatch.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Q3QrF7rCt21bkAjt9BCDFQ