fix: tell one proposal's transcript lines from another's
A room with two proposals open showed "Review" on both, and then dropped it from both the moment either one was decided. The second proposal was still waiting on the reader, still had a decision in it, and had nowhere left to be reached from. Two proposals at once is not a corner case any more: a chapter and the translation scaffolding beside it are proposed as separate sessions, on purpose, and they run at the same time. Both write the same line types into the same stretch of transcript. `answeredRequests` matched a request against any later line of the fulfilling type, and `settledRequests` against any later ending. That reads a room signing one thing at a time exactly right -- the nonce after the request is the answer to it, because there is nothing else it could be an answer to -- and a room signing two things at once exactly wrong. Nothing else on the row could separate them: same type, same room, same minute, and `ChatMessage` carried no session. So the session goes on the row. `ChatMessage.frostSigningSessionId` is nullable, added as schema v11 through `AutoMigration(10, 11)`, and stamped by `FrostSigningManager.announce` -- the one place every FROST line is written, so there is no line that can be forgotten. Both rules read it when both rows have one and fall back to the clock when either does not. The fallback is not a compromise, it is the right reading of the rows it applies to. A line written before this column has no session and never will, and the rooms that wrote those lines could not run two sessions at once, so the clock is the whole truth there. A ceremony line falls back too and always will: a room runs one ritual at a time, and a DKG step is either taken or still waited on. **This reverses a call `FrostSigningRoute` argued for.** Its note said a chat row carrying a session id was "a poor trade for a lookup the screen can do". That was right when the lookup could only be wrong about which of one session it meant. The batch work made two sessions ordinary, and the lookup and the rules both became guesses at the same moment. A column on the table every message uses is the cost; two proposals, one of them unreachable, was the alternative. **Tests.** Three in TranscriptRequestStateTest for what the column buys: a nonce answers its own session's request and not the other's, one session completing settles nothing in the other, and a line naming no session is still read by the clock. TranslationBatchProposalJvmTest proves the other half against a real two-session proposal -- every FROST line the manager writes names its own session, and neither session's lines are attributed to the other. The rule is tested on rows and the stamping is tested on a database, because a rule that is right about rows nothing writes correctly is worth nothing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -408,6 +408,24 @@ part of 12 events". This is worth checking rather than assuming, because a new
|
||||
type would need adding to five sets and would silently render as a chat bubble
|
||||
if missed from `FROST_TYPES`.
|
||||
|
||||
**What this missed, and how it was fixed.** The claim above holds for `k` events
|
||||
in one session and breaks for two sessions at once, which
|
||||
[the first caller](#the-first-caller-a-chapter-and-its-chunks) went on to need: a
|
||||
chapter and the translation scaffolding beside it are two proposals, open
|
||||
together, writing the same line types into the same stretch of transcript.
|
||||
`answeredRequests` and `settledRequests` matched a request against any later line
|
||||
of the fulfilling type, so answering one of the two dropped the "Review" on both
|
||||
— the second proposal became unreachable from the transcript the moment the first
|
||||
was decided.
|
||||
|
||||
Nothing on a row could tell them apart, so `ChatMessage.frostSigningSessionId`
|
||||
was added (schema v11, nullable, `AutoMigration(10, 11)`), stamped by
|
||||
`FrostSigningManager.announce` on every line it writes. Both rules read it when
|
||||
both rows have one and fall back to the clock when either does not — which is
|
||||
what a line older than the column has to be read by, and is right for those
|
||||
rooms: nothing that predates batch proposals ran two sessions at once. A ceremony
|
||||
line still uses the clock always, since a room runs one ritual at a time.
|
||||
|
||||
---
|
||||
|
||||
## Phase 6 — the test that actually proves it
|
||||
|
||||
Reference in New Issue
Block a user