镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

fix(plugins): default reminders and workflows off for fresh installs - #2291

Merged
tellaho merged 9 commits into
mainfrom
tho/optional-workflow-reminder-defaults
Nov 4, 2026
Merged

tellaho merged 9 commits into
mainfrom
tho/optional-workflow-reminder-defaults

Conversation

@tellaho

@tellaho tellaho commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Category: improvement
User Impact: Fresh installs start with Reminders and Workflows off. Existing installs keep both features available, including when their settings were never changed.

Problem: Changing only the bundled defaults would silently disable these features for existing profiles without overrides. That stops local reminder notifications and removes the controls for workflows that can still run on the relay.

Solution: Change the browser and native defaults to Off, then save each known bundled plugin's resolved state. Existing profiles without a Reminders or Workflows flag retain their former On state. Saved On/Off choices always win; a deliberate reset uses current defaults. If an automatic native snapshot cannot be saved, startup uses the resolved values and later catalog reads retry. Explicit changes and reset still report write failures. Browser reset backs up the original settings and atomically replaces their key, preserving the original if the replacement fails.

The native migration checks whether the plugin-profile directory existed before acquiring the registry lock. Browser storage checks for prior plugin settings or client records before client initialization. New devices or cleared local profiles count as fresh even if the account has older relay data. No relay usage scan, registry schema change, or activation/UI redesign is involved.

The accepted plugin-defaults decision makes future default-off changes apply only to fresh installs. Both storage owners now retain known states across subsequent releases; the decision also requires legacy backfills for users who skip releases that would have saved those states.

File changes
  • src/bundled/index.ts and crates/plugin-manager/src/lib.rs: new defaults, native profile detection, initialization under the existing lock, and explicit reset behavior.
  • src/plugins/storage.ts: equivalent browser initialization, saved-choice precedence, and recovery behavior.
  • Native management tests, frontend storage tests, and app composition tests: cold launch/reopen, untouched upgrade, partial and explicit choices, future default changes, storage failure, and recovery.
  • Browser fixture and feature journeys: explicit opt-ins where optional features are required; model fresh plugin choices before seeding community records.
  • tests/browser/plugin-defaults.spec.mjs: real app startup without fixture storage, plus migrated activation, working Workflows navigation, deliberate disable, and reload.
  • AGENTS.md, docs/plugin-defaults.md, docs/plugin-architecture.md, and docs/buzz-help.md: the durable policy and user-facing behavior.

Reproduction steps

  1. Open a fresh disposable profile. Reminders and Workflows should offer Enable under Settings → Plugins → Manage plugins, including after another launch.
  2. Upgrade an existing profile that previously opened Buzz but never saved plugin choices. Both should remain on, and the Workflows page should remain usable.
  3. Repeat with saved On and Off choices. Those choices should remain effective.
  4. Enable or disable either plugin through Settings and reload. The choice should persist.
  5. After deliberately recovering/resetting plugin settings, both should be off and remain off after reopening.

Validation

Current head eda7b3f03 fixes native automatic snapshot failures in 46756c962 and browser reset replacement failures in eda7b3f03.

  • New regressions failed on the previous implementation: the native catalog returned a snapshot write error, and both browser reset cases lost their original key. With the fixes, all 104 native package tests and 130 frontend plugin-owner/app-composition tests passed.
  • At clean eda7b3f03, the complete plugin-defaults.spec.mjs and launch-home.spec.mjs passed 22/22 cases in Chromium and WebKit, including the recovery/reset UI (pnpm test:browser tests/browser/plugin-defaults.spec.mjs tests/browser/launch-home.spec.mjs --project=chromium --project=webkit --no-deps). Two workers, zero retries. No browser cases or fixtures changed in this follow-up.
  • Commit and pre-push checks passed. Native first-launch snapshot failure can still leave a directory that a later process classifies as an existing profile; the decision document records this limitation. Restart stability requires a successful snapshot save.

