Skip to content

History / Reading Long Tickets

Revisions

  • Reading long tickets: remove the named third-party quote stripper Both pages cited Mailgun's talon by name and quoted a figure for how often it succeeds. The argument does not need it: every mail client marks a quoted chain differently, plenty do not mark it at all, and a forward can look identical to a reply - so any approach is wrong some of the time, which is the whole reason a wrong boundary has to cost a click rather than a fact. Quoting another project's failure rate is not something we want in our docs.

    @edmozley edmozley committed Aug 31, 2026
  • Reading long tickets: split into user + two developer guides, with real code Ed's ask: dev articles should carry actual code snippets of the important bits with explanations, and splitting into two dev pages is fine. Reading-Long-Tickets user-facing, no internals Reading-Long-Tickets-Developer-Guide the three automatic behaviours Ticket-AI-Reading-Developer-Guide the summary and the briefing Both dev guides open with the invariant Ed asked to be made explicit: NOTHING EVER DELETES CONTENT. Stated as checkable properties rather than a slogan — no DELETE or UPDATE of a body anywhere in either feature, the full body of every message including a flagged duplicate is in the JSON and the DOM, a refresh writes version n+1, and everything survives the feature being switched off. Verified by grep, not asserted. Both also name the one boundary honestly: stripInboundThread() at INGESTION stores only the new part of an inbound reply. Nothing on either page does that, but a developer chasing "where did the rest of the email go?" needs to be sent to the right file rather than left trusting a promise the system does not keep end to end. Every snippet is quoted verbatim from the source and checked (18/18) rather than written from memory. The ones that earn their place are the bugs that nearly shipped: measuring the shadow root instead of the host (zero-tall <style> as first child, so nothing would ever have collapsed, silently); reading nextElementSibling after appendChild has already moved the node; and the missing busy guard that made every click during a minute-long wait a fresh paid call.

    @edmozley edmozley committed Aug 31, 2026
  • Reading long tickets: the briefing is kept and versioned (#1436/#1437) Storing nothing meant waiting 62 seconds for a briefing you had already read. It now shares the summary's table with kind='read' and inherits its rules; reopening is 0.16s and free, only Read again spends anything. And the busy guard, which is not cosmetic: before it, a click during that minute fired a second PAID call whose answer overwrote the first — and a motionless "Reading the ticket…" is exactly what makes somebody click again.

    @edmozley edmozley committed Aug 31, 2026
  • Reading long tickets (#1429-#1435) + the reasoning-model trap A new page covering everything from discussion #104 in one place: shortening long messages by RENDERED HEIGHT rather than line count, folding the older part of a long ticket, flagging a message that has arrived before, the versioned AI summary, and "read it for me". The rule that runs through all five is written down at the top: nothing deletes, hides or replaces anything, because deciding where quoted history ends is genuinely hard and a wrong call has to cost a click rather than a fact. AI-Providers gains the finding that came out of testing it: a reasoning model spends its output budget thinking BEFORE it writes any content, so a modest max_tokens returns HTTP 200, a full bill and an empty answer — which every AI feature reported as its own generic failure. Measured on qwen/qwen3.7-plus, a one-sentence question spent 375 reasoning tokens of 383.

    @edmozley edmozley committed Aug 31, 2026