Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
114 commits
Select commit Hold shift + click to select a range
44456e2
fix(desktop): resolve overlapping member mentions (#5225)
atishpatel Aug 10, 2026
5e4c05f
feat(desktop): NIP-AM agent-usage backend — P2 emission/transport/arc…
wpfleger96 Aug 10, 2026
563e434
Reduce repeated ACP session context (#5423)
wesbillman Aug 10, 2026
3c76f68
fix(search): surface exact short profile names (#5480)
wesbillman Aug 10, 2026
c1e20a8
fix(release): pin desktop PR operations to block/buzz (#5212)
wesbillman Aug 10, 2026
43573d1
ci(release): gate OSS desktop auto-update promotion (#5398)
wesbillman Aug 10, 2026
bb9aae1
feat(desktop): time-based sweep for stale localStorage caches (#5453)
wesbillman Aug 10, 2026
9c074bb
fix(desktop): bound nine unbounded localStorage stores (#5454)
wesbillman Aug 10, 2026
5a3b3d2
perf(ci): experiment with sccache for relay builds (#5224)
wesbillman Aug 10, 2026
2777189
fix(channels): restore member invitations to private channels (#5493)
wesbillman Aug 10, 2026
07a3c76
fix(desktop): quiesce renderer polling while hidden (#3677) (#5490)
wesbillman Aug 10, 2026
3f2f326
Polish desktop onboarding flow (#5310)
klopez4212 Aug 10, 2026
f8f2ef0
feat(cli): add --visibility flag to channels update (#5119)
cameronhotchkies Aug 10, 2026
538e5e1
chore(release): release Buzz Desktop version 0.5.9 (#5521)
wesbillman Aug 10, 2026
7e6e9c5
fix(link-preview): restore Buzz entity link cards (#5494)
tellaho Aug 11, 2026
be48ce9
fix(link-preview): reliably render previews sent right after they res…
tellaho Aug 11, 2026
5e4d0fe
fix(buzz-agent): harden Databricks OAuth token cache and callback (#5…
wpfleger96 Aug 11, 2026
7eb8cc5
fix(link-preview): resolve YouTube videos through oEmbed (#5520)
tellaho Aug 11, 2026
83ca595
fix(desktop): preserve theme when opening communities (#5266)
tellaho Aug 11, 2026
240cdd3
chore: mesh upgrade, clean up legacy special case code, simplify mode…
micspiral Aug 11, 2026
4935724
fix(desktop): suppress fresh focus-return refetches for channels and …
wesbillman Aug 11, 2026
d3ec831
fix(desktop): preserve fresh channel timelines (#5577)
wesbillman Aug 11, 2026
bba3e06
Fix macOS attachment picker lifecycle and allow inert HTML downloads …
wesbillman Aug 11, 2026
b0795a1
Add Send to channel for thread messages (#5305)
klopez4212 Aug 11, 2026
cd2aa5c
Add glass appearance and cohesive settings (#5478)
klopez4212 Aug 11, 2026
cf03bd7
Improve desktop search scoping (#5306)
klopez4212 Aug 11, 2026
397796c
feat(tracing): add PostgreSQL tracing spans (#3678)
ThePumpingLemma Aug 11, 2026
e8153f8
fix(relay): log event kind on the HTTP bridge /events line (#5291)
Chessing234 Aug 11, 2026
d9dc76c
fix(desktop): bound initial timeline retention (#5603)
wesbillman Aug 11, 2026
16b7ae7
fix(relay): stop panicking the ingest worker on reactions to project …
Chessing234 Aug 11, 2026
9203bf6
perf(desktop): coalesce read state localStorage persistence (#5591)
wesbillman Aug 11, 2026
f359301
fix(desktop): remove 0.5.9+ perf regressions, speed up get_channels (…
wpfleger96 Aug 11, 2026
4b35706
chore(release): release Buzz Desktop version 0.5.10 (#5613)
wesbillman Aug 12, 2026
1ff98fa
fix(desktop): launch Databricks OAuth from passive model discovery (#…
wpfleger96 Aug 12, 2026
6e0631f
feat(acp): deliver channel description in prompt [Context] (#4552)
wpfleger96 Aug 12, 2026
c966b86
fix(deps): bump webbrowser to 1.2.4 for RUSTSEC-2026-0257 (#5659)
wpfleger96 Aug 12, 2026
63f961c
Refine channel settings and profile panels (#5574)
klopez4212 Aug 12, 2026
63d14a0
fix(desktop): preserve live channel timelines (#5662)
wesbillman Aug 12, 2026
8a2c9af
feat(deletion): add durable whole-community deletion (#4425)
kalvinnchau Aug 12, 2026
884ed8a
fix(link-previews): proxy sent preview media (#5627)
tellaho Aug 12, 2026
a8e5c89
fix(desktop): preserve agent mention separator after send (#5623)
tellaho Aug 12, 2026
dc2dbfe
feat(buzz-acp): idle re-sleep for woken lazy pools (#5682)
wesbillman Aug 12, 2026
c3b0ccf
Batch observer-store publications per relay envelope (#5680)
wesbillman Aug 12, 2026
c6c6e7e
perf(desktop): coalesce thread-activity localStorage writes (#5693)
wpfleger96 Aug 12, 2026
59f613c
fix(desktop): defer foreground resume work (#5696)
wesbillman Aug 12, 2026
72d56e7
fix(agent): raise output limit and allow 3 recoveries (#5475)
atishpatel Aug 12, 2026
c86443c
perf(desktop): persist channel snapshot hash (#5684)
wesbillman Aug 12, 2026
7634fe7
fix(mobile): settle hydrated threads on latest reply (#4702)
loganj Aug 12, 2026
4749bc7
feat(acp): report standard adapter usage (#4950)
atishpatel Aug 12, 2026
9e0c6b4
chore(release): release Buzz Desktop version 0.5.11 (#5714)
wesbillman Aug 12, 2026
a96af89
Harden shared agent instruction review (#4220)
shellz-n-stuff Aug 13, 2026
8abc2ba
Add mobile community invites (#5641)
klopez4212 Aug 13, 2026
98d3d77
Fix mobile composer input regressions (#5594)
klopez4212 Aug 13, 2026
45f4b91
fix(desktop): more compact "compact" link previews (#5629)
tellaho Aug 13, 2026
2693e0d
Make workflow run history authoritative in Desktop (#5780)
wesbillman Aug 13, 2026
b269e8d
fix(desktop): route compact preview geometry fixture through media pr…
thomaspblock Aug 13, 2026
bcf353c
fix(desktop): enforce agent mention authorization at send boundaries …
wesbillman Aug 13, 2026
514195b
feat(desktop): add Inbox message delete action (#5779)
brow Aug 13, 2026
e094092
fix(channels): return complete member rosters (#5765)
wesbillman Aug 13, 2026
76f114a
test: add deterministic desktop release smoke (#5699)
wesbillman Aug 13, 2026
0571f54
Polish glass Huddle tray behavior (#5590)
klopez4212 Aug 13, 2026
c8da06c
Speed up initial direct messages (#5658)
klopez4212 Aug 13, 2026
068a83b
feat(huddle): cut voice-turn time-to-first-audio from ~1.0 s to ~0.35…
tlongwell-block Aug 13, 2026
eedcd88
fix(desktop): match compact link preview thumbnail corners to card sh…
morgmart Aug 14, 2026
0f61f24
Fix channel list scroll interruption (#5815)
wesbillman Aug 14, 2026
5743562
fix(huddle): stop 20 Hz speaker-level churn from re-rendering the who…
tlongwell-block Aug 14, 2026
b30f1f6
Polish mobile profiles, DMs, and sheets (#5401)
klopez4212 Aug 14, 2026
df9e773
Scope desktop presence subscriptions to active demand (#5830)
wesbillman Aug 14, 2026
ea0960f
Clarify immediate spoken huddle replies (#5863)
tlongwell-block Aug 14, 2026
8b8445f
fix(desktop): share one timer across same-interval useNow consumers (…
tlongwell-block Aug 14, 2026
43e53fc
Standardize settings section layout (#5855)
klopez4212 Aug 14, 2026
34a7f2f
Unify agent profile content (#5788)
klopez4212 Aug 14, 2026
1797781
fix(desktop): amortize observer journal eviction with a low-water mar…
wpfleger96 Aug 14, 2026
caa64b5
feat(desktop): one relative date ladder across chat and the Inbox (#3…
delkc Aug 14, 2026
1d51081
Teach agents to inherit Buzz product intent (#5875)
wesbillman Aug 14, 2026
17d2147
Fix video comment effect wrapping (#5748)
klopez4212 Aug 14, 2026
5acb930
feat(desktop-messages): render compact Buzz permalink chips (#5638)
tellaho Aug 14, 2026
fd0ab47
fix(link-preview): refetch a link when it re-enters the composer (#5510)
tellaho Aug 14, 2026
dbee291
test(desktop): await channel E2E bridge readiness (#5886)
wesbillman Aug 14, 2026
5ddf23d
feat(mobile-messages): render compact Buzz permalink chips (#5639)
tellaho Aug 14, 2026
2071547
fix(desktop): support channel message path links (#5889)
wesbillman Aug 14, 2026
01f76ec
fix(desktop): cut steady-state relay traffic from polls and read-stat…
tlongwell-block Aug 14, 2026
f086eb6
fix(link-previews): send while previews finish in background (#5697)
tellaho Aug 14, 2026
757779b
perf(desktop): update active turns incrementally (#5897)
wesbillman Aug 14, 2026
0bb7c60
fix(mobile): unwrap batched observer telemetry (#5805)
square-tomb Aug 14, 2026
1f4c69e
chore(release): release Buzz Desktop version 0.5.12 (#5903)
wesbillman Aug 14, 2026
122a8b8
Projects v3: unify sharing, discussions, and issue ownership (#5792)
thomaspblock Aug 14, 2026
263c9bf
fix(desktop): restore the agent trading-card mint button (#5900)
tlongwell-block Aug 14, 2026
0976810
fix(ci): read Playwright version without nested shell quoting (#5910)
wesbillman Aug 14, 2026
51beba6
chore(release): release Buzz Desktop version 0.5.13 (#5912)
wesbillman Aug 14, 2026
1b3dbca
ci(release): remove desktop smoke gate (#5914)
wesbillman Aug 15, 2026
82f7ed1
chore(release): release Buzz Desktop version 0.5.14 (#5917)
wesbillman Aug 15, 2026
69107dc
Polish mobile message threads and composer (#5645)
klopez4212 Aug 15, 2026
78cbffe
fix(desktop): hide the offcanvas-collapsed sidebar so it stops painti…
thomaspblock Aug 15, 2026
d8281b9
feat(mobile): require device authentication for identity export (#5116)
tellaho Aug 16, 2026
f956e6f
docs: refresh agent development guidance (#6049)
wesbillman Aug 16, 2026
1b7e5ac
feat(model-capabilities): drive model capabilities and labels from on…
wpfleger96 Aug 17, 2026
f716eef
fix(desktop): enforce shared agent access across devices (#6086)
wesbillman Aug 17, 2026
edc4a09
feat(workflows): add responsive library card actions (#6008)
tellaho Aug 17, 2026
5b3f037
fix(acp): replace Goose native system prompt (#5964)
atishpatel Aug 17, 2026
54f1121
fix(acp): gate relay-signed workflow messages on their attributed aut…
TheSentinel454 Aug 17, 2026
d12d825
fix(desktop): resolve agent profiles through one archive-aware select…
wpfleger96 Aug 17, 2026
076081b
Rename Bumble agent to Pollen (#5864)
klopez4212 Aug 17, 2026
85bacea
Remove GitHub security advisory commitment (#6144)
jmecom Aug 17, 2026
a282e06
fix(cli): keep project replacement timestamps at or after wall clock …
Illuminfti Aug 17, 2026
57feca2
fix(desktop): repair dropped team membership links at boot and on edi…
wpfleger96 Aug 17, 2026
439c037
fix(desktop): align preview sidebar row styling (#6163)
wesbillman Aug 17, 2026
f64899e
Remove Startup Recovery section in base prompt (#6161)
salman1993 Aug 17, 2026
f7a01bd
fix(workflows): preserve multi-channel listing semantics (#6009)
tellaho Aug 17, 2026
7f61cf4
Preserve managed agent mentions during relay errors (#6167)
wesbillman Aug 17, 2026
c8c8eb5
chore(release): release Buzz Desktop version 0.5.15 (#6173)
wesbillman Aug 17, 2026
f8692fa
test(desktop): cover exact workflow batch limit (#6168)
wesbillman Aug 17, 2026
523fb9a
chore: sync launchpad with upstream block/buzz main
serina-mcfall Aug 18, 2026
43366af
fix(desktop): keep managed_agents/runtime.rs under the file-size ratchet
serina-mcfall Aug 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
24 changes: 23 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,14 @@ jobs:
- 'deny.toml'
- '.github/workflows/ci.yml'
- 'scripts/run-tests.sh'
- 'scripts/model-capabilities.json'
- 'scripts/normative-corpus.json'
- 'justfile'
desktop:
- 'scripts/check-file-sizes-core.mjs'
- 'scripts/check-file-sizes-core.test.mjs'
- 'scripts/model-capabilities.json'
- 'scripts/normative-corpus.json'
- 'desktop/**'
- 'pnpm-lock.yaml'
desktop-rust:
Expand Down Expand Up @@ -77,6 +81,10 @@ jobs:
run: scripts/test-release-ref-contract.sh
- name: Desktop release candidate contract
run: scripts/test-desktop-release-candidate.sh
- name: OSS desktop promotion contract
run: |
scripts/test-oss-desktop-promotion.sh
scripts/test-oss-desktop-promotion-behavior.sh
- name: Mobile release contract
run: |
scripts/test-mobile-release-contract.sh
Expand Down Expand Up @@ -318,6 +326,9 @@ jobs:
if: github.event_name == 'push' || needs.changes.outputs.desktop == 'true' || needs.changes.outputs.desktop-rust == 'true' || needs.changes.outputs.rust == 'true'
permissions:
contents: read
env:
SCCACHE_GHA_ENABLED: "true"
SCCACHE_GHA_RW_MODE: ${{ (github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.number == 5224)) && 'READ_WRITE' || 'READ_ONLY' }}
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: cashapp/activate-hermit@cea9af7913204a965fd488637a8d1811bba2e616 # v1
Expand All @@ -342,13 +353,22 @@ jobs:
.
desktop/src-tauri
save-if: ${{ github.event_name != 'pull_request' }}
# Cache rustc outputs for unchanged workspace crates. Trusted pushes write;
# the bounded PR 5224 trial writes only to its isolated merge-ref scope.
- name: Set up sccache
if: steps.relay-artifacts-cache.outputs.cache-hit != 'true'
uses: Mozilla-Actions/sccache-action@fc920bf0ec8de6ee65d409111f7ec508035751ba # v0.0.11 # zizmor: ignore[cache-poisoning] Bounded trial: only PR 5224 writes to its isolated merge-ref scope; trusted pushes retain production writes.
with:
version: v0.16.0
- name: Install cargo-nextest
if: steps.relay-artifacts-cache.outputs.cache-hit != 'true'
uses: taiki-e/install-action@0fd46367812ee04360509b4169d9f659d6892bb2 # v2.79.15
with:
tool: cargo-nextest@0.9.136
- name: Build relay artifacts
if: steps.relay-artifacts-cache.outputs.cache-hit != 'true'
env:
RUSTC_WRAPPER: sccache
run: |
cargo build --profile ci -p buzz-relay -p git-credential-nostr
cargo nextest archive \
Expand All @@ -360,7 +380,9 @@ jobs:
--test e2e_event_reminder \
--archive-file target/ci/backend-integration-tests.tar.zst
- name: Save relay artifacts cache
if: steps.relay-artifacts-cache.outputs.cache-hit != 'true'
# PR-scoped exact-source entries cannot warm main or other PRs and churn
# the shared cache pool. sccache provides read-only PR reuse instead.
if: steps.relay-artifacts-cache.outputs.cache-hit != 'true' && github.event_name == 'push'
uses: actions/cache/save@caa296126883cff596d87d8935842f9db880ef25 # v5
with:
path: |
Expand Down
45 changes: 45 additions & 0 deletions .github/workflows/promote-oss-desktop-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Promote OSS Desktop Auto-Update
run-name: Promote desktop-v${{ inputs.version }} to auto-update

on:
workflow_dispatch:
inputs:
version:
description: Stable desktop version to promote (X.Y.Z)
required: true
type: string

concurrency:
group: oss-desktop-auto-update-promotion
cancel-in-progress: false

permissions:
contents: read

jobs:
promote:
if: github.repository == 'block/buzz'
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: write
steps:
- name: Require the reviewed workflow from main
env:
DISPATCH_REF: ${{ github.ref }}
run: |
if [ "$DISPATCH_REF" != "refs/heads/main" ]; then
echo "::error::OSS desktop promotion must be dispatched from main, not $DISPATCH_REF"
exit 1
fi

- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
ref: ${{ github.sha }}
persist-credentials: false

- name: Validate and promote exact release manifest
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ inputs.version }}
run: scripts/promote-oss-desktop-release.sh "$VERSION"
5 changes: 1 addition & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -907,6 +907,7 @@ jobs:
[ "${#TRIPLES[@]}" -ge 3 ] || { echo "::error::too few platforms (${#TRIPLES[@]})"; exit 1; }
bash desktop/scripts/generate-oss-latest-json.sh "$VERSION" "${TRIPLES[@]}" > latest.json
cat latest.json
cp latest.json staged/updater-manifest.json

- name: Create or verify versioned draft
run: |
Expand Down Expand Up @@ -946,7 +947,3 @@ jobs:
- name: Publish complete versioned release
if: env.already_published != 'true'
run: gh release edit "desktop-v${VERSION}" --draft=false

- name: Upload latest.json to rolling release last
if: ${{ !contains(needs.setup.outputs.version, '-') }}
run: gh release upload buzz-desktop-latest latest.json --clobber
14 changes: 7 additions & 7 deletions .release/desktop-candidate.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"schema": 2,
"version": "0.5.8",
"base_sha": "6a17d035f79ad582ca3f4f3cdc38d376f2c4087f",
"previous_tag": "desktop-v0.5.7",
"previous_base_sha": "74b913cff8512c015dc6f1a7473b253fa803f954",
"previous_merge_sha": "13c9e900c84cac1e2c8eeb7551bd1510ecb544d3",
"tag": "desktop-v0.5.8",
"commit_count": 4
"version": "0.5.15",
"base_sha": "7f61cf431af1d8f0480a0baf525881a12f2be7f2",
"previous_tag": "desktop-v0.5.14",
"previous_base_sha": "1b3dbcaaea882eeea90359c1db02e306d2f4f50a",
"previous_merge_sha": "82f7ed1532f50e0d28afca5580ed522f1c2ef1ca",
"tag": "desktop-v0.5.15",
"commit_count": 18
}
88 changes: 56 additions & 32 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,25 @@ code style, PR process, architecture), see [CONTRIBUTING.md](CONTRIBUTING.md).

---

## Product Contract

Before planning or reviewing a non-trivial change:

1. Read [VISION.md](VISION.md).
2. Read the `VISION_*.md` documents relevant to the affected product surface.
3. Read the applicable guidance in [TESTING.md](TESTING.md) and any
package-local `TESTING.md`.
4. Check that the proposed design advances, or at least does not contradict,
that product intent. Call out any intentional tension explicitly.

Implementation describes the product today; the vision documents describe the
product it is becoming. A locally correct change can still be wrong if it works
against that direction. Scale validation to the change's risk and exercise the
real workflow for user-visible or integration behavior when practical; green CI
and runtime evidence answer different questions.

---

## Ecosystem

Buzz spans five repos. This one (`block/buzz`) is the OSS source for the relay, desktop, mobile, and CLI. The others handle internal builds and deployment:
Expand Down Expand Up @@ -90,8 +109,9 @@ See CONTRIBUTING.md for full setup details and dependency requirements.

## Quality Gates

Run `just ci` before every PR — it runs `fmt` + `clippy` + desktop lint +
unit tests + builds. Clippy passing does not mean fmt passes; run both.
Run `just ci` before every PR — it runs repository-wide formatting, lint,
and static checks; Rust, Tauri, desktop, and mobile tests; and desktop and web
builds. Clippy passing does not mean fmt passes; run both.

Run `just test` for integration tests if you touched `buzz-relay`,
`buzz-db`, or `buzz-auth` — these require a running Postgres and Redis.
Expand Down Expand Up @@ -185,7 +205,7 @@ or invoke with the full path.
thread. To read the linked thread:

```bash
buzz messages thread --channel <uuid> --event <hex> --format compact
buzz --format compact messages thread --channel <uuid> --event <hex>
```

Extract `channel` and `id` from the URL query parameters. The optional
Expand Down Expand Up @@ -216,7 +236,9 @@ E2E tests live in `crates/buzz-test-client/tests/`:
- `e2e_media_extended.rs` — extended media scenarios
- `e2e_nostr_interop.rs` — Nostr interop (NIP-50 search, NIP-10 threads, NIP-17 gift wraps)

Desktop E2E: `cd desktop && pnpm exec playwright test`
Desktop E2E: `cd desktop && pnpm test:e2e:smoke` for mock-bridge smoke
coverage, or `pnpm test:e2e:integration` for relay-backed coverage. These
scripts build the required E2E bridge before running Playwright.

See [TESTING.md](TESTING.md) for the full multi-agent E2E guide.

Expand Down Expand Up @@ -427,11 +449,10 @@ description. See [PR #803](https://github.com/block/buzz/pull/803).

1. **Kind `39000` for channel metadata, not `41`** — kind 41 is NIP-01 (unused). All kinds defined in `buzz-core/src/kind.rs`.
2. **Relay queries must specify `kinds`** — omitting `kinds` triggers the p-gate (403). Always include explicit kind filters.
3. **`messages search` must include `--kinds`** — an open-ended search (no kinds) hits the relay p-gate and returns 403. Pass at least `--kinds 9,45001,45003` to scope the query.
3. **`messages search` chooses its own supported kinds** — do not add a `--kinds` option; the current command does not accept one. This differs from raw relay filters, which still need explicit kinds.
4. **Worktrees: `cd` in the same command** — shell CWD doesn't persist between tool calls. Use `cd /path && cargo build` as one command.
5. **Desktop crate excluded from root workspace** — `cargo test` at repo root does NOT run desktop tests. Use `cargo test --manifest-path desktop/src-tauri/Cargo.toml` explicitly.
6. **Desktop Tauri fmt fails in worktrees and blocks commits** — the pre-commit hook runs `just desktop-tauri-fmt`, which fails in git worktrees because `cargo fmt` resolves workspace paths relative to the worktree root. Run `just desktop-tauri-fmt` from the main checkout to apply the fix, then re-stage and commit. CI is unaffected.
7. **React render perf: `React.memo` is all-or-nothing** — it only skips a re-render when *every* prop is reference-stable; one unstable prop (inline arrow/JSX, or a hook returning a fresh `{}`/`[]`/`Map` each render) defeats it. Two repeat offenders: (a) React Query results (`useMutation`/`useQuery`) are a **new object each render** — depend on the stable method (`mutation.mutateAsync`), not the object; (b) derived `Map`/array state that recomputes on a version bump — wrap in a content-equality ref cache (`shared/hooks/useStableReference.ts`). When chasing interaction lag, **measure with DevTools closed and no perf probes** (an open Web Inspector + per-keystroke `console.log` inflate the numbers), and isolate by removing one suspect at a time rather than guessing.
6. **React render perf: `React.memo` is all-or-nothing** — it only skips a re-render when *every* prop is reference-stable; one unstable prop (inline arrow/JSX, or a hook returning a fresh `{}`/`[]`/`Map` each render) defeats it. Two repeat offenders: (a) React Query results (`useMutation`/`useQuery`) are a **new object each render** — depend on the stable method (`mutation.mutateAsync`), not the object; (b) derived `Map`/array state that recomputes on a version bump — wrap in a content-equality ref cache (`shared/hooks/useStableReference.ts`). When chasing interaction lag, **measure with DevTools closed and no perf probes** (an open Web Inspector + per-keystroke `console.log` inflate the numbers), and isolate by removing one suspect at a time rather than guessing.

---

Expand Down Expand Up @@ -492,27 +513,12 @@ class instances, cached promises) survive across remounts. Every community-scope
singleton needs a reset function wired into `resetCommunityState()` in
`desktop/src/features/communities/useCommunityInit.ts`.

Current singletons that are reset on relay boundary changes (same-relay
reconnects preserve pending avatar verification work):
- `relayClient.disconnect()` — WebSocket teardown + promise rejection
- `resetRateLimitGate()` — clears any active rate-limit window from the old relay
- `clearAllDrafts()` — message draft cache
- `resetAgentObserverStore()` — agent observer relay store
- `resetActiveAgentTurnsStore()` — active agent turn timers
- `resetAgentWorkingSignal()` — agent working indicator signal
- `resetAvatarProfileSync()` — pending verified-avatar profile writes
- `resetAvatarPresentations()` — avatar probes, previews, and Retry toasts
- `resetSidebarRelayConnectionCardState()` — sidebar relay card dismiss state
- `resetMediaCaches()` — proxy port and relay origin caches
- `resetVideoPlayerState()` — video player singleton
- `resetRenderScopedReactionHydration()` — reaction hydration cache
- `clearSearchHitEventCache()` — search result event cache
- `clearMarkdownNodeCache()` — markdown parse-node cache
- `resetLinkPreviewTitleCache()` — link preview title cache (Buzz entity titles come from relay events)

**If you add a new module-level cache, Map, or class instance that holds
community-scoped data, you must add its reset to `resetCommunityState()`.**
Failure to do so causes data from the old community to leak into the new one.
`resetCommunityState()` is the canonical inventory of community-scoped
singletons. **If you add a new module-level cache, Map, or class instance that
holds community-scoped data, add its reset there in the same change.** Failure
to do so causes data from the old community to leak into the new one. Avoid
duplicating its complete reset list here; the implementation is the source of
truth.

Key files:
- `desktop/src/app/App.tsx` — community key, init gate, remount boundary
Expand All @@ -537,9 +543,23 @@ The mobile app lives in `mobile/` — a Flutter app using Riverpod + Hooks.

- **NEVER use `StatefulWidget`** — favor Riverpod for state and always use
`HookConsumerWidget` or `ConsumerWidget` with `flutter_hooks` for local state.
- **NEVER run `flutter run`, `flutter build`, `flutter clean`, or
`flutter upgrade`** — only `flutter test`, `flutter analyze`, and
`dart format` are safe for agents to run.
- Agents may build and run the Flutter app when it materially helps implement,
debug, or validate mobile changes. Prefer the smallest relevant command and
reuse an already-running simulator/emulator and the app's configured staging
or production community when that is sufficient. Do not start or rebuild
local relay services unless the task specifically requires relay-side or
isolated integration behavior.
- For iOS runtime validation, prefer `just mobile-dev`; it applies the
worktree-specific debug identity and runs `flutter run`. Direct `flutter run`
or IDE workflows are also allowed. Use `just mobile-build-android` only when
an APK build is relevant to the task.
- Do not rebuild, reinstall, or relaunch merely for ceremony. Preserve Flutter's
incremental build cache and use hot reload/restart where appropriate. Use
`flutter clean` only when stale build artifacts are a credible cause. Run
`flutter upgrade` only when the task explicitly requires a toolchain change.
- For user-visible or integration changes, exercise the affected workflow in a
real app when practical and report the device/simulator, connected community,
and workflow actually tested.
- **Do NOT use `print()`** — use `debugPrint()` or structured logging.
- Prefer `context.colors` and `context.textTheme` (via theme extensions)
over raw `Theme.of(context)` calls.
Expand All @@ -565,12 +585,16 @@ flutter test

Or from repo root: `just mobile-fmt` (auto-fix), `just mobile-check` (lint + fmt check), `just mobile-test` (tests).

To run the app locally (starts Docker, relay, iOS simulator automatically):
To run the app locally with a worktree-specific debug identity and a
started or reused iOS Simulator:

```bash
just mobile-dev
```

This runs `flutter run` against the app's configured community; it does not
start Docker or local relay services.

When run from a git worktree, `just mobile-dev` (and `just
mobile-build-android`) give the debug build a per-worktree app identifier
(keyed to the worktree directory name) and a branch-labelled app name via
Expand Down
Loading
Loading