The earlier merge head ff8e6c9ed brings in main 517443522 without rewriting the published branch. The merge applied without conflicts and includes the mainline history geometry / Virtua fix.

  • The complete plugin-defaults.spec.mjs and history-loading.spec.mjs passed 48/48 cases in Chromium and WebKit at the clean merge head, in 2.1 minutes (pnpm test:browser tests/browser/plugin-defaults.spec.mjs tests/browser/history-loading.spec.mjs --project=chromium --project=webkit --no-deps). Two workers, zero retries; unrelated measurement projects were excluded.
  • Blob comparisons confirm the native manager, browser plugin storage, frontend default declarations, and decision document are identical to e6f8f4a07. The history spec matches main exactly except for the explicit Workflows fixture opt-in; main's assertions remain intact.
  • Mandatory pre-push checks passed: TypeScript and related unit tests, design-system checks, workspace Clippy and publication checks. The PR remains ready for review; native UI / human migration acceptance remains pending.

At clean commit 31d97764c:

  • pnpm exec vitest run src/plugins src/app/pages.integration.test.mjs: 128 passed, 11 complete files.
  • cargo test -p buzzodz-plugins --locked: 103 passed across the complete package suite.
  • pnpm test:browser tests/browser/plugin-defaults.spec.mjs tests/browser/notification-settings.spec.mjs tests/browser/settings.spec.mjs --project=chromium --project=webkit --no-deps: 38 passed in 1.3 minutes. Unrelated measurement projects were excluded.
  • The new frontend regression suite produced six failures against the previous browser storage implementation at 73a0bd246, then passed with this migration. The comparison used a temporary Vite transform without editing production working-tree files.
  • Mandatory commit and pre-push checks passed: formatting, TypeScript and related unit tests, design checks, workspace Clippy, and publication checks. A merge simulation against current origin/main completed without conflicts.

Two browser journeys were added (four cases across the engines), with none removed. They exercise app startup ordering and plugin activation/Settings integration; the state matrix remains in storage tests. Fixture datasets and workers are unchanged. A comparative setup-cost benchmark was not run; no performance claim is made.

The earlier broader run at 15c902232 passed 337/340 cases across 19 complete specs. Its three failures reproduced on unchanged upstream 134248ba7: macOS Alt+ArrowUp scrolling in both engines and sidebar keyboard focus in WebKit. That broader set has not been rerun locally for this migration; current hosted CI supplies the broad check.

Native UI walkthrough and human acceptance of this migration remain pending.

Review follow-up at e6f8f4a07

  • Extended the existing native/desktop parity test to guard the legacy-On migration set. No production declarations changed.
  • Added an isolated browser page with no fixture init scripts, seeded only with a client record. It checks both plugins stay On across reopening. This adds one journey (two engine cases); none were removed.
  • All 103 native package tests and all 10 cases in the complete plugin-defaults browser spec passed at the clean follow-up commit. Mandatory pre-push checks passed.
  • Investigated the advisory CI drag-loop failure. On clean pre-fix main b293002a0, using its frozen dependencies and no changes from this PR, the same assertion failed twice in 10 Chromium repetitions: 4 drag steps versus at least 6. Its 10 WebKit repetitions passed locally. The assertion counts drag steps, not message rows.
  • Current main 3fabf1be4 passed 20/20 repetitions across both engines. It already contains the shorter viewport / available-distance adjustment from f557d0a5, along with a newer Virtua patch. The comparison does not isolate those two mainline adjustments. This establishes that the failure exists independently of this PR; the unrelated scrolling test remains unchanged here.

Comparison command: pnpm test:browser tests/browser/history-loading.spec.mjs --project=chromium --project=webkit --no-deps --grep 'a held pointer scrolls across the page without being pulled back' --repeat-each=10. Local headless macOS runs used two workers and zero retries. Baseline traces were retained. CI originally reported 3 steps in Chromium and 5 in WebKit.

Screenshots

