pub fn sanitize(raw: &str) -> Option<String>Expand description
Reduce a raw model answer to a storable title, or reject it.
Pure, total, and network-free, so it is the part of this module that a unit test can pin exactly.
§The rules, in order (each one is load-bearing; the order is the contract)
- Trim leading/trailing whitespace.
- First line only — everything from the first
\n(or\r) on is dropped, so a chatty answer (“Sure!\n\nSession title: …”) yields its first line, not a paragraph. - Strip quotes and backticks — remove every
",'and`from what remains (altogether, not just at the ends: a model often returns`w031 session titles`). Interior apostrophes therefore go too; a title is not prose and “don’t” reads fine as “dont” in a one-line label. - Collapse whitespace — every run of spaces/tabs becomes one space, so a tab-separated answer cannot break the single-line picker row.
- Trim again (step 3/4 can expose new edge whitespace).
- Reject empty —
None, neverSome(""). This is the ONE place an unusable answer is distinguished from a usable one; a caller that getsNonemust treat it as “no title”, not as an error to surface. - Clamp to
TITLE_CLAMPchars, on a char boundary, then trim once more. No ellipsis: a truncated name is still a name, and…would be stored in the transcript forever.
§Does not
- Strip a leading
Title:/Session:label. Not in W031’s rule list; a model that emits one keeps it (see the module friction note in the loop sketch). Adding it is a later, tested change. - Reject a long answer — it clamps instead.
- Normalize case, punctuation, or emoji.
§Panics
Never. A string of any content (invalid UTF-8 cannot reach here: &str).