Repository navigation
Conversation
Co-authored-by: Codex <codex@openai.com> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Co-authored-by: Codex <codex@openai.com> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Co-authored-by: Codex <codex@openai.com> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Co-authored-by: Codex <codex@openai.com> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
|
🤖 Independent agent review of These captures show actual updated components with disposable synthetic fixture data. They establish the displayed light-theme browser states only. Reply controls at narrow width: the Reply message icon appears beside the preserved Forward action. Inline reply: a 100 ms hold presents the preview inside the existing composer and retains the draft. Escape: canceling removes the reply target while preserving the draft and reading position. Required hosted CI and DCO passed on |
Co-authored-by: bmo <a7b504d9a2bfe905589e9ac237d7d8d023b8d10547060ec9618e6487b55d756c@buzz.block.builderlab.xyz> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Use real message links for thread-pane setup while preserving draft, focus, media and activity assertions. Verify Reply in channel and Solo composers without expecting pane navigation. Co-authored-by: bmo <a7b504d9a2bfe905589e9ac237d7d8d023b8d10547060ec9618e6487b55d756c@buzz.block.builderlab.xyz> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
kalvinnchau
left a comment
There was a problem hiding this comment.
🤖 Two behavioral regressions and one memoization issue found. The held-pointer CI failure remains unresolved despite passing local repetitions.
Keep the immediate 100 ms hold interaction intact. Prevent target messages from seeding another author's agent mentions, reuse the timeline reply callback, and exercise held scrolling in the verified timeline gutter. Co-authored-by: bmo <a7b504d9a2bfe905589e9ac237d7d8d023b8d10547060ec9618e6487b55d756c@buzz.block.builderlab.xyz> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Co-authored-by: bmo <a7b504d9a2bfe905589e9ac237d7d8d023b8d10547060ec9618e6487b55d756c@buzz.block.builderlab.xyz> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Co-authored-by: bmo <a7b504d9a2bfe905589e9ac237d7d8d023b8d10547060ec9618e6487b55d756c@buzz.block.builderlab.xyz> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Co-authored-by: Codex <codex@openai.com> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Co-authored-by: Codex <codex@openai.com> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
kalvinnchau
left a comment
There was a problem hiding this comment.
🤖 Two additional findings: delayed text selection loses focus, and Reply icon guidance contradicts the implementation.
Keep the 100 ms preview, defer composer focus until release, and cancel provisional reply targets when dragging or selection wins. Preserve the chosen Reply icon and document its approved usage. Co-authored-by: Codex <codex@openai.com> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
kalvinnchau
left a comment
There was a problem hiding this comment.
🤖 One remaining cancellation defect: withdrawing the reply preview does not restore live-bottom following.
Restore the prior reading state only while the provisional reply still owns it. Preserve newer scroll intent in channel and thread timelines, with browser regressions for selection cancellation and upward scrolling. Co-authored-by: Codex <codex@openai.com> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Establish option focus before Home/End and Enter so the save-failure test exercises the intended selection. Preserve existing success, persistence, and error assertions. Co-authored-by: Codex <codex@openai.com> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Carry Bestie reply state into its extracted workspace component and keep Activity on shared conversation tabs. Adapt the Inbox reply test to current props and tabs, and await applied split geometry in resize assertions. Co-authored-by: Codex <codex@openai.com> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
…rements Keep the current channel or thread reading anchor when rows arrive during a provisional reply. Compare the existing loaded message snapshots so strict threads work without loading older pages or changing unread policy. Open the thread-scroll measurements through the actual thread link, and wait for settled pane geometry before aiming scrolling input. Cover arrivals before selection in both scroll owners and a partially loaded strict thread; wait for real pointer readiness and an active, settled preview in wheel cases. Integrate main 028e5a1, including its timeline width measurement changes. Co-authored-by: Codex <codex@openai.com> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Integrate Builderlab catalog/settings updates, the keyboard latest-message ordering fix, and the channel-settings Shift+Escape correction. The reviewed held-reply cancellation fix is unchanged. Co-authored-by: Codex <codex@openai.com> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
|
🤖 Addressed the P1 thread-scroll measurement failure in Both opening paths now use a real Buzz thread link instead of inline Reply. The opening click remains inside the measured interval; scrolling waits for the opening pane's geometry to settle before aiming input. Corpus, gesture distances, and assertion thresholds are unchanged. All six isolated open/fling/reverse samples passed across Chromium and WebKit. The P2 selection-anchor fix and its channel/thread/partially-loaded-thread regressions are included. All 114 affected browser cases passed, including the notification and cancellation cases that failed in prior hosted WebKit CI. Mandatory hooks and DCO passed; independent review and Arjun's integrated desktop acceptance are complete. The new hosted run is still pending: https://github.com/block/buzz-app/actions/runs/42132643607. I am keeping the PR draft until that result is checked. |
Integrate main and update the keyboard preference journey to open a thread link. Retire stale channel preview positioning, refresh paused-reader arrival controls, and respect newer thread scrolling while retaining real resize clamps. Co-authored-by: Codex <codex@openai.com> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Keep the composer focus-restoration and removed-field fallback checks while avoiding an assertion against a transient pre-menu focus state after the asynchronous menu open. Co-authored-by: Codex <codex@openai.com> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
|
🤖 Fixed and pushed as 50575c6. Hosted CI run 42163080324 completed successfully: 73 checks passed, one configured Windows skip, no failures. Both previously failing jobs are green. All review threads are resolved. Mandatory push hooks passed; final repair passed 137 owner tests and 68 browser cases on Mac and Linux, plus 63 Linux WebKit reply repetitions without retries. The PR remains draft pending human acceptance of the final tiny-scroll/scrollend boundary; earlier Mac checks were accepted. https://github.com/block/buzz-app/actions/runs/42163080324 |
Co-authored-by: Codex <codex@openai.com> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
kalvinnchau
left a comment
There was a problem hiding this comment.
🤖 One remaining WebKit reading-position failure; the prior native-selection and thread-scroll measurement issues are repaired. Required CI remains red.
Record upward channel intent before sampling near-bottom follow, and resume thread following for downward wheel input at the actual end. Cover slow cancellation and synchronous toolbar forwarding without changing the existing full-wheel or notice-overlap assertions. Integrate main. Co-authored-by: Codex <codex@openai.com> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Capture the queued restoration's scroll position and upward-input evidence. Newer native movement retires the restoration generation before it can overwrite the reader, including cleanup writeback. Preserve browser clamps and settled-state bookkeeping. Integrate the current navigation contract from main. Co-authored-by: Codex <codex@openai.com> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Co-authored-by: Codex <codex@openai.com> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
kalvinnchau
left a comment
There was a problem hiding this comment.
🤖 No new proven regression found. The completed tiny-scroll contract still needs explicit acceptance and coverage; see inline comment.
| "selection with pending arrivals", | ||
| "scroll", | ||
| "slow scroll", | ||
| ]) { |
There was a problem hiding this comment.
🤖 [P3] Cover arrivals after the completed shallow scroll
The slow-scroll case checks a positive gap after 20 px, then scrolls another 330 px before testing arrivals. It therefore does not distinguish the completed shallow-gesture contract: ChannelTimeline.tsx:1824 clears upwardGesture before final position sampling and can resume following within its 80 px bottom threshold, while ThreadPanel.tsx:1879 keeps a shallow upward move paused. The thread variant is skipped here. This is a contract/coverage question, not a proven regression against main. Please explicitly accept or reconcile the two behaviors and assert an arrival after the shallow gesture has completed, before the second scroll; cover the thread behavior or document why it differs.
Preserve the reply-hold and agent activity changes when resolving conflicts, keep the awaited community-menu focus barrier, and remove the duplicate ChannelTimelineProps import introduced by the automatic merge. Cover live arrivals after completed shallow gestures in channels and threads. Retire a settled channel anchor within the existing one-pixel scroll tolerance: Chromium rounded the restored position by one pixel and otherwise retained that anchor indefinitely, preventing near-bottom follow from resuming. Co-authored-by: Codex <codex@openai.com> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Integrate main through a58e604. Complete the native thread reveal frame before the Inbox reading fixture takes over timers, then dispatch the window focus event under the controlled clock. Current main and the prior merged PR both reproduced the same stalled-reading assertion; the full Inbox file now passes all 150 cases without changing assertions, timeouts, or production reading semantics. Co-authored-by: Codex <codex@openai.com> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Deliver the root insertion's MutationObserver callback before advancing the frame clock. The reading observer now keeps its lifecycle when only the latest message changes, so the fixture must exercise its deferred measurement instead of depending on an effect restart. Keep the 300ms dwell and exact catch-up assertion unchanged. Co-authored-by: Codex <codex@openai.com> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Resolve the overlapping catch-up fixture change in favor of upstream's measurement frames and 299ms/300ms boundary assertions. Preserve the PR's Solo thread composer coverage and reply/scroll owners while integrating current coordination-history behavior. Co-authored-by: Codex <codex@openai.com> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Keep upstream's keyboard option-focus sequence when resolving the duplicate authorization test repair. Preserve its custody and recovery assertions while integrating the current Messages navigation and Canvas fixes. Co-authored-by: Codex <codex@openai.com> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
Sample a fresh converged restoration after reader input even when its scroll is a no-op, retaining existing preview and cold-restoration anchors. Do not reclassify a late observation of a finished wheel gesture as active input. This preserves the shallow reading offset until arrivals and keeps larger upward gestures paused. Integrate current main and retain its event-based Inbox readiness fixture. The scroll source matches the independently reviewed Linux snapshot that passed 292 owner tests, 34 browser cases and 30 focused repetitions. Co-authored-by: Codex <codex@openai.com> Signed-off-by: Arjun Mahanti <arjun@squareup.com>
…uzz tools (#2707) ## TL;DR An approved external app (like Nexus) now gets the selected agent's whole Buzz MCP tool catalog and native dispatcher, including tools plugins add later, after one explicit "full access" approval. Before, it got a hand-picked list of six tools with rewritten arguments. Older narrow approvals still connect but grant no tools until the owner approves full access again, so no existing grant widens on its own. Initiative status: https://g2.sqprod.co/apps/kylez-nexus-buzz-plugins-status Fixes NEXUS-4262 ## What changes - **One scope, `agent`.** New links request `scope=agent`, and `agent` can't be combined with other scopes. Rust pairing accepts only `["agent"]` for new approvals (`valid_scopes`). Saved `read`/`post`/`create` approvals still load, renew and resume, but grant nothing. - **No adapter.** `respondExternal` now passes `tools/list` and `tools/call` to `respond` in `rpc.ts`, using the same `sessionTools(added)` catalog as native sessions. Plugin-added tools come from `addedTools.snapshot()` (the source native harnesses use) and are re-read on every message, so enabling or disabling a plugin changes the catalog live. The old policy map, argument rewriting and Bestie injection are removed. - **The agent's own authority.** The connection uses the agent's run handle (`runners.handle(key, undefined, true)`), so it gets device settings, plugin requests, Git access and handoff exactly as a native run does. Plugin installs still go through the owner's confirmation. Memory reads use the agent's `memoryListing`, like the native plugin path. Protected agents are still refused. `plugin_disable` acts at once, as it does natively, and the consent text says so. - **Handoff with true provenance.** `self_handoff` goes through the run's own handoff and `Agents.wakeIn`, but its `from` is `{ external: true }`. `wakeSection` shows it as an `<app-wake>` section that says an external app the owner approved sent it, and that it is not a message, a watch or timer, or another of the agent's conversations. - **Files where the agent reads them.** `send` with `path`/`files` calls a new optional `AgentType.readFile`. Claude, Codex, Pi and goose implement it with the reader their own tools use, in the agent's saved workspace on this device. Relative paths start there; absolute and `~/` paths reach any file the account can read, as they do natively, and the consent text says so. A Claude or Codex agent bound to an execution target refuses, because only a conversation's session opens that target. A type without `readFile` refuses with the same message its tools give natively. Closing the connection cancels a read in progress. - **No implicit conversation.** Calls run with an empty context, so every tool needs explicit channel or message IDs. - **Consent.** The dialog now states full access plainly: future plugin tools, Git access, waking the agent, Nexus workers, settings changes, posting any file the agent can read (including outside its workspace), and immediate plugin disabling. A legacy narrow link shows an update-required notice with Deny only, which sends the normal denial callback. `approve()` refuses non-`agent` requests as a second check. Agent settings flags a saved legacy approval as no longer working. ## Companion-client contract (for the Nexus consumer) | | Behavior | | --- | --- | | Request | `scope=agent` alone. Narrow scopes get the update-required notice and only a denial callback. | | `tools/list` | The full native catalog: 66 built-in tools with settings, plus plugin tools. Each tool is listed as natively, plus `_meta: {"buzz/requiredScopes": ["agent"]}`. Result `_meta`: `buzz/grantedScopes` (`["agent"]`, or `[]` for a legacy approval) and `buzz/supportedScopes: ["agent"]`. Cursors are rejected (single page). | | `tools/call` without the grant | `isError` result, nothing dispatched, `_meta["buzz/error"] = {code: "authorization_required", required_scopes: ["agent"]}`. | | `tools/call` with the grant | Native result and errors, unchanged. | | `self_handoff` | Native arguments. The wake reaches the agent as an `<app-wake>` from the app. | | `send` `path`/`files` | Read by the agent's type in its saved workspace. Agents on an execution target, and types without a reader, return their refusal. | | `channel_create` | Takes native arguments. A private Solo chat with the owner's Bestie must now pass `visibility: "private"`, `solo: true` and `members` explicitly. Buzz no longer fills them in. | An unupdated consumer that accepts only `read`/`post`/`create` will reject `supportedScopes: ["agent"]`. Its upgrade path is to accept `agent` and request `scope=agent`, which takes one owner approval. ## Overlap These open PRs touch nearby files. This PR neither depends on nor replaces any of them: - #2260 and #2685 cover external pairing and identity. - #2647 adds plugin skills to `session-tools`. - #2622 covers Bestie settings. - #1939, #1909, #1854, #2311 and #2070 change `service.ts`/`runner.ts`. - #2610 has no shared files. ## Validation Ran on a Linux Blox box against the current head: - `tsc --noEmit` and `tsc -p tsconfig.design.json`; - Biome on the touched files; - Vitest for `src/buzz-mcp`, the external connection, dialog and settings tests, `AgentsPage.test.tsx`, `service.test.ts`, `plugin-wake.test.ts` and the Claude, Codex, Pi and goose runtime tests. New tests cover the external handoff's trigger and `<app-wake>` wording, file reads through the type's reader (target workspace, cancellation on close, native refusal), the Claude and Codex workspace and execution-target cases, a saved narrow approval that a link asks to resume as `agent`, and memory read from the selected agent. The Rust pairing tests (`host_mcp::pairing`) need the Tauri system libraries, so they are left to PR CI. No browser journeys were added or removed. Independent security reviews traced authorize, approve, resume, renew and call, and found no path that grants tools without the `agent` scope. Not done: - The native desktop consent dialog and a live external connection have not been exercised against this build, including a live `<app-wake>` turn and a file read in a running Claude, Codex, Pi or goose agent. - No human testing yet. - The Nexus side of the contract is a separate change. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: Kyle Zemek <kylez@squareup.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
## TL;DR Captured explicit reads now check the current saved manual-unread journal inside the replacing transaction, so a newer local choice—including one saved by another window—is not erased. Retries retain their original cut; the additive `unread.prepareThreadRead(channelId, rootId)` captures only retained incoming replies without reading the root or advancing the channel. The fence also preserves earlier same-window queued manual actions, authorizing their revisions only after a successful save whose prior same-key intent is also captured. An earlier queued save cannot mask an intervening unread choice from another window. It leaves reading-lease ownership, passive observations, remote-marker ordering, journal format and relay protocol unchanged. Mark all now reserves one shared saved revision cut before queued writes. Each predicate retains only the revision, not a full journal copy. ### Validation - Shared-cut correction: pinned Linux Blox run of both complete owner files passed 383 tests (174 read-state; 209 unread). The per-sweep capture-budget and capture-failure regressions fail on the prior implementation; older queued-save controls pass. No new browser cases. - Linux Blox, pinned tools: both owner files passed 366 tests on the initial head. After review fixes, `pnpm exec vitest run src/features/relay/unread.test.ts` passed all 206 tests. The final queue-ordering fix passes all 174 tests in `src/features/relay/read-state.test.ts`, typecheck and the commit/push hooks. - Pre-fix channel regressions: six failures; bypassing the new transaction fences makes eleven targeted concurrency regressions fail. Replacing canonical thread selection with parent-edge traversal makes the narrow-thread regression fail. Restoring the implementation passes both owner files. - Three successful-save interleavings fail before the final fix and pass afterward, with three matching controls: channel, thread and message marks overwritten by an older queued save after another window marks unread. - Eight additional regressions fail before the review fixes and pass afterward: root/reply deletion before or after persistence, and shared sidebar hints with absent, present or cross-window forced-message overlays. - Touched-file Biome, `pnpm typecheck`, `pnpm author:build`, strict generated-SDK consumer compilation and repository commit/push hooks. - Deterministic fixture gates cover newer channel/thread/message marks, second-window saves at the transaction boundary, queued ordering, retry cuts, later arrivals, independent root/thread markers and access/lifecycle expiry. No browser tests were added or removed. Generated type-only SDK declarations expose the additive method through the existing `UnreadCapability` export; existing channel and message APIs remain compatible. Capture requires initialized read-state storage. The thread API does not discover history; receipts remain device-local. A narrow read leaves the shared sidebar hint until channel open reconciles it, since that hint has no subtree ownership. Its shared message-force fence is conservative: a newer mark elsewhere in the same channel can also reject the save. This does not establish native runtime behavior, identical remote-tuple ordering or atomicity through an operation's eventual return. Related independent work remains with #2060 (quiet Solo/Inbox), #2610 (selected-message UI), #3181 (passive recovery), and #2939/#1666/#2956 (notification/audience behavior). This change is limited to the explicit mutation/preparation seam. Fixes NEXUS-4426 [Initiative status](https://g2.sqprod.co/apps/kylez-buzz-improvements-status) *Posted by Codex (gpt-6.1-sol) on behalf of kylez.* Signed-off-by: Kyle Zemek <kylez@squareup.com> Co-authored-by: Codex <noreply@openai.com>



Holding message text previews a reply in the existing composer across Messages, Activity conversations, Bestie and conversation tabs. The preview appears after 100 ms; composer focus waits for pointer release. Dragging to select, scrolling, or Escape cancels the provisional target without losing the draft. Reply actions retain the designer-approved MessageIcon, with the icon contract documented separately from thread tabs and links.
Cancellation restores prior following only when no newer reading intent or arrivals supersede the preview. Channel and thread owners preserve the selection anchor when messages arrive during a hold, including partially loaded threads. Explicit Solo replies create threads, and the exact thread reader retains its existing verified-evidence send gates.
The final scroll repairs keep upward channel input from restarting near-bottom following and let a downward wheel at the actual thread end resume following, including wheel input forwarded synchronously by the floating action bar. The thread-scroll measurements and keyboard-preference journey open real thread links. Main through 15fdd36 is integrated. Channel resize restoration also retires an anchor when newer native upward scrolling has superseded its captured position, preventing a queued callback from reversing a continuous wheel gesture.
Validation
Earlier coverage added three arrivals-during-preview cases (channel, thread, and partially loaded thread), with none removed. Those failed before their repairs in both engines. All six isolated thread-scroll measurement samples passed; corpus, gesture distances, and thresholds are unchanged. The related community-menu test now checks setup focus before opening rather than racing autofocus; restoration and removed-composer assertions remain intact.
The existing channel scroll case remains unchanged. One additional slow-scroll case splits the same 350px input into 20px and 330px, proving the first upward step survives preview cancellation. Before repair it failed with a zero bottom gap in Chromium and WebKit.
The existing rejected-Join journey now deliberately returns to the end through the floating message-action bar, after scrolling far enough upward to pause following. It checks actual pointer targets and waits for native gesture completion. Before repair Chromium reproduced the exact hosted overlap of 23.90625px. The notice-overlap and end-position assertions are unchanged.
Native selection, scroll geometry, top-layer wheel forwarding, and real resize ordering require browser coverage. No assertions were relaxed, no retries were added, and no production test seam or new lifecycle owner was introduced.
At 321e431, all 114 cases across six affected browser files passed in Chromium and WebKit locally, and all 114 passed on Linux. Linux also passed 63/63 WebKit reply repetitions and 70/70 Chromium search repetitions (seven full runs each, two workers, zero retries), plus 2/2 focused WebKit cases. Final head 50575c6 passed all mandatory push hooks, including types, related unit tests, and design checks. Hosted CI run 42163080324 passed on final head 50575c6: 73 successful checks, one configured Windows skip, no failures. Independent review found no blockers. Human acceptance covered those channel and thread repairs in the Mac desktop app. A subsequent pre-push unit regression found completed tiny near-bottom gestures retained active input intent; 50575c6 clears that intent before the final scrollend sample. All 137 existing owner tests and all 68 affected browser cases pass on Mac and Linux after that one-line repair. All 63 final WebKit reply repetitions passed on Linux with zero retries. Human acceptance of this last boundary remains pending.
The shared composer, ReplyContext, message action bar, and existing channel/thread scroll owners remain responsible for the UI. Earlier desktop checks covered identity/community loading, Bestie/Activity replies, drafts, Escape, and light/dark narrow/wide presentation. This follow-up changes scroll behavior; artwork is unchanged. Ready for review at Arjun’s explicit request on 2026-11-06. Automated validation and independent review are complete. Human acceptance of the final completed-tiny-gesture boundary remains pending; this readiness request does not attest that check was performed.
Conflict and shallow-scroll follow-up (2026-11-06)
Integrated main through 15fdd36 without rewriting the PR history. The MessageRow conflicts retain reply holds and incoming agent activity behavior/tests. The community-menu test retains both setup-focus checking and awaited menu autofocus. The later authorization-fixture overlap retains main’s keyboard option-focus sequence and all custody/recovery assertions. Removed the duplicate ChannelTimelineProps import created by the automatic merge.
Kalvin's P3 coverage question exposed a concrete Chromium boundary: a restored row settled at Y=54.984375 for a requested Y=55.984375. Exact equality kept the old anchor active and prevented arrivals from resuming near-bottom following. The existing channel owner now accepts its one-pixel scroll tolerance when retiring that settled standalone anchor; same-row, membership, and bottom-clamp guards remain intact. No new lifecycle state, timer, retry, or scroll policy was added.
Added two browser scenarios, with none removed: channel and thread arrivals after a completed 20px upward gesture, before further scrolling. Native wheel completion and real layout/delivery require the browser layer. The channel case failed before repair in Chromium. Channels retain their existing <80px follow policy; threads retain the upward reading intent already implemented in this PR. The tests document and exercise that distinction.
The current Inbox fixture uses main's event-based reading-position readiness and cleanup. This supersedes the earlier PR fixture synchronization while retaining every unread assertion and the existing fake-time limits. The resolved complete file passed 150/150 tests locally.
Final synchronization retains main's thread catch-up test fix from #2837, including its measurement frames and the negative assertion at 299ms before catch-up at 300ms. The earlier local synchronization change is superseded by that upstream version; the PR's Solo thread composer assertions remain intact.
The Linux WebKit failure on 17ee960 exposed two resize/scrollend orderings in the existing channel owner: a queued no-op anchor restoration could miss the final follow sample, and a late native wheel step could be reclassified as active input after the gesture had ended. The repair samples a fresh converged restoration after reader input while retaining preview-owned and cold-restoration anchors, and preserves completed-gesture state when superseding stale restoration. Production changes are eight additions and one replacement in ChannelTimeline.tsx; no tests, thresholds, timeouts, or retries changed for this repair.
Validation of that exact source snapshot on Linux: 292/292 owner tests; 34/34 complete message-click-reply and thread-resize browser cases across Chromium and WebKit; 30/30 focused shallow/slow/pending-arrival repetitions with zero retries. After integrating main, aa55728 passed all 58 cases across message-click-reply, thread-resize, activity-lifecycle and local-agent-activity in both engines on macOS (4.1 minutes). Independent review found no blockers (9/10). All mandatory push hooks passed on aa55728: TypeScript and related unit tests (498.56 seconds), design types/guards, Rust selection, and policy checks. DCO passed, and GitHub reports the PR mergeable. Hosted CI run 42271653744, attempt 2 passed on aa55728. Both required checks (CI required and DCO Check) passed, and GitHub reports the current head mergeable. All browser journey and repeated-check shards passed in the first attempt. The native lane exceeded its existing 20-minute budget, also reproduced on current main; a targeted retry of that cancelled lane and the aggregate passed without changing the budget or coverage. Native human acceptance remains separate.
The owner returned the PR to ready-for-review at 17:15:48 UTC on 2026-11-06; that concurrent status update is preserved. Native human acceptance of this precise boundary remains pending, and no review-completed attestation is added. In the updated desktop build, hold message prose until the reply preview appears, scroll upward about 20px and release, then observe a peer arrival: a channel near its end follows it, while a thread preserves the reading position. The draft and canceled reply state must remain intact. Continue farther upward to verify ordinary paused reading. Hosted checks and this attended desktop check are tracked separately from the macOS fixture results above.