Fresh-profile controls are visually unchanged by the migration. These captures are from the earlier built-app walkthrough with disposable data; the migration is covered by the current tests above.

Plugin Fresh profile
Reminders Reminders is off and offers Enable
Workflows Workflows is off and offers Enable

tellaho and others added 3 commits November 3, 2026 10:09
Preserve saved plugin choices while keeping the two optional features off for profiles without overrides.

Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@feedback.communities.buzz.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Keep feature navigation and layout journeys independent of bundled defaults while checking fresh profiles offer Enable for Reminders and Workflows.

Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@feedback.communities.buzz.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Opt into the optional Reminders notification category so the existing eight-switch geometry check keeps its full coverage.

Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@feedback.communities.buzz.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
@tellaho

tellaho commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

🤖 Carl: Enabled buzz.reminders explicitly in the notification-settings fixture so its existing eight-switch layout assertion retains full coverage. The production diff remains four lines.

At 73a0bd24606a931d08a9bb0226cd009f1893c51f, the complete spec passed in Chromium and WebKit (2/2): pnpm exec playwright test --config tests/browser/playwright.config.mjs --project chromium --project webkit --no-deps tests/browser/notification-settings.spec.mjs. Mandatory pre-push checks passed. Full CI for the new head remains pending.

@tellaho
tellaho marked this pull request as ready for review November 3, 2026 19:36
@tellaho
tellaho requested a review from a team as a code owner November 3, 2026 19:36

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Carl, an automated reviewer, commenting via Wes's GitHub account.

Verdict: one recommended blocker, which is a product decision on the upgrade path. The default flip itself is correct and consistent across the browser and native catalogs. Saved On/Off choices survive on both backends, and the test changes keep their real coverage.

What was checked at 73a0bd2: browser and native persistence (a focused storage probe covered the snapshot upgrade, explicit Off on reopen, and a missing flag), other default catalogs and indirect dependants (none found), fixture ordering and retained journey assertions, and the user-facing behavior traced from source. Hosted CI is green, with Windows native skipped. Native UI wasn't exercised.

One thing the PR body should say: browser changePlugin saves the whole resolved map (src/plugins/storage.ts, in changePlugin). So a browser profile that ever toggled any plugin keeps Reminders and Workflows on after upgrading, and only untouched profiles lose them. Native saves only the targeted override. This behavior predates the PR and is fine. It does mean "profiles without a saved override" covers a different set of people on each backend.

Optional follow-up: a deep link, Back entry or reminder notification that targets a disabled Reminders or Workflows page reaches failure = "unavailable" (src/app/navigation.ts:151). It then shows "It may have been removed, or you may need to update Buzz" (src/app/App.tsx:497). That advice is wrong for a plugin that is only turned off. This already happens with Bestie and Todos, but this PR puts it in front of every upgrader. Saying " is turned off" with a Manage plugins action would fix it, and a separate PR is fine.

To merge: resolve the inline thread, either by keeping existing users' plugins on or by explicitly accepting the upgrade behavior and documenting it.

Comment thread src/bundled/index.ts Resolved
@tellaho
tellaho marked this pull request as draft November 3, 2026 22:34
Persist resolved bundled flags before activation. Backfill the former Reminders and Workflows defaults for established profiles, preserve saved choices, and use current defaults after an explicit reset. Record the fresh-install policy for future default changes.

Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@feedback.communities.buzz.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
@tellaho tellaho changed the title fix(plugins): disable reminders and workflows by default Default Reminders and Workflows off for fresh installs Nov 3, 2026
@tellaho
tellaho marked this pull request as ready for review November 3, 2026 22:42
@tellaho tellaho changed the title Default Reminders and Workflows off for fresh installs fix(plugins): default reminders and workflows off for fresh installs Nov 3, 2026

@kalvinnchau kalvinnchau left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Two maintainability and regression-coverage improvements below. No current migration defect was demonstrated; the overall CI run still has unresolved scrolling failures.

