feat: say in the transcript that a member is being caught up

Phase 7 of docs/member-archive.md, in part. Three chat types --
`TYPE_ARCHIVE_REQUESTED`, `TYPE_ARCHIVE_SENT`, `TYPE_ARCHIVE_RECEIVED` -- so a
room that fills itself in explains itself once.

Without this the archive is entirely silent by design: it files no line per
applied payload, because `ChatMessage` has an `autoGenerate` primary key and
every payload would mint a fresh row on every pass of the sweep. The result was a
member joining a working group and watching a room populate with no account of
where any of it came from, which is worse than the noise it avoided.

**One line per archive, not per page.** The received line is written when the
request stamp is cleared, which is as close as this can get: an archive's pages
are not distinguishable from each other at apply time, and clearing the stamp is
exactly the moment a catch-up stops being pending. There is a test that delivers
a payload per page, backwards, so the sweep runs repeatedly over many pages, and
asserts the transcript holds two lines.

**A push behind a Welcome writes nothing**, because the room was never asked. It
lands before the member has opened the room, and "caught up on work you have not
seen yet" is a line about nothing. Also tested.

**The received line names no sender.** An archive can be assembled from pages
sent by more than one member, so attributing the catch-up to one would be a guess
dressed as a fact. The sent line does name its recipient, written into the
content the way the invite line writes one -- which does not follow a rename, and
is the accepted cost for a line about something that happened once.

**Content is whole sentences**, so these stay out of the AUTHORED sets and
nothing prefixes a name to them. And they are added to `ARCHIVE_TYPES` with a
matching arm in the transcript, because the failure mode for a missed set is
silent: the line renders as a chat bubble, looking exactly like a member having
said "Caught up on 12 items". Icons per type rather than the `PanTool` fallback.

**Two items from this phase are deliberately not done**, rather than written
without the app in front of me: the banner saying a room is catching up, and a
"Send history" action on the member row. The first is UI state plumbed through a
view model into a layout and the transcript line covers the same ground; the
second is a convenience, since both real paths are already automatic. Both are
written up in the plan as outstanding, along with the thing this phase was also
meant to say and does not: that an archive does not make its recipient able to
sign, and does not carry the translated text.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kgothatso Ngako
2026-09-06 14:34:19 +02:00
parent 6d8866c2b0
commit a315b86918
5 changed files with 233 additions and 23 deletions

View File

@@ -530,23 +530,41 @@ occasions.
**A day.**
- **A room being backfilled says so.** A banner on the room and on the artifact
list: *"Catching up on this group's work"*, with the page count from
`ArchivePageTag` when an archive is in flight. Without it the first minutes in
a new room are indistinguishable from a group that has done nothing, which is
the wrong first impression and generates the support question this whole
document exists to answer.
- **A "Send history" action** on the member row, for the case the automation
misses and for testing. It queues an archive to that member.
- **The transcript gets one line per archive**, not one per event: *"Sent the
group's history to X"* / *"Received the group's history"*. `TYPE_ARCHIVE`,
added to `FROST_TYPES`' neighbours in
[ChatMessage.kt](../composeApp/src/commonMain/kotlin/press/mantra/compose/database/model/ChatMessage.kt)
-- check every set a new type has to be added to, because one missed set
renders it silently as a chat bubble.
- **Say what the new member cannot do.** See below; this is the part of the
feature most likely to be reported as a bug, and the screen is where to answer
it.
**The transcript gets one line per archive**, not one per event. Three types --
`TYPE_ARCHIVE_REQUESTED`, `TYPE_ARCHIVE_SENT`, `TYPE_ARCHIVE_RECEIVED` -- in
`ARCHIVE_TYPES`, with an arm in the transcript that renders them as notices. A
type missing from that set renders as a chat bubble, silently, looking exactly
like a member having said *"Caught up on 12 items"*.
Three decisions inside that:
- **The received line is written when the request stamp is cleared**, which is as
close to one-per-archive as this can get: an archive's pages are not
distinguishable from each other at apply time, and clearing the stamp is
exactly the moment a catch-up stops being pending.
- **A push behind a Welcome writes no line at all**, because the room was never
asked. It lands before the member has opened the room, and *"caught up on work
you have not seen yet"* is a line about nothing.
- **The received line names no sender.** An archive can be assembled from pages
sent by more than one member, so attributing the catch-up to one of them would
be a guess dressed as a fact.
**Not done, and deliberately.** Two items from this phase's first draft are
left out rather than written blind:
- *A banner on the room saying it is catching up.* Worth having -- the first
minutes in a new room otherwise look like a group that has done nothing -- but
it is UI state plumbed through a view model into a layout, and the transcript
line covers the same ground badly rather than not at all. Do it with the app
running.
- *A "Send history" action on the member row.* A convenience, not a mechanism:
both real paths are automatic, so this is for the case the automation misses,
and it wants a screen to live on.
**Say what the new member cannot do.** Still unwritten, and still the part of
this most likely to be reported as a bug: an archive does not make its recipient
able to sign, and it does not carry the translated text. Both belong in front of
a member the first time they open a room they were added to late.
---