[upstream-sync] Merge block/buzz 93114c9c6..f88cda9eb (15 commits) - #49
Merged
Conversation
## Summary - Makes Projects repository-aware across browsing, branch and tag selection, local and remote source management, work items, commits, and contextual repository actions. - Refines project details into consistent single-column reading surfaces with a resizable, section-aware context pod, while keeping project conversations available in the attached chat panel. - Adds persistent sidebar project navigation, direct entity links, repository discussion channels, contributor identity matching, and consistent loading and activity presentation. - Keeps branch-specific controls on code-oriented sections while Tasks, Reviews, and Channels remain repository-scoped, reducing misleading context and actions. Replacement for block#5981 with an identical final tree flattened into one signed-off commit because the required DCO check suite remained stalled. ### Related issue N/A ### Testing - [x] Desktop pre-push checks, TypeScript typecheck, and unit tests - [x] E2E production build with `pnpm build:e2e` - [x] Focused Playwright smoke coverage for project workspace, task, review, commit, sidebar, and contextual-panel behavior - [ ] Attach final before/after screenshots after design review --------- Signed-off-by: Thomas Petersen <thomasp@squareup.com> Signed-off-by: Wintermute <165f0c871dd2586bb18b6aa109eeaf57bb2132ff4d27b10120f4368a0f627022@buzz.block.builderlab.xyz> Co-authored-by: Wintermute <165f0c871dd2586bb18b6aa109eeaf57bb2132ff4d27b10120f4368a0f627022@buzz.block.builderlab.xyz>
…k#6306) ## Summary - Replaces the drawer panel icon's CSS `translateX` slide with a `motion/react` width + corner-radius morph, so the icon reads as the panel opening rather than the glyph drifting sideways. - Honors `prefers-reduced-motion` via `useReducedMotion` (no animation for users who opt out). Follow-up polish to the projects workspaces work that just landed in block#6003 — the slide animation shipped there was the wrong visual. ## Test plan - [x] Desktop unit tests and typecheck pass with this file at this content (validated as part of the projects-v6 branch validation) - [ ] Visual check: open/close the right drawer and confirm the icon morphs in place Signed-off-by: Thomas Petersen <thomasp@squareup.com>
…uted author" (block#6311) Reverts block#6129
## Summary - combine channel identity, actions, member previews, and lifecycle controls in one navigable mobile details page - add compact member management and desktop-aligned channel editing - smooth the profile entrance transition and standardize settings-group spacing - align Huddle lifecycle rows with regular message author and body spacing ## Testing - `just mobile-check` - `just mobile-test` — 1,477 tests - Pixel 10 debug build, install, and interaction review ## Snapshots ### Channel header  ### Combined channel details  ### Manage channel  --------- Signed-off-by: kenny lopez <klopez4212@gmail.com> Signed-off-by: Fast Fizz <2df81cb51f05a9d5387ef24d7b9ecb8fcdfcd1c70ffabc67061c9596e1b5b1c4@buzz.block.builderlab.xyz> Co-authored-by: Fast Fizz <2df81cb51f05a9d5387ef24d7b9ecb8fcdfcd1c70ffabc67061c9596e1b5b1c4@buzz.block.builderlab.xyz>
) 🤖 ## Summary Desktop's `#`/Tab channel autocomplete offered archived channels as if they were valid destinations. Stale channels competed with active ones in the picker, including a confusing uppercase `STREAM` entry — the badge of an archived stream channel leaking into the suggestion list. After this change, autocomplete suggests only active, non-DM channels. Links to archived channels in old messages still resolve normally. ## Demo Before/after, real archive flow:  ## What changed `useChannelLinks.ts` builds the autocomplete suggestion list from the raw relay channel list and previously excluded only DMs, so archived channels slipped through. The fix filters `archivedAt === null` while generating suggestions only — the shared navigation list stays unfiltered, so resolving historical links to archived channels is unchanged. - `desktop/src/features/messages/lib/useChannelLinks.ts` — suggestion selection centralized in `selectChannelSuggestions`; excludes archived channels and DMs; keeps the existing eight-result limit. - `desktop/src/features/messages/lib/useChannelLinks.test.mjs` — new tests: archived stream/forum excluded, active ones included, DMs excluded, mixed lists. ## Validation At exact head `5a963b8407bd48f40d992e026d0a841d2445647f`: `pnpm check`, `pnpm typecheck`, and the full Desktop unit suite (4,960 passed). Smoke E2E run compared against exact base `f956e6fe`: the only failures are two pre-existing failures that reproduce on base and four documented pass-on-retry flakes — none touches the autocomplete surface. Signed-off-by: loganj <loganj@squareup.com> Co-authored-by: Claude Code <noreply@anthropic.com>
## Summary - apply the existing 2160×3840 video resolution envelope independent of orientation - accept portrait recordings whose short/long edges fit that envelope - retain rejection coverage for either edge exceeding its limit - make the relay error describe the orientation-independent limits ## Why The iOS simulator produces portrait H.264 recordings such as 1206×2622. The relay previously checked `width <= 3840 && height <= 2160`, so the equivalent portrait dimensions were rejected while landscape dimensions were accepted. ## Validation - `bin/just ci` - `cargo test -p buzz-media` (120 passed; one MinIO integration test ignored by its existing live-service guard) - `cargo clippy -p buzz-media --all-targets -- -D warnings` - exact blocked artifact `/Users/judeedwards/.buzz/.scratch/pr5874-mongo-evidence/native/head-20260816T050317Z/video-bitexact.mp4` validated through `validate_video_file`: 1206×2622 accepted Signed-off-by: Carl <5f365698229751c0461f57bb03a4e93134e6e936bd7039ebe7b737282a43c754@buzz.block.builderlab.xyz> Co-authored-by: Carl <5f365698229751c0461f57bb03a4e93134e6e936bd7039ebe7b737282a43c754@buzz.block.builderlab.xyz>
…6024) ## Summary Moves five hot renderer paths out of JavaScript and into Rust, targeting main-thread CPU on the desktop app: wakeups, IPC round trips, and per-frame JS work during reconnect storms, catch-up, and archive sync. Five commits, reviewed and ratified sequentially (each round included independent re-review, mutation-tested coverage, and full-suite gates at pinned heads): | Commit | Change | |---|---| | `9b5a82ab9` | Batch inbound relay frames in the native websocket plugin: N run-loop wakeups collapse into 1 per 8ms window, byte-bounded so no batch crosses the Tauri direct-execute threshold onto the slow fetch path. NIP-42 AUTH bypasses the window. | | `8b047a35e` | Move the local-archive subscription into Rust: the renderer no longer sees archived frames at all. Shared `native_relay_client` (one authenticated socket per relay+pubkey, declarative subscription reconciliation, CLOSED-driven retry with write-time eviction), lease/epoch lifecycle ownership so delayed IPC cannot resurrect a stopped task. | | `609962b49` | Move persona catalog fetching into Rust: signature verification (~473us/event, ~0.24s per 500-event page formerly on the webview thread) now runs under `spawn_blocking`; one projected DTO crosses IPC. | | `38afea0a0` | Batch unread catch-up behind one IPC call: N per-channel REQs/awaits become one command with global two-pass classification, making the completion-order race unrepresentable. Both IPC DTO surfaces pinned by wire tests asserting serde output against the TS contract. | | `b955f528b` | Move observed unread state into native SQLite: scoped WAL DB with a sequence/revision protocol, transactional localStorage migration, epoch-tagged rebuild detection. Membership no longer serializes five capped arrays per catch-up: measured 327.4 KiB before, 0.2 KiB after at the same populated 5x1000 fixture. | Full design rationale, failure matrices, and verification detail are in the individual commit messages. ### Known behavior notes - **Native migration is a one-way door per profile.** A successful native open sets `migration_complete` in the first open's transaction and the renderer then deletes the legacy localStorage key (`useObservedUnreadPersistence.ts:290-294`, `observed_unread.rs:420-442`). The one-release JS fallback remains for native open *failure*, but a profile that has completed migration cannot return to the JS store. Relevant if a rollback path is ever needed. - **The membership seed is built unconditionally at startup** (`useUnreadChannels.ts:245-250`), before any `isNative()` check. It is ref-cached and small, but it is a startup cost the baseline does not pay, including on the fallback path. ### Related issue None found. Work originated and was reviewed in the Buzz `buzz-gui-performance` channel. ### Testing **Current head is `9a8128ba4d2d695113505162be388fcec62cda0a`. For receipts at that head, see [Round-3 receipts](#round-3--final-head-9a8128ba4) at the bottom; the block immediately below is the historical record for the original five-commit pack and its counts are superseded.** The receipts in this subsection are at exact pack head `b955f528b6dfa34db089b21cc718fba0f9284d6f` (tree oid `dcc711a66`), verified by three independent instruments (implementer, reviewer, gatekeeper), with `git rev-parse HEAD` confirmed in the same shell as each run: - `cargo test --lib` (full package): **2511 passed / 0 failed** (+7 +3 in the other targets) - `pnpm test`: **4920 / 4920 across 74 suites** - `cargo fmt --check`, `clippy --all-targets -D warnings`, `tsc --noEmit`, `pnpm check` (including the file-size ratchet): all clean - Mutation controls on the final review round: badge-lane controls A and B each turn exactly one test red; seed-guard (M4) and anchor-monotonicity (M5) mutants each killed by exactly their own witness; restored bytes fully green - The observed-unread native path is exercised by an in-tree `__TAURI_INTERNALS__` protocol rig (entry, replay, gap, rebuild, markers, membership, badge lane), added after review found the original suite never left the localStorage fallback **Open gates, stated plainly (status as of head `9a8128ba4`):** - **Paired CPU benchmark still not run.** The three-arm design (baseline `78cbffeb6` vs pack vs a null arm with native forced off, fresh profile per arm) was instrument-reviewed but never executed. The IPC payload reduction above is measured; end-to-end CPU improvement is predicted, not measured. This gate is unchanged since `b955f528b`. - **Live-local gate at the final head: GREEN at `9a8128ba4`.** A real native Tauri live-local pass per `TESTING.md` was run at this exact head. Receipts: `.scratch/pr6024-final-9a8128ba4d2d695113505162be388fcec62cda0a/`, `MANIFEST.txt` `start_utc=2026-08-17T21:58:07Z`, `FINAL_ATTESTATION.txt` `end_utc=2026-08-17T22:20:47Z` — both after the commit's `21:32:51Z`, and the build worktree's HEAD is `9a8128ba4` with a clean tree. **I opened these files rather than relaying the summary**, and recomputed 6 SHA256SUMS entries against the sealed manifest (6/6 match). From the raw artifacts: historical catch-up persisted 10 seeded events into the native `observed-unread.db`; a realtime event advanced it 10→11; the relay was killed and restarted with Desktop up and an event sent after recovery advanced it 11→12 within 2 polling ticks; Desktop was then stopped, an event sent offline, and after relaunch with the appdir preserved catch-up advanced it 12→13. `relay.log` shows 2 app WebSocket connections, the restart-close signal, and fresh connections after each recovery — the app-attributable socket evidence the previous round lacked. The preserved appdir database is still on disk and `select count(*) from observed_events` returns **13**. The ignored real-relay archive wire test passed **1/1** at this head. This exercises the `lib.rs` / `e2eBridge.ts` merge recombination under a real app and blocker 2's failure-mode family (relay killed mid-session, app killed with offline traffic in flight, sync did not go dead). It does **not** directly force the precise overlapping B/C archive-ownership timing window through the GUI; that invariant is pinned by the compiled `drop(owner)` mutation proof below, and is deliberately not relabelled as live race evidence. **Retraction retained for the record:** an earlier revision of this description said live-local was GREEN at `9a8128ba4` while citing a run executed against `f079d0914`, the pre-fix head, roughly three hours before `9a8128ba4` existed. That claim was false and was corrected before this run existed. The GREEN above rests on the new receipts only. - **Workspace-wide `cargo test --workspace` is red on `main`, not on this PR.** The exact-head live run's workspace logs contain honest `rc=101` results. All are in crates this PR does not touch: `git diff origin/main...9a8128b` is **empty** for `crates/git-sign-nostr`, `crates/buzz-relay`, and `crates/buzz-pair-relay`. `git-sign-nostr::tests::test_parse_envelope_rejects_invalid_oa_pubkey` fails **deterministically on clean `main`** — reproduced independently in fresh worktrees at merge-base `a282e0643` and at current tip `7f61cf431` (55 passed / 1 failed, same assertion at `lib.rs:2136`). Root cause: `nostr` 0.36→0.44 changed `PublicKey::from_hex` from a curve-point parse to a plain hex decode, so an all-zeros (off-curve) key now parses; measured with a standalone probe, `from_hex("0"*64).is_ok()` is `false` on 0.36.0 and `true` on 0.44.7. Filed as block#6175, with the observation that nothing in CI runs this crate's tests (`just test-unit` enumerates packages and omits it; `server-cross-compile` compiles it and runs nothing). The mesh-demo and pair-relay failures in the same logs are timing flakes in equally untouched crates. **None of these gate this PR.** - **Full smoke + integration: GREEN at `9a8128ba4`.** CI run 32072147445 is `success` with every job green — all 4 Desktop Smoke E2E shards, both Desktop E2E Integration shards, Desktop Core, Desktop Build (macOS), Desktop E2E Relay, Rust Lint, Windows Rust, DCO, Dead Token Reference Guard. Attempt 1 was cancelled by an infrastructure hang, not by this code: both integration shards stalled 19m37s inside `Install Playwright system dependencies` (an apt install that runs before the e2e bundle is built or the relay starts), so no test executed and all downstream steps were skipped. The same step took 16s at `9128b9389` and 12s/18s on attempt 2 of these same bytes. Attempt 2 was a job rerun, not a push; the head is unchanged. --- Opened by Eva (agent) on Tyler's behalf at his request. --- ## Review round 2 — head `9128b9389` Carl's review [4953970089](block#6024 (review)) raised two blockers against `f079d0914`. Both were confirmed real at the source by a second reader and both are fixed in `9128b9389`. **Blocker 1 — recovery dropped the mutation whose ingest failed.** Every captured mutation now gets one retry after `reopen()` refreshes sequence/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). `snapshotRequired` takes the same recovery path instead of being treated as success. If reopen and retry both fail, native is explicitly degraded and equivalent state is applied to the JS fallback so `isNative()` stops reporting healthy. Regressions assert the *originally rejected* marker, destructive clear, and membership delta each survive; removing the retry takes 5 tests red including all three. **Blocker 2 — a superseded archive start could tear down the newer scope's relay session.** `begin` now returns an `ArchiveOwnership` token that holds both ownership guards, and `archive_session` requires one, so session acquisition happens inside the ownership critical section rather than after it. ### Deviation from the requested regression test for blocker 2 Carl asked for "a production-wiring regression that pauses B after `begin`, fully installs C, resumes B, and proves only C's session and subscriptions remain live." **We did not write that test, deliberately, and wrote a stronger one instead.** Under this fix that scenario is unreachable by construction. The fix is not a revalidation check that a test could observe passing or failing — it is a type-level fence: `begin` hands the winner a token that holds the ownership locks, and `archive_session` cannot be called without one. A test that staged "B pauses after `begin`, C fully installs" would be staging a state the type system now forbids, so it could only pass vacuously. Two things close the blocker, and only one of them is a test: 1. *A superseded start cannot reach `archive_session` at all.* Enforced by the compiler, not by a test. `ArchiveOwnership` is un-constructible outside `archive::sync`. Verified by attempting both bypasses: calling `archive_session` without a token fails **E0061**, and forging the token from a real non-archive caller fails **E0451** ("fields `_latest` and `_running` are private"), with a second independent barrier because `RunningSync` is itself a private type. 2. *While an owner holds the token, no newer start can claim.* This is the property the token's usefulness rests on, and it is what the new regression pins — `a_newer_start_cannot_claim_while_the_owner_holds_its_token`. That test is aimed at the one mutant that actually threatens this design: keeping the token but releasing the guards inside `begin`, which is what someone reaches for to avoid holding a lock across an await. It **compiles**, it keeps every other lifecycle test green, and it restores the exact race. Against it the new test goes **single-red** — the other 26 tests in the module stay green. Proving mutual exclusion over the whole claim → acquire → install unit is strictly stronger than staging a pause the type system forbids, which is why we chose it. Also recorded in the code, in `ArchiveOwnership`'s doc comment: what this token does **not** cover. It serializes archive lifecycle against archive lifecycle, not against a plain `NativeRelayClient::session()` call from a non-archive feature. That window predates this PR and is theoretical today given renderer gating, so it is documented rather than fixed here. ### Round-2 receipts at `9128b9389` - `cargo test --lib`: **2513 passed / 0 failed** - `pnpm test`: **4926 / 4926** - `cargo clippy --all-targets -D warnings`, `cargo fmt --check`, `pnpm check`: rc 0 - Merged against `origin/main` in a scratch worktree (clean, zero conflicts) and re-gated on that merged tree: **2544** Rust / **4956** frontend, both 0 failed --- ## Round 3 — final head `9a8128ba4` `9a8128ba4d2d695113505162be388fcec62cda0a` is a merge of `origin/main` (`a282e0643`) into the pack branch, taken **before** final verification so that verification would run on the bytes CI builds rather than on a head that was about to move. The merge is textually clean but touches two files the pack also touches, `desktop/src-tauri/src/lib.rs` and `desktop/src/testing/e2eBridge.ts`, so recombination was checked explicitly rather than inferred from the absence of conflicts: **all 342 pack-added lines in those files survive (0 missing), and all 17 main-added lines survive (0 missing)** — no silent revert in either direction. Main's contribution is a `#[doc(hidden)] pub use print_agent_access_owner_only_probe_if_requested` in `lib.rs`, plus a Bumble→Pollen rename and workflow revision / `workflowUpdateError` mocks in `e2eBridge.ts`. ### Receipts at `9a8128ba4` Implementer, in a shell with `git rev-parse HEAD` confirmed at this SHA: - `cargo test --lib` (full package): **2544 passed / 0 failed** / 18 ignored - `pnpm test`: **4956 / 4956** across 74 suites - `cargo clippy --all-targets -D warnings`, `cargo fmt --check`, `pnpm check`: rc 0 - The 4 remaining `pnpm check` findings (`channelMutesStorage.test.mjs`, `channelStarsStorage.test.mjs`, `terminal.css`, `empty-edit-delete.spec.ts`) are all in files this PR never touches - All 7 pre-push hooks green, including `branch-skew`, which now passes on its own because the branch contains `origin/main` Independent reviewer, same exact head, own instruments: - `cargo test --workspace`: green; `cargo clippy --workspace --all-targets -- -D warnings`: green *(a later workspace run at `9a8128ba4` hit pre-existing `main`-side failures in untouched crates — see the workspace-gate entry under Open gates above; the difference is flake timing plus which run happened to reach `git-sign-nostr`, not a change in this PR)* - `pnpm test`: **4956 / 4956**; `pnpm check`: rc 0, same known findings outside touched files - **Mutation proof of the blocker-2 fix:** dropping the ownership token's hold (`drop(owner)`) turns `a_newer_start_cannot_claim_while_the_owner_holds_its_token` red; restoring the shipped bytes returns the suite green. The invariant that a superseded start cannot claim or disturb a newer archive session is pinned by a test, not just by the type system. - **Live-local at this exact head: attested and verified.** The mis-cited `f079d0914` run that originally appeared here is retracted; a real run at `9a8128ba4` replaced it, and its receipts were opened file-by-file (not relayed) by a second agent. See the live-local entry under Open gates above for the receipt path, wall-clock bounds, store-count chain, and socket evidence. - Verdict: minimalness **9/10**, elegance **9/10**, correctness **9.5/10**. **Score restored** now that the exact-head live-local run exists and its provenance has been checked from the files (SHA-named receipt dir, self-dating manifest, receipt mtimes after the commit time, sealed digests spot-checked). Gatekeeper re-bless at `9a8128ba4`: **9/10, merge recommended.** The paired CPU benchmark remains the one gate not run. It is a measurement of the pack's *benefit*, not of its correctness, and it is stated as unrun rather than estimated. --------- Signed-off-by: Tyler Longwell <tlongwell@squareup.com> Signed-off-by: Wren <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@buzz.block.builderlab.xyz> Signed-off-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz> Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Dawn <c6237ef84fa537c78dcee78efd2d4e59f728859c7f194da42ac51ededfa0be05@buzz.block.builderlab.xyz> Co-authored-by: Wren <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@buzz.block.builderlab.xyz> Co-authored-by: Perci <5a968df9a7494b4e019b9ecf739e088ba61097b4312124e9a88ae5b42e3f5f3e@buzz.block.builderlab.xyz> Co-authored-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz> Co-authored-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
…lock#6271) ## Problem `resolve_path` (crates/buzz-dev-mcp/src/paths.rs) only ever treats a path as absolute or joins it onto the workspace root. A user-named tilde path like `~/.claude/skills/context-health-check/SKILL.md` is not absolute, so it resolves to `<workdir>/~/.claude/...` (e.g. `/app/~/.claude/...`), which never exists. The `shell` tool expands `~` via bash, so the file tools diverged from it. Surfaced in the PR block#6261 named-path benchmark: all five agents initially passed a literal `~` to `read_file`, which resolved incorrectly under `/app/~`. They recovered, but the ergonomics are wrong — agents already expect `~` to work; the resolver violated that expectation. ## Fix Expand a leading `~` (bare `~` or `~/...`) to the user home directory at the single chokepoint `resolve_path`, matching shell semantics. Home is read from `$HOME` (`%USERPROFILE%` on Windows). Both `read_file` and `str_replace` route through `resolve_path`, so both are fixed. - `~user` (another user home) is intentionally NOT handled — it needs a passwd lookup and is out of scope, consistent with the conservative posture for un-mappable MSYS forms already in this file. `~user...` falls through untouched and fails with the clear `path not accessible` error. - `expand_tilde` takes `home` as a parameter so it stays pure and unit-testable without mutating process environment; env lookup lives in a thin `home_dir()` helper. - Tool/param descriptions are intentionally left unchanged: `~` is normal shared path behavior, not a per-tool feature. Advertising it in each `resolve_path` caller's description would spend prompt tokens on an implementation detail and invite drift across callers. The tests on `resolve_path` document the behavior. ## Tests - `expand_tilde_forms`: pure coverage of non-tilde passthrough, `~user`/`~foo` passthrough, bare `~`, `~/rest`, and unset/empty home. - `resolve_path_expands_tilde_against_home`: end-to-end through the real `home_dir()` env read (creates a marker file under `$HOME`, skips cleanly if no home). - Full package suite green: `cargo test -p buzz-dev-mcp` — 98 passed, 0 failed. `cargo clippy -p buzz-dev-mcp --all-targets` clean. Closes block#6270 --- ## Follow-up (review by @wpfleger): honor `$HOME` on Windows + translate MSYS home The first cut read `%USERPROFILE%` on Windows and `$HOME` elsewhere. That diverges from the shell tool, which is the whole point of this fix: - `HOME` is passed through to the MCP child on **every** platform (`buzz-agent` `PASSTHROUGH_ENV`, not cfg-gated) and inherited verbatim by the `shell` tool (`shell.rs` spawns bash with no `env_clear`). Bash expands `~` against `HOME`. So on Windows the file tools and shell tool disagreed whenever `HOME != USERPROFILE` — e.g. a git-bash `HOME=/c/Users/x`, or an `mcpServers[].env` override setting `HOME`. - Ordering also mattered: `~` expansion runs **after** `msys_to_windows` in `resolve_path`, so a spliced-in MSYS home (`/c/Users/x`) never got translated and `canonicalize` rejected it on Windows. **Change (`paths.rs` only):** - Prefer non-empty `$HOME` on every platform; fall back to `%USERPROFILE%` only on Windows when `HOME` is unset. - On Windows, run the chosen home through `msys_to_windows` so `HOME=/c/Users/x` → `C:\Users\x`. An MSYS home with no Windows equivalent (`/home/x`) is left untranslated and fails with the clear `path not accessible` error — the intended conservative outcome. - Selection factored into a pure `select_home(home, userprofile)` so it is unit-testable without mutating process env. **Tests:** `select_home_prefers_home` (HOME-first + empty/unset fallback, all platforms) and `select_home_translates_msys_home_and_prefers_it` (Windows: MSYS translation + divergent `HOME`/`USERPROFILE`, which also fixes the prior test's silent no-op when `HOME` is unset on CI). `cargo test -p buzz-dev-mcp` — 99 passed, 0 failed; clippy clean. Pre-push `rust-tests` + `desktop-tauri-checks` green. HEAD `29e0082ff`. --------- Signed-off-by: Salman Mohammed <smohammed@squareup.com> Co-authored-by: Leo <5faf251baee50ee6bcde338aef6acdd70bb3e60115664c2cd490d94a55dfc488@buzz.block.builderlab.xyz>
…lock#6261) ## Problem Agents refused to read a specific, user-named path outside `.buzz` (e.g. `~/.claude/skills/context-health-check/SKILL.md`), and behaved inconsistently — refusing in one channel, listing the same dir in another. This is the issue Aaron and Wes hit: buzz://message?channel=e62570dd-33ad-42c5-b92b-75f2689f9694&id=401199157f8a9734109fdddfbbce4603a1ff465fae895042f29738ad52a5d15f Root cause: two prompt fragments told agents not to search `$HOME` "or other directories". The intent (added in block#1194 by Will Pfleger) was narrow — stop unscoped `$HOME` sweeps that fire macOS TCC dialogs or make a model invent its own workspace dir. But "or other directories" reads as a blanket filesystem wall, so a cautious model generalized it to "any path outside `.buzz`" and refused a targeted, named read. ## Fix Prompt-only. Reframe both fragments per context-engineering guidance — state the reason and trust judgement, rather than banning a technique: **`crates/buzz-acp/src/pool.rs` — `workspace_section()`** > …This is where you already are, so start here rather than scanning `$HOME`. Any specific path the user names is fine to read. **`crates/buzz-acp/src/base_prompt.md` line 106** > These paths are relative to your working directory — start there for your own files rather than scanning `$HOME` or `/`. When the user names a specific path, read it. Preserves the original anchor intent (start at the grounded workspace; avoid unscoped `$HOME` sweeps) while explicitly permitting a named-path read — the exact case that was broken. ## Testing `cargo test -p buzz-acp` — 816 unit + 9 integration tests pass, 0 failures. Prompt-only change; the doc comment at `pool.rs:1327-1333` already states the narrow intent and is left as-is. Signed-off-by: Salman Mohammed <smohammed@squareup.com> Co-authored-by: Leo <5faf251baee50ee6bcde338aef6acdd70bb3e60115664c2cd490d94a55dfc488@buzz.block.builderlab.xyz>
Serialize the mobile pre-push analysis and test commands into one lane, mirroring the existing `desktop-tauri-checks` pattern. The shared Flutter state under `mobile/` (`.dart_tool`, shader bundle, and `pubspec.lock`) must not be driven by parallel hook processes. The existing `mobile/**` path filter is unchanged; `mobile-check` now runs before `mobile-test` in the same lane. - Replace the parallel `mobile-check` and `mobile-test` commands with `mobile-checks`. - Keep the commands serial with `just mobile-check && just mobile-test`. Signed-off-by: Will Pfleger <pfleger.will@gmail.com> Co-authored-by: Alia <d32955ad69077062930cc46cfe2df30ca9aaf6f8e76422681265e9e9af704d78@buzz.block.builderlab.xyz>
## Summary
- normalize emoji-mart's poisoned literal `{}` recents state before
initialization
- preserve the established idle emoji-index prewarm so first picker open
stays responsive
- keep the mounted quick-reaction tray behavior unchanged from main
- cover full-picker same-session recents, prewarm ordering/callback
behavior, and the production picker-to-prewarm import boundary
## Validation
- focused prewarm tests passed 2/2 at
`98188797e219db20670b46379a240493ff8f4cbe`
- mutation check passed: changing `EmojiPicker` back to direct
`@emoji-mart/data` consumption fails the new production-boundary
assertion
- pre-push branch-skew, file-size, Desktop check, typecheck, and full
Desktop unit suite passed (5,024/5,024) at exact pushed head
`98188797e219db20670b46379a240493ff8f4cbe`
- focused full-picker lifecycle plus existing custom-emoji/tray smoke
passed 2/2 on the preceding runtime-equivalent head
- independent Royal Court scope review and headless field test passed
the full-picker journey on the preceding runtime-equivalent head
---------
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
## Summary - Replace the Link previews and Thread layout dropdowns with the shared segmented control from block#5644. - Pair each setting with a real, inert preview: production Compact/Rich link cards and a simplified Focus/Split thread diagram. - Keep scrub previews local to Settings so only a completed selection updates the saved preference and real app behavior. - Keep each setting and preview responsive as one grouped unit, with focused light/dark and narrow/wide coverage. ## Dependency - Stacked on block#5644, which provides the typography/density foundation, shared `SegmentedControl`, and responsive `SettingsOptionRow`. - After block#5644 merges, this PR should be retargeted/rebased onto `main`. ## Validation - `pnpm typecheck` - `pnpm check:px-text` - `pnpm check:file-sizes` - `pnpm exec playwright test tests/e2e/appearance-previews.spec.ts --project=smoke` (3 passed) - Focused existing Appearance coverage (2 passed) - Pre-push desktop checks, typecheck, tests, and Tauri checks Signed-off-by: morgmart <98432065+morgmart@users.noreply.github.com>
## Summary Large repositories were silently limited to the first 250 lexicographically sorted paths, which could leave the Files tab showing only dot-directories. Retain all tracked paths while limiting eager content previews, and replace the Files tab hard cutoff with incremental 200-entry pagination. ### Related issue Fixes block#4960. No duplicate PR found. ### Testing - Targeted Rust regression: `cargo test --manifest-path desktop/src-tauri/Cargo.toml parse_ls_tree_keeps_paths_after_eager_preview_limit --lib` - Pagination helper regression: `node --import ./test-loader.mjs --experimental-strip-types --test src/features/projects/lib/projectsViewHelpers.test.mjs` - Desktop Biome, type checking, and file-size checks pass - All 4,393 desktop tests pass - Repository pre-push hooks pass - `just ci` currently stops on pre-existing Clippy warnings in `crates/buzz-acp/src/queue.rs` and `crates/buzz-agent/src/hints.rs`, outside this PR diff Generated with Codex --------- Signed-off-by: Evan Chen <evanc@squareup.com> Co-authored-by: Codex <noreply@openai.com>
## Summary - introduce a `PlaybackCoordinator` as the exclusive owner of the rodio `Player` - serialize append, cancellation, synthesis-flight, and drain-release state - cancel without blocking the coordinator by replacing the player queue - preserve first-append/onset bookkeeping across cancellation - increase the existing playback lead-in from 20 ms (480 samples) to a derived 22 ms (528 samples), covering rodio 0.22.2's 512-source-sample add-time bootstrap span This is the behavior-preserving coordinator prerequisite for the follow-up floor-authorization policy. The only intentional playout difference is +2 ms silence at playback-chunk starts to prevent the measured fresh-player bootstrap chirp. ## Verification (all at this exact head, `8bfa4c0531834dce39f5ad0266f2674505e659bf`) - `cargo clippy --manifest-path desktop/src-tauri/Cargo.toml --workspace --all-targets -- -D warnings` — clean - `cargo test --manifest-path desktop/src-tauri/Cargo.toml --package buzz-desktop` — 2,596 passed / 17 ignored / 0 failed - coordinator concurrency tests: stalled cancellation, append-vs-cancel serialization, cancel election, first-append rearming, and the post-swap `starts_playback_chunk` invariant - headless known-answer sweep: 528-sample lead-in clean across 7/7 device configurations (incl. falsifier arm at 192k/96k/32k/16k/8k and 1/2/4/6 ch); current 480 dirty across 5/7 - live CoreAudio gate at production buffer shape (24 kHz mono, real `build_sentence_append_buffer` path): bootstrap chirp eliminated (660.1 Hz head vs 660 Hz control), no false drain, cancel-to-silence ~1 ms vs 12 ms baseline - independent line review + mutation testing on the shipping coordinator bytes: 4/6 mutants killed, 2 shown equivalent under rodio 0.22.2 `Player::drop` semantics ## Playout cost - +2 ms lead-in at each playback-chunk start versus main - first post-cancel utterance receives 22 ms total intentional silence (not stacked cushions) ## Provenance Authored and reviewed by Buzz agents (Wren: implementation; Dawn: line review, known-answer control, mutation testing; Max: live CoreAudio gates; Eva: coordination and final verification), with review records on the Buzz relay. This PR was briefly merged to main directly by mistake and reverted via ref reset; this is the same commit going through the front door. --------- Signed-off-by: Wren <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@buzz.block.builderlab.xyz> Signed-off-by: Dawn <c6237ef84fa537c78dcee78efd2d4e59f728859c7f194da42ac51ededfa0be05@buzz.block.builderlab.xyz> Co-authored-by: Wren <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@buzz.block.builderlab.xyz> Co-authored-by: Dawn <c6237ef84fa537c78dcee78efd2d4e59f728859c7f194da42ac51ededfa0be05@buzz.block.builderlab.xyz>
…block#6335) ## Summary Part 1 of 4 stacked PRs continuing the Projects work from block#6003. - The Projects overview now follows the selected section: the right-hand context pod stays visible across the Projects / Repositories / Reviews / Tasks / Channels tabs and shows section-specific people, stats, and contribution graphs, so it reads as live context rather than a detached summary. - Entity list rows are consolidated onto one compact line (title first, icons after, aligned dates/counts), shared across projects, repositories, PRs, issues, and channel lists via `ProjectEntityListRow`. - New `projectRelatedChannels` helper resolves the channels a project is discussed in for the overview. Follow-ups in this stack: part 2 (selectable workspaces), part 3 (context-aware collaboration), part 4 (navigation & detail-page polish). ## Test plan - [x] Desktop unit tests (`pnpm test`) — pass - [x] TypeScript (`tsc --noEmit`), Biome, clippy — clean via pre-push gate - [x] Playwright specs updated for the new overview behavior (`projects-v3-screenshots.spec.ts`, `sidebar.spec.ts`) — pass locally in the smoke project --------- Signed-off-by: Thomas Petersen <thomasp@squareup.com>
Signed-off-by: adrienlacombe <6303520+adrienlacombe@users.noreply.github.com> # Conflicts: # desktop/src-tauri/src/lib.rs # desktop/src/features/sidebar/ui/AppSidebarPinnedHeader.tsx
Upstream block#6341 moved the global-shortcut plugin construction out of `global_shortcut_plugin` and into `ptt_shortcut::install`, deleting the old function. The merge kept both — the two edits landed in different regions of the file, so git had no conflict to report — and `lib.rs` now calls only `install`, leaving the old builder unreferenced. `cargo clippy --manifest-path desktop/src-tauri/Cargo.toml --all-targets` caught it as `function \`global_shortcut_plugin\` is never used`; the file carries no fork-local content, so this restores it byte-identical to upstream/main. Signed-off-by: adrienlacombe <6303520+adrienlacombe@users.noreply.github.com>
…location upstream superseded The Markets feature (#31) has been fork-local for eleven syncs with no row in the patch table. This sync paid for that: upstream block#6003 restructured AppSidebarPinnedHeader.tsx around the fork's combined Inbox+Markets row and the conflict had to be resolved by reconstructing intent from git log. Adds three rows covering the nav surface, the prop threading, and the additive implementation paths, plus a section on what actually conflicts and why the combined row is height-stable. Also records that #31's PTT relocation is gone. It moved the global-shortcut plugin out of lib.rs into ptt_shortcut.rs to shed 92 lines under the file-size ratchet; upstream block#6024 made the same relocation into the same file as `install()`. Both landed in different regions of the file, so git kept both copies with no conflict marker, and the fork's became unreferenced — surfacing only as a tauri-clippy dead-code error that reads like an upstream defect. The relay.rs row gains this sync's ratchet data point: 996 -> 1003, condensed back to 999, which spends the last of the comment slack. Names the next move (returning `pub mod allowlist;` to lib.rs, now 936 lines) so the following overflow does not get resolved by splitting upstream's code. Signed-off-by: adrienlacombe <6303520+adrienlacombe@users.noreply.github.com>
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.
Upstream sync — 15 commits (
93114c9c6..f88cda9eb)Merged
block/buzz@f88cda9ebintomainwith a real merge commit (two parents,git rev-list --count upstream/main ^HEAD= 0).What changed upstream
Desktop
perf(desktop): move five hot renderer paths from JS into Rust(perf(desktop): move five hot renderer paths from JS into Rust block/buzz#6024)feat(desktop): refine repository-aware project workspaces(feat(desktop): refine repository-aware project workspaces block/buzz#6003)feat(desktop): make the Projects overview follow the selected section(feat(desktop): make the Projects overview follow the selected section block/buzz#6335)refactor(desktop): coordinate TTS playback(refactor(desktop): coordinate TTS playback block/buzz#6341)fix(desktop): show complete repository trees(fix(desktop): show complete repository trees block/buzz#5102)Add appearance preference previews(Add appearance preference previews block/buzz#6193)fix(desktop): restore emoji recents(fix(desktop): restore emoji recents block/buzz#6263)fix(desktop): hide archived channels from #/Tab autocomplete(fix(desktop): hide archived channels from #/Tab autocomplete block/buzz#6156)fix(desktop): morph the drawer panel icon instead of sliding it(fix(desktop): morph the drawer panel icon instead of sliding it block/buzz#6306)Mobile —
Unify mobile channel details(block#6113),chore: serialize mobile pre-push checks(block#6322)Agent surface —
fix(buzz-acp): loosen workspace-scan guardrail to allow named paths(block#6261),fix(buzz-dev-mcp): expand leading ~ in read_file/str_replace paths(block#6271),Revert "fix(acp): gate relay-signed workflow messages on their attributed author"(block#6311)Media —
fix(media): accept portrait video resolutions(block#6058)No changes under
migrations/,crates/buzz-core/src/kind.rs,crates/buzz-relay/src/handlers/ingest.rs, or.github/.Conflicts
desktop/src-tauri/src/lib.rsptt_shortcut::install(builder)over the fork's older#[cfg(not(test))] builder.plugin(global_shortcut_plugin()). The fork's only patch in this file — thedeep_link::is_supported_deep_linkargv filter — is untouched and verified present.desktop/src/features/sidebar/ui/AppSidebarPinnedHeader.tsx<SidebarProjectsSection />, renamedFolderGit2→Foldersand re-indented every line. The fork (#31) has Inbox and Markets sharing one height-stable row. Kept both: upstream's structure and indentation, with the fork's combined row re-seated where upstream's plain Inbox item was, andChartNoAxesCombinedadded alongside upstream'sFoldersimport.Two clean-merge defects (neither produced a conflict marker)
1. Duplicated PTT relocation — fixed in 9c44b68. To shed 92 lines from
lib.rsunder the file-size ratchet, the fork's #31 moved the global-shortcutplugin construction into
ptt_shortcut.rsasglobal_shortcut_plugin().Upstream block#6024 independently made the same relocation into the same file as
install(). The two landed in different regions, so git auto-merged and keptboth copies;
lib.rscalls onlyinstall(), leaving the fork's copyunreferenced. Caught by tauri clippy as
functionglobal_shortcut_pluginis never used. Verified upstream'sinstall()is a faithful superset (semanticdiff of the handler bodies is empty — only the wrapper signature, rustfmt
wrapping, and an added
cfg(test)no-op arm differ), soptt_shortcut.rsisnow byte-identical to
upstream/main.2.
relay.rsfile-size ratchet, 996 → 1003 against a hard limit of 1000.Fixed by condensing the fork's two comment blocks from 5 lines to 2 → 999, per
AGENTS.md (
do not split or reorganise upstream's relay.rs to make room). Thisspends the last of the comment slack; see the AGENTS.md row for what to do next
time.
Verification
cargo fmt --all --checkcargo fmt --manifest-path desktop/src-tauri/Cargo.toml --all --checkcargo clippy --workspace --all-targets -- -D warningscargo clippy --manifest-path desktop/src-tauri/Cargo.toml --all-targets -- -D warningscargo metadata --locked(root + tauri)just file-size-checkrelay.rsfix)scripts/test-release-ref-contract.shrelease ref contract passedscripts/test-mobile-worktree-overrides.shscripts/test-oss-desktop-promotion.shjust test-unitpnpm test(desktop)pnpm exec tsc --noEmit(desktop)pnpm check:px-text,check:pubkey-truncationdart format --set-exit-if-changed .flutter analyzeflutter testThe three contract scripts were run in a clean clone;
test-release-ref-contract.shcopies
target/(~55 GB) when run from the working checkout.CI
32 pass, 0 fail, 3 skip (
Web,CodeQL, and the push-gateway publish — allpath- or event-gated). Notably green:
Desktop Core(carries theAppSidebarPinnedHeader.tsxresolution), all fourDesktop Smoke E2Eshards,Desktop E2E IntegrationandDesktop E2E Relay,Mobile, andWindows Rust (x86_64-pc-windows-msvc)— that last one matters because thefunction deleted in 9c44b68 existed to keep the global-shortcut plugin out of
the Windows lib-test binary (
STATUS_ENTRYPOINT_NOT_FOUND); upstream'sinstall()preserves that with acfg(test)no-op arm, and this lane confirms it.Fork-local patch sites — all verified intact
relay.rs(allowlist mod + default relay),native_websocket.rs(allowlist call),deep_link.rs(DEEP_LINK_SCHEME, dual-scheme acceptance),lib.rs(argv filter),tauri.conf.json(brand, identifier, scheme),relay/allowlist.rs. Upstreamtouched the first four; markers survived and still make sense in their new
surroundings.
release.ymlwas not touched by this range.Needs a human look
deleted (feat(markets): Bitcoin difficulty betting (hidden L2, Lightning fund only) #31's PTT relocation, superseded by upstream perf(desktop): move five hot renderer paths from JS into Rust block/buzz#6024) and the AGENTS.md
patch table changed. The table edits are one rationale-column update
(
relay.rsratchet history) plus three new rows — the File/Change columnsgrew, which is the higher-severity kind. The new rows document the Bitcoin
markets feature (feat(markets): Bitcoin difficulty betting (hidden L2, Lightning fund only) #31), which had been fork-local for eleven syncs with no row
at all; that gap is what made this sync's
AppSidebarPinnedHeader.tsxconflict expensive to resolve.
AppSidebarPinnedHeader.tsxis a visual change worth eyeballing. The fork'scombined Inbox+Markets row now sits inside upstream's new fragment, above
upstream's new
<SidebarProjectsSection />. AGENTS.md records that packingMarkets as its own item previously broke
virtualization.spec.ts"06", so thatspec was run locally against this branch — 22 passed, including
06 — custom-section dnd reorder commits under content-visibility, alongsidesidebar-snapshot.spec.tsandsidebar-more-unread-overlap.spec.ts. Thelayout is therefore verified, not just type-checked; what remains is a
subjective look at where Markets now sits relative to the new Projects
section.
08eb46ef3(Revert "fix(acp): …",Revert "fix(acp): gate relay-signed workflow messages on their attributed author" block/buzz#6311). It is upstream's own commit; signing it off would mean rewriting
upstream history and destroying the merge parent, so it was left alone. This is
informational only — no DCO check runs in this fork (there is no
dcoworkflowand PR [upstream-sync] Merge block/buzz f8692fa9b..93114c9c6 (26 commits) #48 had none either); the DCO gate lives on
block/buzz. Both commitsauthored here are signed off.
Merge with a merge commit, not squash — a squash drops the second parent and
leaves the merge base stale, which is the entire point of this job.