Comment thread crates/plugin-manager/src/lib.rs Resolved
Comment thread tests/browser/plugin-defaults.spec.mjs Resolved
tellaho and others added 3 commits November 3, 2026 15:20
Extend the existing native/desktop catalog parity check to compare the browser legacy-On condition with native upgrade resolution, so a future one-sided default migration fails the existing guard.

Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@feedback.communities.buzz.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Exercise startup in an isolated page without fixture init scripts. Seed only the existing client record, assert both plugins are enabled, and verify their saved On states survive reopening.

Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@feedback.communities.buzz.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Merge origin/main at 5174435 without rewriting the published branch. Preserve the plugin defaults and migration while bringing in the mainline history geometry and Virtua fixes.

Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@feedback.communities.buzz.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Carl, an automated reviewer, commenting via Wes's GitHub account.

Verdict: no blockers. The legacy-On migration resolves my earlier upgrade-path blocker. Untouched upgraders keep Reminders and Workflows on, fresh installs start with them off, and saved choices still win on both backends.

This was a split review: native, browser, and policy/docs each had an independent reviewer, and I integrated the results. Checked at ff8e6c9:

  • Native: all seven read() callers hold registry.lock. Only Manager::lock creates profiles/<p>, and desktop opens the Manager after sign_out::boot.
  • Browser: the catalog is pinned before client storage is created. The v1, v2 and v3 shapes, explicit choices and a second viewer behave correctly.
  • Compatibility: older builds read the full bundledOverrides map without trouble.
  • Docs and fixtures: they match the normal-path behavior, and the fixture edits don't weaken any existing assertion.

Two small checks were run on the failure paths. A disposable scratch test covered native, and a probe of the real storage module covered the browser. They reproduced the two inline findings. Hosted CI is green, with Windows native skipped. Native UI and human migration acceptance are still pending, as the PR body says.

Pinning every bundled default is broader than flipping two flags. It also means a future Off→On default won't reach established profiles. The decision doc says this explicitly, so I'm treating it as accepted policy, not a finding.

Optional, before merge if cheap: the two inline threads. Both are write-failure paths where the new migration breaks the documented contract.

Comment thread crates/plugin-manager/src/lib.rs Resolved
Comment thread src/plugins/storage.ts Resolved
tellaho and others added 2 commits November 4, 2026 00:08
Treat automatic default snapshots as best-effort writes. Keep resolved settings usable and retry persistence on later catalog reads; retain errors for explicit edits and the existing registry-version migration. Cover read-only profiles and document the fresh-profile write-failure limitation.

Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@feedback.communities.buzz.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Keep the original settings key until a single replacement write succeeds. Verify quota failures preserve corrupt settings and saved Off choices, and that retrying reset persists the current defaults.

Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@feedback.communities.buzz.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Star Lord’s automated source review via Wes’s account, with independent Rocket, Mantis and Groot coverage.

No new actionable findings. The two write-failure observations from the previous review are addressed: native default-snapshot persistence is best effort while explicit edits/reset and the existing version migration still propagate write errors; browser reset replaces the settings key atomically, preserving saved or corrupt contents if replacement fails. The added regression cases cover preservation and a later successful retry.

Reviewed head eda7b3f0350da6b480cd3b97d1d032c0a251331f, base 517443522133b5c0dc6c29d9b0216ed2636af83b, with follow-up comparison against ff8e6c9ed1b24d560350c8d5eb66bb09a8e7b568. The documented native fresh-profile classification limitation after a failed first snapshot remains; restart stability requires a successful save. Existing recovery-screen presentation is unchanged.

Source-only review: no tests, builds or app execution performed. Public description, commit messages and both attached screenshots inspected. A single hosted-check snapshot showed 71 successful checks and Windows native validation skipped. Native UI, live storage-failure behavior, keyboard/screen-reader recovery, performance and human migration acceptance remain unverified by this review. This is a COMMENT review, not approval or merge authorization.

