Repository navigation
fix(messages): end the New messages hold when no repair can sample - #3169
Merged
Merged
Conversation
Follow-up to #3071, which made a channel longer than one page wait for the unread store's repair before placing "New messages", holding the channel's own reading meanwhile. The hold keyed on `sampled` alone. A repair that failed, overflowed its evidence budget, or was abandoned by a dropped connection or an access change left `sampled` unset with `requested` already true, so `ensure()` started nothing. Once later live evidence made the store observed again, the timeline held reading until some unrelated repair succeeded. Channel snapshots now report `sampling` while a repair that can set `sampled` is reading, about to restart, or not yet requested. The timeline holds only while it is set. Otherwise the visit settles with no line and reading resumes, including when the channel is entered after such a repair has already ended. The line inside incomplete history needed a read row above it, but any read row counted, including one read only by its own `msg:` receipt (dwell short of the bottom), which says nothing about the rows above it. `attention()` now reports `prefixRead` when the channel frontier, the `activity:` catch-up mark (ordinary rows) or the retention floor reaches the row, and only such a row lets the line sit below it. A channel read part-way by scrolling now shows no line on return. Unread mentions, broadcasts, broadcast replies and marked-unread rows above the window remain the documented residual. docs/unread.md records both. docs/buzz-help.md scopes the sentence about waiting to mark anything read to the repair check, and says the line is absent when the rows above were only read one by one. Each new regression test fails without its fix: the hold after a failed repair that becomes observed again, entry after a failed or overflowed repair, the receipt-only witness, and the store's `sampling` and `prefixRead` contracts, including the restart gap. Signed-off-by: Matt Toohey <contact@matttoohey.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
matt2e
marked this pull request as ready for review
November 10, 2026 02:33
baxen
approved these changes
Nov 10, 2026
gilgtm
added a commit
that referenced
this pull request
Nov 10, 2026
…nt-progress-rows * origin/main: Revert "ci: use larger GitHub runners for Rust and browser journeys (#3090)" (#3180) Show Goose's unset thinking level as Default, not Off (#3124) ci(release): publish stable and beta desktop releases from v tags (#3150) fix(messages): end the New messages hold when no repair can sample (#3169) Signed-off-by: Gil Birman <gil@squareup.com>
damienrj
added a commit
that referenced
this pull request
Nov 10, 2026
…rminal-font-picker * 'main' of https://github.com/block/buzz-app: (168 commits) Unify Membership sharing and live roster updates (#3147) fix(activity): show one working cue per agent request (#3166) Introduce opt-in first-agent setup (#2804) fix(codex): drop the security-review sign-in prompt from harness defaults (#3188) feat(releases): publish desktop download manifest (#3154) fix(mcp): preserve current attachments across edits (#2937) fix(agents): call the Claude and Codex first-run download "the integration" (#3165) chore(goose): bump bundled goose-acp to v1.58.1 (#3161) Revert "ci: use larger GitHub runners for Rust and browser journeys (#3090)" (#3180) Show Goose's unset thinking level as Default, not Off (#3124) ci(release): publish stable and beta desktop releases from v tags (#3150) fix(messages): end the New messages hold when no repair can sample (#3169) fix(search): make Command F search the Bestie conversation (#3084) fix(plugins): keep failed update checks on the plugin's Settings row instead of a toast (#3088) Show single-agent Stop on the activity bubble (#3140) fix: support explicit hosted browser origins (#3149) fix: keep Codex tool namespace descriptions bounded (#3128) fix(messages): show "New messages" in channels longer than one page (#3071) Keep shared agent guidance generic (#3134) fix(typing): a thread reply also ends the agent's channel-level typing (#3148) ... Signed-off-by: damienrj <damien@squareup.com> # Conflicts: # src-tauri/Cargo.toml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #3071, which made a channel longer than one page wait for the unread store's repair before placing the "New messages" line and held the channel's own reading meanwhile. This addresses the three review threads left open when that PR merged.
Problem
sampledalone. A repair that failed, overflowed its evidence budget, or was abandoned by a dropped connection or an access change leftsampledunset withrequestedalready true, soensure()started nothing. Once later live evidence made the store observed again, the timeline held reading until some unrelated repair happened to succeed.msg:receipt (dwell short of the bottom) says nothing about the rows above it, so a short repair sample could place the line below a row whose predecessors were still unread.Fix
samplingwhile a repair that can setsampledis reading, about to restart, or not yet requested. The timeline holds reading only while it is set; otherwise the visit settles with no line and reading resumes, including when the channel is entered after such a repair already ended.samplingstays set across the gap between a repair settling and its restart (repairAgain), so the hold does not flicker.attention()reportsprefixReadwhen a channel-wide read reaches the row: the channel's read frontier, theactivity:catch-up mark for an ordinary top-level message, or the retention floor. Only such a row lets the line sit below it.docs/buzz-help.mdscopes the wait to the history check and says reading resumes if that check fails; it also says the line is absent when the rows above were only read one by one.docs/unread.mdand the code comments record both behaviours and the remaining residual.Testing
Run with Hermit via
bin/pnpm, on b76ba40 (parent 5cf1713, currentmain).ChannelTimeline.restore.test.tsx,unread.test.ts,unread-startup.test.ts,use-reading.test.ts,use-reading.dm.test.tsvitest relatedonunread.tsandChannelTimeline.tsxtsc --noEmit, Biome,git diff --checktests/browser/new-message-boundary.spec.mjsEach new regression test fails without its fix:
samplingrelease fails 3 tests: the failed-repair case where the store becomes observed again before any dwell, and entry after an already-failed and an already-overflowed repair.prefixReadcheck fails the receipt-only witness case.repairAgainterm fails the store test's restart-gap assertion.samplingandprefixReadfrom the store fails the 3 store tests, including the startup test that walks failure, retry and overflow against a live session.Known limits
msg:marks) now shows no line on return. The line needs a row above it that a channel-wide read reached.activity:mark never reads them, so a short sample can still hide one.samplingnow reports it correctly. Possible follow-up, not changed here.🤖 Generated with Claude Code