Reverse of ReceiptThread::as_str: parse a stored thread tag into the
enum. Empty string maps to Unthreaded; "main" to Main; anything
starting with $ to Thread(event_id) if parseable.
Private read receipts surfaced by private_read_get. One legacy
unthreaded row plus zero or more per-thread rows; inline-1 catches the
dominant case (a single unthreaded marker) without a heap alloc.
Stored thread-kind tag: "" for Unthreaded, "main" for Main, or
the event-id string for Thread(...). v3+ event ids are 44 bytes
including the leading $; 48 bytes inline matches the project’s
StateKey budget and stays inline for every realistic thread root.