@tellaho
tellaho merged commit 83b72a3 into main Nov 4, 2026
72 checks passed
@tellaho
tellaho deleted the tho/optional-workflow-reminder-defaults branch November 4, 2026 15:31
gilgtm added a commit that referenced this pull request Nov 4, 2026
* origin/main: (52 commits)
  feat(agents): give plugin agent types the Buzz side of a turn (#2364)
  feat(plugins): pin buzz://plugin-install links to a path and commit (#2315)
  feat(plugins): tint currentColor SVG page icons like host icons (#2314)
  feat(notifications): add a soft notification sound (#1536)
  feat(agents): let agents propose a profile picture (#2267)
  fix(plugins): default reminders and workflows off for fresh installs (#2291)
  Show all reactors in compact, separate emoji capsules (#2179)
  fix(panels): remember page split widths per workspace (#2264)
  feat(search): browse open channels from a Channels tab in search (#2164)
  perf(relay): page combined replay filters after a reconnect (#2308)
  fix(composer): make native Mac text shortcuts work past link chips (#2390)
  perf(relay): read creator proofs for many channels per filter (#2312)
  fix(channels): let published leave and delete confirm through access loss (#2357)
  fix(media): save native context menu media downloads and hide loopback links on macOS (#2131)
  fix(links): say why a message preview is unavailable, and preview unjoined public channels (#2136)
  test(browser): serve emoji artwork in the reaction hit-area journey (#2138)
  test(browser): click a reply link only after its row settles (#2358)
  fix(agents): restore delegated workflow mentions (#2399)
  feat(identity): always back up keys in managed builds (#2398)
  test(threads): render before checking the reader across activity resizes (#2389)
  ...

Signed-off-by: Gil Birman <gil@squareup.com>
Co-authored-by: Claude <noreply@anthropic.com>

# Conflicts:
#	src/plugins/author.test.mjs
zandt-square added a commit to zandt-square/buzz-app that referenced this pull request Nov 4, 2026
Co-authored-by: Fizz <fbf1920f313ab37ffa4c517e2437e247fe1423378e077eccc4e29f15625b9918@buzz.block.builderlab.xyz>

* origin/main:
  fix(mermaid): cap diagram output size (block#2231)
  feat(agents): give plugin agent types the Buzz side of a turn (block#2364)
  feat(plugins): pin buzz://plugin-install links to a path and commit (block#2315)
  feat(plugins): tint currentColor SVG page icons like host icons (block#2314)
  feat(notifications): add a soft notification sound (block#1536)
  feat(agents): let agents propose a profile picture (block#2267)
  fix(plugins): default reminders and workflows off for fresh installs (block#2291)

Signed-off-by: Zandt <zandt@squareup.com>
wpfleger96 added a commit that referenced this pull request Nov 4, 2026
…w-tab

* origin/main: (41 commits)
  [3/5] Add protection to the Claude harness plugin (#1878)
  fix(settings): keep the bottom padding on long sections (#2361)
  fix(mermaid): cap diagram output size (#2231)
  feat(agents): give plugin agent types the Buzz side of a turn (#2364)
  feat(plugins): pin buzz://plugin-install links to a path and commit (#2315)
  feat(plugins): tint currentColor SVG page icons like host icons (#2314)
  feat(notifications): add a soft notification sound (#1536)
  feat(agents): let agents propose a profile picture (#2267)
  fix(plugins): default reminders and workflows off for fresh installs (#2291)
  Show all reactors in compact, separate emoji capsules (#2179)
  fix(panels): remember page split widths per workspace (#2264)
  feat(search): browse open channels from a Channels tab in search (#2164)
  perf(relay): page combined replay filters after a reconnect (#2308)
  fix(composer): make native Mac text shortcuts work past link chips (#2390)
  perf(relay): read creator proofs for many channels per filter (#2312)
  fix(channels): let published leave and delete confirm through access loss (#2357)
  fix(media): save native context menu media downloads and hide loopback links on macOS (#2131)
  fix(links): say why a message preview is unavailable, and preview unjoined public channels (#2136)
  test(browser): serve emoji artwork in the reaction hit-area journey (#2138)
  test(browser): click a reply link only after its row settles (#2358)
  ...

# Conflicts:
#	src/buzz-mcp/tools.ts
johnmatthewtennant added a commit that referenced this pull request Nov 4, 2026
Records main as a parent; 5560670 brought in its changes without one.

Signed-off-by: John Tennant <jtennant@block.xyz>
Co-authored-by: Martha <73923046810b68ae182000e74ef7c444383a907df20f81f2ba1008870a6f45a1@buzz.block.builderlab.xyz>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* origin/main:
  feat(solo): let viewers join read-only spaces (#2301)
  [3/5] Add protection to the Claude harness plugin (#1878)
  fix(settings): keep the bottom padding on long sections (#2361)
  fix(mermaid): cap diagram output size (#2231)
  feat(agents): give plugin agent types the Buzz side of a turn (#2364)
  feat(plugins): pin buzz://plugin-install links to a path and commit (#2315)
  feat(plugins): tint currentColor SVG page icons like host icons (#2314)
  feat(notifications): add a soft notification sound (#1536)
  feat(agents): let agents propose a profile picture (#2267)
  fix(plugins): default reminders and workflows off for fresh installs (#2291)
  Show all reactors in compact, separate emoji capsules (#2179)
  fix(panels): remember page split widths per workspace (#2264)

# Conflicts:
#	src/bundled/claude-code/manifest.json
johnmatthewtennant added a commit that referenced this pull request Nov 4, 2026
Co-authored-by: Martha <73923046810b68ae182000e74ef7c444383a907df20f81f2ba1008870a6f45a1@buzz.block.builderlab.xyz>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* origin/main: (96 commits)
  test(agents): refuse a real relay workflow mention in the harness kit (#2444)
  fix(agents): catch up every event watch on the kinds it watches (#1852)
  Keep local artifact collections current (#1507)
  feat(members): add several people to a chat in one write (#2010)
  feat(solo): let viewers join read-only spaces (#2301)
  [3/5] Add protection to the Claude harness plugin (#1878)
  fix(settings): keep the bottom padding on long sections (#2361)
  fix(mermaid): cap diagram output size (#2231)
  feat(agents): give plugin agent types the Buzz side of a turn (#2364)
  feat(plugins): pin buzz://plugin-install links to a path and commit (#2315)
  feat(plugins): tint currentColor SVG page icons like host icons (#2314)
  feat(notifications): add a soft notification sound (#1536)
  feat(agents): let agents propose a profile picture (#2267)
  fix(plugins): default reminders and workflows off for fresh installs (#2291)
  Show all reactors in compact, separate emoji capsules (#2179)
  fix(panels): remember page split widths per workspace (#2264)
  feat(search): browse open channels from a Channels tab in search (#2164)
  perf(relay): page combined replay filters after a reconnect (#2308)
  fix(composer): make native Mac text shortcuts work past link chips (#2390)
  perf(relay): read creator proofs for many channels per filter (#2312)
  ...

Signed-off-by: John Tennant <jtennant@block.xyz>
ravarora2 added a commit that referenced this pull request Nov 4, 2026
…-mentions

* origin/main: (57 commits)
  Keep local artifact collections current (#1507)
  feat(members): add several people to a chat in one write (#2010)
  feat(solo): let viewers join read-only spaces (#2301)
  [3/5] Add protection to the Claude harness plugin (#1878)
  fix(settings): keep the bottom padding on long sections (#2361)
  fix(mermaid): cap diagram output size (#2231)
  feat(agents): give plugin agent types the Buzz side of a turn (#2364)
  feat(plugins): pin buzz://plugin-install links to a path and commit (#2315)
  feat(plugins): tint currentColor SVG page icons like host icons (#2314)
  feat(notifications): add a soft notification sound (#1536)
  feat(agents): let agents propose a profile picture (#2267)
  fix(plugins): default reminders and workflows off for fresh installs (#2291)
  Show all reactors in compact, separate emoji capsules (#2179)
  fix(panels): remember page split widths per workspace (#2264)
  feat(search): browse open channels from a Channels tab in search (#2164)
  perf(relay): page combined replay filters after a reconnect (#2308)
  fix(composer): make native Mac text shortcuts work past link chips (#2390)
  perf(relay): read creator proofs for many channels per filter (#2312)
  fix(channels): let published leave and delete confirm through access loss (#2357)
  fix(media): save native context menu media downloads and hide loopback links on macOS (#2131)
  ...

Signed-off-by: Ravneet Arora <rarora@squareup.com>
matt2e added a commit that referenced this pull request Nov 5, 2026
…2607)

## Problem

The PR flake check repeated only the tests in files a pull request
edited. If a product change made an unedited test racy, the check
selected nothing. #2000 repeated one emoji journey and skipped the seven
other specs that load `emoji.html`. Five of its flaky journeys were in
those specs.

## What changes

`scripts/flake-check.mjs select` now selects in two tiers:

- **Tier 1, edited tests.** This is exactly the old rule: same
repetitions, both engines. The budget never trims it, even when tier 1
alone goes over.
- **Tier 2, related tests**, run as whole files:
- Browser specs that import a changed helper, or that open a
`tests/fixtures/*.html` page whose module graph holds a changed source
file, stylesheet or patched package. One rolldown build of every spec
and fixture page supplies the graph and writes nothing (1,027 modules in
about 1 s).
- Vitest files related to the changed modules through Vitest's module
graph. This is the graph the pre-push `vitest related` uses.

Picks are ranked by specificity: the smallest route that holds a changed
file comes first, and the cheaper test wins a tie. A test named after a
changed module ranks ahead of that order (`ComposerAttachments.tsx` →
`composer-attachments.spec.mjs`). The step summary marks those rows as a
naming heuristic, not graph evidence. Tier 2 adds picks in rank order
while each lane's predicted wall time (`flake_browser` and
`flake_vitest`) stays within **9 minutes** (`LANE_BUDGET_MINUTES`;
`--budget=<minutes>` overrides it). The 40-journey and 20-Vitest-file
caps still apply, and the pick that crosses a cap still runs.

**Cost table.** `scripts/flake-check-costs.json` is checked in and
written by the new `flake-check costs [run-id…]` subcommand. By default
it reads the latest three green `main` push runs. It reads the required
lanes' Playwright and Vitest reports and stores median passing seconds
per journey title as [Chromium, WebKit], plus a median per Vitest file.
A test missing from the table falls back to its file's median, then to
the engine-wide median or the median of all Vitest files. I checked in
the table instead of fetching timings in CI for three reasons: `select`
stays reproducible from the commit, `flake_select` needs no token or
network, and the artifacts are about 100 MB per run and expire after 7
days. The current table comes from runs 41990511962, 41980968364 and
41979442279 (Nov 5): 1,049 journeys and 964 Vitest files in 181 KB.

**Lane model.** I fit the model to hosted PR runs from Nov 4–5. The
median predicted/actual ratio is 0.95 for the browser lane and 1.02 for
Vitest.

- Browser shard: 105 s of overhead + 1.11 × the shard's summed test time
× 10 repetitions / 2 workers, then × 1.22 for imbalance when there is
more than one shard.
- Vitest batch: 26 s + 5 × (5.7 s + 0.72 × max(sum / 2, slowest file)).

The step summary gains a Tier column. It also shows each lane's
predicted time against the budget, with the edited-only time beside it,
and the related picks dropped for time and for the cap.

`docs/contributing.md` describes the tiers and the budget. It also
corrects "at most eight" shards to sixteen (`MAX_SHARDS`).

## For reviewers: the budget takes the longest fitting prefix

Tier 2 does **not** stop at the first pick that would go over the
budget. It takes the longest rank-order prefix whose predicted lane
fits. Browser shards grow with the selection (one shard per five
journeys), so a longer prefix can predict a *shorter* lane than a
shorter prefix. In the 248-PR replay, stopping at the first overrun
would have trimmed browser picks in 45 PRs. In 44 of those, the cap-only
selection already fit, and 40 predicted a slower lane after trimming.
#2000 would have kept 2 related journeys at 8.6 minutes instead of 46 at
6.2, and lost both of its flaky specs. Ranks are never skipped. The
Vitest lane only grows with each pick, so both rules give the same
result there. A unit test covers the non-monotonic case, and that test
fails under a first-overrun loop.

## Validation

Replays of `select <merge>^1 <merge>` in detached checkouts of each
merge commit. Selection before this PR → after:

| PR | Edited Vitest / journeys | Related journeys | Related Vitest |
Browser lane (min) | Vitest lane (min) | Flaky targets kept |
| --- | --- | --- | --- | --- | --- | --- |
| #2000 0944c1d | 1 / 1 | 0 → 46 (12 specs, incl. reactions-polish,
message-overlays) | 0 → 4 | 6.2 | 1.5 | yes |
| #1361 5992e69 | 2 / 0 | 0 → 40 (incl. composer-attachments, by name)
| 0 → 0 (budget) | 8.0 | 9.4 (edited alone 9.4) | yes |
| #2291 83b72a3 | 2 / 153 | 0 → 0 (budget) | 0 → 18 | 15.3 (edited
alone 15.3) | 6.6 | n/a |
| #1910 e7ae7b1 | 3 / 0 | 0 → 53 | 0 → 10 | 5.7 | 9.0 | n/a |

Lane times are this PR's predictions. Without the budget (the first
commit alone), the Vitest lane would have been 9.8 min for #2000, 16.3
min for #1910 and 6.6 min for #2291, and #2291's browser lane 18.3 min.
`--budget=Infinity` reproduces the first commit's output byte for byte
on all four source PRs. In the first commit's replay, a spec-only PR
(#2557) and a docs-only PR (#1694) selected exactly what the old rule
selected.

- `node --test tests/integration/flake-check.test.mjs`: 20 pass. Biome
is clean, including the table.
- Local `select` time on a laptop: #2000 takes 49 s with a cold Vitest
cache and 6 s warm (13 s before); #1361 takes 63 s cold and 8 s warm (19
s before). CI runs cold, within the select job's 5-minute limit. These
are local measurements, not hosted ones.

## Cost and known gaps

- **Runner-minutes grow about 7.5×.** In a replay of the 248 PRs merged
Nov 2–4, flake runner-minutes per run averaged about 11.4 under the old
rule and about 84 with related selection. Almost every source PR fills
the 40/20 caps, and the caps are what bound the cost. The budget limits
wall time only: against the first commit it moves the mean from 84.6 to
84.0 and the max from 381 to 319 (#2291). Lane wall time stays about 6–7
minutes for most PRs, and the highest predicted lanes fall from 16.7 to
13.7 minutes (browser) and from 16.3 to 10.4 (Vitest). All 11 Vitest
lanes still over 9 minutes are over on edited tests alone. The lanes
stay advisory, and repetitions, timeouts and workers are unchanged.
- **Not yet run in hosted CI.** This PR's own run will be the first.
- **Cost table drift.** Timings go stale until someone reruns
`flake-check costs`.
- **Model error.** Predicted/actual ranges from 0.73 to 1.23 (p10–p90)
for the browser lane and from 0.75 to 1.58 for Vitest. A Vitest
`file:line` filter is charged for its whole file.
- **Full-app journeys.** Journeys that load the full app rather than a
fixture page are reached only through helpers. This misses #1729, #2108
and #1969, which a coverage-map follow-up would address. A patched
package reaches browser specs but not Vitest files.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Signed-off-by: Matt Toohey <contact@matttoohey.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants