ingestframe: switch the worker wire format to DRISL CBOR master
The worker↔main protocol was a hand-rolled magic+type+length framing. Swap it for a stream of concatenated DRISL CBOR items — the same codec muxl uses for its own stdio protocol — so the whole stack speaks one self-describing, debuggable format and we stop maintaining a bespoke parser. CBOR data items are self-delimiting (the length/count is in each item's head), so the separate length prefix is redundant and goes away. Crucially this PRESERVES the crash-vs-clean-end signal the supervisor depends on: the decoder returns io.EOF at an item boundary (clean end) and io.ErrUnexpectedEOF mid-item (a worker that died) — verified against the real hyphacoop/cbor decoder, not assumed. A garbage/desynced stream now fails to decode rather than being mis-parsed (replaces the magic-tag guard); the explicit MaxPayload cap is dropped (the decoder grows incrementally rather than pre-allocating a hostile declared length, and the peer is a trusted local subprocess). - frame.go: each frame is one DRISL CBOR map {type, payload} (payload omitted when empty, e.g. End). Writer marshals via drisl.Marshal then writes under the lock (frames still never interleave); Reader wraps drisl.NewDecoder. The public API (Type constants, Writer/Reader, WriteFrame, the per-type helpers) is unchanged, so consumers don't move — except: - A streaming CBOR decoder READS AHEAD, so a Reader now owns its stream for the stream's lifetime. consumeWorkerFrames takes a *Reader instead of an io.Reader, and the WHIP path reuses ONE Reader across readWHIPAnswer → the segment consume (a second Reader would lose buffered read-ahead). The reconnecting socket consumer still makes a fresh Reader per connection, which is correct — a reconnect replays the worker's buffer from the start. go-dasl moves from indirect to a direct dependency (used via its drisl subpackage); hyphacoop/cbor stays indirect (a small interface avoids importing it here). Tests: round-trip across all frame types; truncation = ErrUnexpectedEOF, torn-head = ErrUnexpectedEOF, clean-boundary = EOF, garbage = decode error, all re-proven against the real codec; concurrent-writer integrity. The whole worker stack still passes over real pipes/sockets/ICE — subprocess framing, buffered socket reconnect, and the WHIP Answer-then-segments single-decoder path (TestWHIPWorkerLoopback). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>