mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
Round-2 review found two defects in the previous repair commit. **The mutation whose ingest failed was dropped.** `enqueueNative`'s recovery reopened the authoritative snapshot and resolved, so the captured mutation was never retried or preserved — and the reopened snapshot is the store *without* that write. A rejected marker un-read the channel; a rejected `removeChannel` /`clearAll` resurrected rows the user had just cleared, because those delete their projection optimistically first. The previous test proved the chain healed, not that the operation survived: it asserted only that the *next* command landed. Every captured mutation now gets one retry after `reopen` refreshes sequence and revision, which is safe because ingest is idempotent — events upsert `DO NOTHING`, channel latest advances by `MAX`, membership is `INSERT OR IGNORE`, and a replayed sequence returns a snapshot rather than reapplying. A `snapshotRequired` response takes the same recovery path instead of being treated as success. If reopen and retry both fail, native is explicitly degraded and the equivalent event/marker/latest/clear state is applied to the JS fallback, so `isNative()` stops reporting healthy. Membership needs no fallback copy: its renderer-owned sets remain authoritative. **A superseded archive start could tear down the newer scope's relay session.** `begin` claimed ownership and released its guards, then `start_archive_sync` awaited `archive_session`. `ensure_session` shuts down a different scope's socket and installs its own inside its own lock, and `attach_archive` replaces the session's archive sender outright — both destructive on entry. So a stale start B could win `begin`, pause, let newer C claim and install, then resume, shut C's session down, and attach the archive stream to a task whose token was already cancelled. B cleared its subscriptions on exit and archive sync stayed dead until the next lifecycle edge. Revalidating the mark after the await cannot fix this: by the time B discovers it lost, C's socket is already gone, and a session is spawned rather than handed back, so there is nothing to restore it from. The damage is done by the call, so the fence is around the call. `begin` now returns an `ArchiveOwnership` token holding both guards, and `archive_session` requires one. The token is un-constructible outside `archive::sync`, so a stale start cannot reach the call at all. This is sound because acquisition performs no I/O: both halves await only mutex acquisitions and the socket connects on a spawned task. Reverting the token does not compile, so the Rust regression pins the property its usefulness rests on — while an owner holds the token, no newer start can claim. That goes red against the mutant this design exists to stop: keeping the token but releasing the guards inside `begin`, which compiles and restores the race. The JS regressions assert the originally rejected marker, destructive clear, and membership delta each survive, and go red when the retry is removed. Co-authored-by: Wren <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@buzz.block.builderlab.xyz> Co-authored-by: Tyler Longwell <tlongwell@squareup.com> Signed-off-by: Tyler Longwell <tlongwell@squareup.com>
Buzz
Desktop chat shell with:
- Tauri + React + TypeScript + Vite
- Tailwind CSS
- shadcn/ui-ready shared components
- Biome (lint/format/check)
- Feature-driven frontend structure
Scripts
pnpm dev- run the web frontendpnpm tauri dev- run the desktop apppnpm build- typecheck and build frontendpnpm typecheck- TypeScript checkspnpm lint- Biome lintpnpm format- Biome format (write)pnpm check- Biome check
Structure
src/shared- reusable app-wide code (ui,lib,styles)src/features- feature modules (vertical slices)src/app- top-level app composition