Files
pl_mail/migrations
Claude 044aa01846 Reported mail is one feature: one list, one triage, one export you choose
Two kinds of report — a mail an extractor should have understood and did not,
and a mail somebody found in the wrong tab — were two tables behind two panels
with two export buttons. That split made sense to whoever wrote them and to
nobody using them: an admin opening this section is asking "what is still mine
to do", and that question does not have two answers.

The tables stay apart, because the evidence really is different: a wrong tab is
a disagreement between three classifiers, a missed insight is a mail body a
parser could not read, and making them inherit would put a dozen always-null
columns on each row and tie a schema change on one to the other for ever. What
is unified is everything above them. ReportedMail carries the handful of fields
a triage list is built from and the entity alongside for the fold and the
export; ReportedMailProvider is the only place that knows there are two tables;
the panel, the buttons and the file are written against the pair.

Category reports gained handledAt, which is what makes them belong in the same
list — a worklist you cannot cross anything off is not a worklist. Before this
the only way to stop looking at one was to delete every one of them, taking the
evidence for a rule away at the moment somebody might want to check it again.

The export's scope becomes the selection. "Everything, or only the unhandled
part" answers the question an admin has on their first visit and none of the
ones they have afterwards; the one that comes up is "these six, the ones about
the shop". So the list filters — by status, and by the problem itself, with the
chips derived from the rows because for a wrong tab the problem IS a pair of
categories and only this install knows which pairs it has produced — and the
export takes what is ticked. Filtering never unticks anything: a row hidden by
a chip is out of the selection while it is hidden and comes back ticked, so a
selection built across two chips survives. An empty post still means everything,
which is what a browser without JavaScript sends.

Each record now carries its kind, every field its kind has, and the same
one-line rendering the panel shows and the copy button copies. The document is
plmail.reported-mail version 2 — a new name rather than a bumped version alone,
so a consumer written against version 1 fails on the name instead of half-reading
a file whose records it only understands some of.

The row is a <div> and not a <label>, though a label around the whole row would
give the checkbox a better hit target: a label may not contain a <form> or a
<details> and both are there. Chromium happens not to forward label activation
from a nested button, which means the invalid version works right up until the
row is read by something that is not Chromium.

Verified on a running stack: six reports of both kinds in one list, the status
chip hiding the handled one, select-all writing five keys into the export form,
a problem chip narrowing that to one without losing the other four, and the
export returning scope:selection with the full record and its line.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 15:21:11 +02:00
..
2026-07-16 12:59:19 +02:00
2026-07-17 10:34:32 +02:00
2026-07-17 12:47:20 +02:00
2026-07-17 18:19:47 +02:00
2026-07-17 18:19:47 +02:00
2026-07-19 20:38:41 +02:00
2026-07-19 20:38:41 +02:00
2026-07-20 10:56:25 +02:00
2026-07-20 10:56:25 +02:00
2026-07-21 13:40:57 +02:00
2026-07-23 13:53:37 +02:00
2026-07-23 14:17:49 +02:00
2026-07-24 13:56:18 +02:00
2026-07-24 13:56:18 +02:00
2026-07-24 22:26:19 +02:00
2026-07-25 10:47:50 +02:00
2026-07-25 10:47:50 +02:00
2026-07-26 10:58:31 +02:00
2026-07-27 12:15:24 +02:00
2026-07-27 13:10:36 +02:00
2026-07-27 13:10:36 +02:00
2026-07-28 00:26:47 +02:00
2026-07-28 12:33:46 +02:00
2026-07-28 13:37:30 +02:00
2026-07-28 22:25:00 +02:00
2fa
2026-07-31 07:18:26 +02:00