Repository navigation
fix(plugins): share background updates with Manage plugins - #2621
johnmatthewtennant wants to merge 61 commits into
Conversation
Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Keep read-only acquisitions and result ordering under one owner. Share pending source reads, retain failures, and preserve the latest result through update review. Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Resolve PluginImport overlap by retaining the shared discovery checker alongside pinned shell previews, source revalidation and automatic-install access review. Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Reuse unchanged source results after management actions, honor Git automatic-check eligibility, and discard queued retries for superseded installations. Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Revalidate the current installation and automatic-check policy before queued retries and after Git authorization. Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Track every consumer of a shared acquisition and settle pending indicators independently of result eligibility. Preserve explicit checks after automatic access is disabled. Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Reuse the bounded saved-source reader for discovery, retaining package identity, signature and path checks without scanning sibling packages. Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Preserve the extra-actions target alongside shared update checks. Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
There was a problem hiding this comment.
🔵 Needs a closer look
Human verification of native list discovery and update consent remains outstanding, and static review could not validate app interactions or WebKit behavior.
No open issues 🎉
What changed in this PR
This PR makes saved-source plugin updates discoverable directly from Manage plugins, without opening each plugin’s details, while preserving the existing review-before-install flow.
Changes:
- Check saved folders and eligible Git sources on opening Manage plugins, window focus, and visibility changes.
- Share pending checks, revisions, and errors between the list and details, with stale-result protection.
- Limit native folder checks to the installed package path and add regression coverage and user guidance.
| File | Description |
|---|---|
tests/browser/plugin-import.spec.mjs |
Adds browser coverage for list discovery and focused details refresh. |
src/plugins/update-checks.ts |
Adds shared read-only checks with retained results and acquisition ordering. |
src/plugins/update-checks.test.ts |
Covers shared reads, stale results, failures, and eligibility changes. |
src/app/Settings.tsx |
Triggers source checks and exposes discovered updates in the list. |
src/app/Settings.test.tsx |
Covers list discovery, refresh, preferences, and review interactions. |
src/app/PluginImport.tsx |
Connects details and update review to shared check results. |
src/app/PluginImport.test.tsx |
Covers pending-check usability and retained source-less updates. |
docs/buzz-help.md |
Documents automatic discovery and review-before-install behavior. |
crates/plugin-manager/src/imports.rs |
Bounds folder discovery to the installed package and tests validation safeguards. |
Review effort: Balanced
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Star Lord’s automated source review via Wes’s account.
One P3 keyboard-focus regression is detailed inline: automatic discovery can replace the focused row action without handing focus to its replacement.
Reviewed head 9cca28a5fef788bae867875194186f65ecbb3f31 against target/merge-base a49d19688de36d20f6037fe22f5a4075c146fa79. Coverage includes the native saved-folder reader, shared asynchronous update checks, and list/details/owner-review flows, with independent Rocket, Mantis and Groot coverage and lead integration. The PR description and both attached screenshots were also inspected.
Source-only review: no tests, builds, app launches or PR code execution. The reported native/browser results and human acceptance are not independently verified; rendered keyboard behavior still needs confirmation. This is a COMMENT review, not approval.
kalvinnchau
left a comment
There was a problem hiding this comment.
🤖 One additional maintainability finding; the existing focus-preservation comment is not duplicated.
Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Preserve retained update review queues and source identity checks alongside shared discovery observations and independent folder checks. Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Force the coalesced follow-up after sources drift during acquisition, while preserving throttling for ordinary management changes. Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Use each source's eligibility clock for scheduling and token freshness so a later plugin check cannot spin or postpone another source. Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Keep discovery results through enabled-state changes and restore a failed active review only when its installation and recovered candidate still match. Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Publish the recovered candidate before selecting its retained token so an unchanged active review survives background recovery. Cover background and explicit recovery with changed-candidate refusals. Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
## TL;DR
This lets a plugin distinguish a conclusively retired update provider
from an unknown submission without bypassing native review. The plugin
update capability gains an optional `getOwnerStatus(ownerId)` that
returns `retired` only once the host has seen that exact provider
lifetime disposed with no queued, reviewing or confirmed operation left.
Every other case stays `unknown`.
## Why
Today a plugin that captured `ownerId` before an ambiguous
`queueUpdates` call can only learn `unknown` once that provider is gone.
A changed `ownerId`, a missing queue, an `unavailable` snapshot or an
unregister are not proof that the old lifetime is over. `register(next)`
swaps the bridge pointer without disposing the original, and `dispose()`
deliberately keeps an already-confirmed installing review, and its
shared review hold, until that operation completes.
## What changes
- `createPluginUpdates` keeps a small `{ ownerId, retired }` lifetime
record. It flips to `retired` in `releaseReview` once the provider is
closed and has no active review. That happens at `dispose()` when
nothing is in flight, or later when a confirmed operation finishes or
ends and releases the shared hold, never before.
- The installer bridge keeps the lifetime records of the 16 most
recently registered providers, not the providers themselves, and answers
`getOwnerStatus` from them. Unregistered-but-undisposed,
never-registered, evicted and post-restart IDs are `unknown`. The query
is read-only and adds no listeners.
- The per-plugin installer service forwards the method. It is optional
in `PluginUpdateCapability`, so plugins feature-check it on older hosts.
- `docs/plugin-architecture.md` documents the contract. `retired` says
nothing about what happened to an earlier request: a `getQueueRequest()`
result of `unknown` stays `unknown`, and nothing is retried, reset or
installed.
There are no changes to review, confirmation, source or access
validation, or queue admission.
## Tests
Added to the existing provider, bridge and installer test paths:
- `updates.test.ts`: provider replacement while the original stays live.
Its queued and unopened reviews are cancelled at dispose, after which it
reports `retired` stably on repeated queries and through `forCaller`; it
cannot start or confirm a review, and `getQueueRequest` stays `unknown`.
- `updates.test.ts`: a confirmed operation keeps its provider `unknown`
past dispose until its review is released, whether it finishes, ends, is
cancelled after unconfirming, or is re-confirmed as stale. The status is
still `unknown` while the shared hold is being released, and the retired
provider then admits no new queue or review.
- `updates.test.ts`: live, unregistered, never-registered, evicted and
new-bridge (restart) IDs stay `unknown`.
- `installer.test.ts`: real install requests and the plugin-facing
service. While the old confirmed update runs, the shared review stays
held: `requestInstall` is `unavailable` and the replacement cannot open
a review. Retirement is reported to every caller and after remount only
once that update finishes, and then the replacement's review can start.
Mutation check: each of these was applied in turn, and the new tests
failed every time: retiring at `dispose()`, retiring before the hold
release, removing eviction, and inferring retirement from a changed
current owner.
Targeted `vitest` over `updates`, `installer`, `PluginUpdates` and
`PluginImport` (287 tests), `tsc --noEmit` and `biome check` passed on a
Linux workstation. No browser journeys were added or removed.
Nearby open PRs #2621 and #3242 touch `updates.ts` and `installer.ts` in
different hunks. This change does not depend on either.
Not yet done: no agent exercised this in the native app (no UI change),
and the human test step is still pending.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Signed-off-by: Kyle Zemek <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Preserve revision and publisher identity throughout retained folder and Git checks, review recovery and per-source scheduling. Retain bounded saved-path acquisition and retired-provider status. Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Keep the public checker status consistent with shared discovery failures and recovery. Cover explicit reads and recovery from a failed background check. Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
kalvinnchau
left a comment
There was a problem hiding this comment.
🤖 One nonblocking freshness-notification inconsistency remains.
Seed missing eligible Git records before the existing reconciliation so explicit results and failures reach notices and the public update queue even when background discovery found no prior update. Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Restore the opt-in enforcement and signature-only repair guidance alongside shared update discovery instructions. Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Use the oldest eligible source check for snapshot staleness and the existing expiry timer. Cover staggered checks and removal of the older source. Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
## TL;DR The manual Git import form now maps a plugin listing's Ref to Branch or tag and explains that a blank ref scans the repository's default branch. Known Git-size refusals keep their native error text and add focused recovery guidance. ## Related work This remains separate from the importer changes in [#2712](#2712), [#2621](#2621), and [#2746](#2746). ## Testing Component tests cover blank and explicit refs, preserved native refusals, matching size guidance, and unchanged behavior for unrelated errors and install calls. A fictional visible-UI browser case checks the guidance and recovery text, keyboard return path, and narrow-width/enlarged-interface-size layout in light and dark themes. No live plugin install or manual product test was performed. ## Screenshots **Main — Git form, light, 320px**  **Updated — Git form, light, 320px**  **Main — size refusal, dark, 320px at 200% interface size**  **Updated — size refusal, dark, 320px at 200% interface size**  Generated with [Codex](https://openai.com/codex); posted by Codex (gpt-6-luna) on behalf of kylez. --------- Signed-off-by: Kyle Zemek <[email protected]> Co-authored-by: Codex (gpt-6-luna) <[email protected]>
Preserve scoped Git acquisition and error recovery while sharing retained update checks. Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Scope the Git-to-URL migration journey to its review action when retained discovery also offers an update notice. Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Assert the exact URL installation calls while permitting the read-only startup check of the installed Git source. Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
Retain the effective Git discovery scope, including managed pins. Discard mismatched retained results when recommendations change, so unchecked releases cannot acquire update tokens. Cover commit, repository, ref and folder changes while offline, plus recovery after checking the new source. Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
kalvinnchau
left a comment
There was a problem hiding this comment.
🤖 One managed-update review reconciliation regression remains.
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Automated source review by Star Lord, via Wes’s account.
Reviewed head 3fa12732f417bf8cb1a71fef3637fe8622594413 against target and merge-base ab344439a38248bb7088adf247167827e5fe8f4b, retaining the completed review of b6fcc37b. This follow-up covers the new folder scheduling and bounded previews, retained-result/source identity, recovery, expiry, and integration with queued consent and publisher checks.
No additional actionable findings. The existing P2 on managed review source identity remains applicable at this head; it is tracked there rather than duplicated here.
Source and relevant test bodies reviewed; PR description and screenshot inspected. No tests, builds, or native/browser workflows were executed. Author validation claims and human acceptance remain unverified; the PR reports no native-app or human testing of the pinned-URL integration.
Record fresh review results with the source actually loaded, including managed commit pins. Cover failed acquisition, recovery of the original queued candidate, and rejection of changed revisions or publishers. Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Automated source review by Star Lord, via Wes’s account.
Reviewed head ff8883448b9727f233a7ba22782d592bd01bf380 against target and merge-base ab344439a38248bb7088adf247167827e5fe8f4b, retaining the completed review at 3fa12732.
The managed-source observation P2 is addressed in source: both review observations now carry the effective update source, including its managed commit pin. Failure/recovery results can reconcile the retained record, while token recovery still requires the original candidate revision and publisher. No new actionable findings in this repair.
Reviewed the changed source and regression-test bodies, plus the current PR description and unchanged screenshot. No tests, builds, or native/browser workflows were executed. Author validation claims and human acceptance remain unverified.
Retain shared acquisition completion times independently of the automatic discovery cadence. Explicitly checked candidates can open review while offline or after a previous background result expires, while the hourly schedule and token expiry remain unchanged. Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <[email protected]>
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Automated source review by Star Lord, via Wes’s account.
Reviewed head 831ffb15ffd1fc39496a0bdba66ccc29d814dbe2 against target and merge-base ab344439a38248bb7088adf247167827e5fe8f4b, retaining the completed review at ff888344.
No new actionable findings in the freshness follow-up. Successful shared checks now supply source-qualified token freshness for explicit offline or expired checks, while automatic scheduling remains separate. The prior managed-source observation repair remains intact.
Reviewed the changed source and service/component regression-test bodies, plus the current PR description and unchanged screenshot. No tests, builds, or native/browser workflows were executed. Author validation claims and human acceptance remain unverified.
Why
Buzz could announce an available plugin update while Manage plugins still showed Disable. The popup and the list used separate discovery paths, so opening the list started another source read before showing the same update.
What
Use the existing background checker’s retained results in Manage plugins and plugin details. Check saved folders and eligible Git sources at startup and hourly while the app is visible. Opening the list, reopening Settings, and focusing the window do not start another check. Keep rows compact and silent while discovery runs; show Update when a newer version is available.
Saved folder and Git sources offer an explicit Check for updates action in details. Update uses the existing fresh package review, permission checks and installation flow. Saved-folder discovery and update previews read only the installed package path through the bounded native reader, preserving signature and plugin-ID validation. Unrelated sibling packages do not prevent reviewing an offered update. Managed plugins and pinned HTTPS URL artifacts keep their recommendation flow; URL sources never enter folder or Git discovery. Each discovery batch starts folder probes before awaiting Git authorization or acquisition. Unchanged sources retain their hourly check deadline, a stalled folder probe does not hold up other plugins, and notification reviews and explicit checks reconcile the same retained result and notice.
Reviewer-reproducible examples
The popup-to-list regression fails before the fix because the row still shows Disable despite the notice. It passes with the shared background result. Isolated native verification reproduced that failure, then confirmed immediate Update, compact rows, no additional Git acquisition on opening/reopening Settings or window focus, and cancellation without installation.
Screenshots
Manage plugins retains the compact Update action after dismissing the background notice.
Representative browser cases cover the Git notice-to-list path and a pinned URL installation followed by a newer pin, through the production app and native IPC adapter fixture. They verify the list/details wiring across those boundaries; helper tests cannot exercise that wiring. Existing enabled-state, modal retry/focus, saved-folder and open-details journeys retain their assertions and drive the hourly background cadence. No browser cases were removed.
Verification
The pinned-URL checker regression fails before the source guard and passes afterward. Held Git authorization and acquisition regressions likewise show a later folder result without releasing the Git operation after the scheduling repair. Browser journeys cover discovery before opening details, fresh review without installation, URL hash rejection, and updating a URL installation to a newer pin without Git or folder discovery. Native package tests cover pin validation and persisted URL source metadata. A saved-folder regression installs from a parent, adds 32 sibling plugins, rebuilds the installed package and reviews its update. Before the fix, preview fails with the sibling limit; afterward it captures only the installed path, and confirmation installs those captured bytes even if the source changes again. Both discovery and preview reject escaping paths, changed plugin identities and malformed signatures.
Earlier native and human checks confirmed Update before opening details and after Close. This integration with pinned HTTPS URL installs has not been exercised in a native app or by a human.