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

fix(plugins): review a pinned link to an installed plugin's source as an update - #3024

Merged
kazemek21 merged 1 commit into
block:mainfrom
kazemek21:kylez_NEXUS-4327_pinned-link-plugin-update
Nov 9, 2026
Merged

kazemek21 merged 1 commit into
block:mainfrom
kazemek21:kylez_NEXUS-4327_pinned-link-plugin-update

Conversation

@kazemek21

@kazemek21 kazemek21 commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

TL;DR

A buzz://plugin-install Git link pinned to both a commit and a path, for a plugin already installed from that same repository and folder, now opens the Update review that a plugin's Git requestInstall already gets. If the link names another branch or tag than the plugin tracks, the review says so. Before, it hit the Add path's Already installed refusal, so there was no reviewed way to update from such a link. Links without both pins, and links to a plugin installed from another source, are still refused as duplicates.

What changed

  • When the installed plugin was imported (not bundled), PluginImport treats a link with both commit and path like a bound requestInstall request when deciding between update and duplicate (src/app/PluginImport.tsx). It reuses the existing same-source check: the installed updateSource must be a Git source whose repository matches the fetched preview's source and whose folder matches the candidate's folder, and the candidate must have the installed manifest ID. Native import saves the requested ref, and later update checks follow it. So when a link's or plugin request's ref differs from the installed Git source's ref, the review adds "Future updates will follow instead of ." An empty ref reads as "the repository default".
  • Confirming a requested update (link or plugin request) re-reads the live catalog and refuses with "The installed plugin changed. Close this review and check again." if the installed revision, enabled state or saved source changed after the review opened, so the review's "stays disabled" line can't go stale.
  • A requested update of a disabled plugin now says "This plugin will stay disabled.", as the Details Update review already does. Native install already keeps the enabled state, and the review offers no enable switch for updates.
  • Docs: docs/plugin-architecture.md, docs/deep-links.md and docs/buzz-help.md describe the pinned-link update.

Protections that still apply: the commit pin (native refuses a ref whose tip differs, and the review re-checks the fetched commit), the folder filter, the access review against the installed manifest, the publisher line and native publisher-continuity refusal, the unsigned-to-signed rollback warning, explicit Update confirmation, and preview discard on cancel. Links with only commit, only path, or neither, and pinned links to a bundled plugin, keep showing Already installed / Open in Buzz.

Not in scope: update discovery, Update-all, managed policy feeds or checkers (#2504, #2621, #637), signature or publisher-trust policy (#2212, #2746), and the compact request dialog (#2625). This PR doesn't touch their hunks. #2983 and #2762 also edit tests/browser/plugin-import.spec.mjs; this PR leaves that file unchanged.

Supported operation

On a Buzz desktop build that includes this change, open buzz://plugin-install?repository=<repo>&ref=<ref>&path=<folder>&commit=<40-or-64-hex> for a plugin whose installed copy came from a Git import of that same repository and folder. The review shows Update , with access changes listed against the installed version, and states any change to the branch or tag later updates follow. Nothing changes until you choose Update. Native import still refuses the update if the ref's tip isn't the pinned commit, or if the publisher changed or a signed plugin became unsigned.

Tests

New src/app/PluginImport.test.tsx cases, all with fictional example.com fixtures:

  • A pinned link to the installed source reviews as Update, installs the pinned folder, and doesn't call enable. This is the regression test for the original failure.
  • A disabled plugin stays disabled and the review says so.
  • A pinned link with another ref than the installed plugin tracks (a named ref, or the repository default) reviews as Update, says which ref future updates will follow, and installs on Update. A same-ref link shows no such line.
  • A link without both pins (none, path only, commit only), or a pinned link to a bundled plugin, still shows Already installed with Open in Buzz.
  • An installed source in another repository or folder, a local folder, or an unknown source is refused with the source-mismatch message and Open in Buzz.
  • When only another plugin ID is installed from that source, the link offers a new install.
  • A fetched commit that differs from the pin offers no Update.
  • Cancel discards the preview without installing.
  • If the installed revision, enabled state or source changes after the review opens, Update is refused, for both a link and a plugin's requestInstall.

The request and link harnesses now return a ready catalog from plugins.snapshot(), which the new confirm-time check reads.

Checked on a Linux box at 37cf73e1: biome check on both files, pnpm typecheck, and vitest run src/app/PluginImport.test.tsx (100 passed). After the first review fixes, the same three checks passed locally (102 tests), and the bundled-plugin test fails on the earlier predicate. The later enabled-state drift case (two lines plus one test input) passed biome locally; host load refused a local test run, so PR CI covers it. With only the requested line reverted, 6 of the 8 pinned link tests fail. Against main's PluginImport.tsx, the same 6 fail and the other 94 pass. The two that pass either way are the existing pin-retry test and the other-plugin-ID new-install case, which should behave the same before and after.

After review feedback, the tracked-ref disclosure was verified on a Blox box at e913727f: biome check, pnpm typecheck and vitest run src/app/PluginImport.test.tsx (103 passed). With the review line disabled, the new tracked-ref test fails. The before/after screenshots predate this line and show a same-ref update.

Before / after

These screenshots come from a temporary Chromium journey using the existing nativeImports IPC fixture and fictional example data; the journey is not committed. It installs example.linked from https://github.com/example/plugins at plugins/linked, then delivers the same pinned link again with a newer candidate.

Light Dark
Before (main) t027-before-light t027-before-dark
After t027-after-light t027-after-dark

Remaining gaps

  • No native (Tauri) run: the Playwright screenshots use the existing IPC fixture. Native import, publisher continuity and the deep-link handoff were not changed here.
  • No human has tried it in the app yet, so buzz-review-completed is not set.

Initiative context

Status: https://g2.sqprod.co/apps/kylez-buzz-improvements-status (buzz-improvements T027).

Fixes NEXUS-4327

🤖 Generated with Claude Code

@kazemek21
kazemek21 force-pushed the kylez_NEXUS-4327_pinned-link-plugin-update branch 2 times, most recently from c7ce487 to c516182 Compare November 8, 2026 20:35
@kazemek21
kazemek21 marked this pull request as ready for review November 8, 2026 20:52
@kazemek21
kazemek21 requested a review from a team as a code owner November 8, 2026 20:52
@tellaho

tellaho commented Nov 8, 2026

Copy link
Copy Markdown
Contributor

🤖 Design review at c5161825879777dc70b2570442d9c7a37104f0d3: no design blockers found. Pinned links now reach an explicit Update review, compare access with the installed version, and preserve whether the plugin is enabled. The supplied wide light/dark screenshots are consistent.

Reviewed the diff, surrounding source and regression cases; did not run tests. Not checked live: native deep-link/update, narrow or enlarged-text layouts, keyboard/focus, agent activity, or rendered disabled/access-change/error states.

@kazemek21

Copy link
Copy Markdown
Contributor Author

Thanks for the design pass. Nothing here changes layout: the pinned link reuses the existing Update review, and the only new copy is the "This plugin will stay disabled." line that the Details Update review already shows. I agree the items you listed weren't checked live: native deep-link/update, narrow and enlarged-text layouts, keyboard/focus, and the rendered disabled, access-change and error states. They stay listed under Remaining gaps in the description. The disabled, access-change and changed-plugin refusal states are covered by src/app/PluginImport.test.tsx at c5161825.

— Posted by Claude Code (claude-opus-5-5) on behalf of kylez

@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.

🤖 One update-source correctness issue.

Comment thread src/app/PluginImport.tsx Resolved
@kazemek21
kazemek21 force-pushed the kylez_NEXUS-4327_pinned-link-plugin-update branch from c516182 to 532def4 Compare November 9, 2026 00:50
@kazemek21
kazemek21 requested a review from kalvinnchau November 9, 2026 01:12
… an update

A buzz://plugin-install Git link pinned to a commit and folder for a plugin
imported from that repository and folder now opens the same Update review a
plugin's Git requestInstall gets, instead of the Add duplicate refusal. When
the link's or request's ref differs from the ref the plugin tracks, the review
says which branch or tag later updates will follow, because native import
saves it. Links without both pins and pinned links to a bundled plugin keep the
duplicate refusal. Confirming a requested update now also refuses if the
installed plugin's revision, enabled state or source changed after the review
opened.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Kyle Zemek <kylez@squareup.com>

@gilgtm gilgtm 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.

🤖 No P0/P1 findings in the deep-dual review of e913727fd5608ca61e3e239e078456ce8d5cec41 against main@80cb3a25569f763a2b36ce473320fe628a17c85f. Reviewed pinned-link update eligibility, confirmation and stale-state guards, native pin/publisher enforcement, source persistence, enabled-state preservation, and regression coverage.

Posted by duel-review skill [driver: codex(high), mode: deep-dual, review synthesized by codex(high)]

@kazemek21
kazemek21 merged commit 3333784 into block:main Nov 9, 2026
66 checks passed
gilgtm added a commit that referenced this pull request Nov 10, 2026
…nt-progress-rows

* origin/main: (53 commits)
  fix(search): make Command F search the Bestie conversation (#3084)
  fix(plugins): keep failed update checks on the plugin's Settings row instead of a toast (#3088)
  Show single-agent Stop on the activity bubble (#3140)
  fix: support explicit hosted browser origins (#3149)
  fix: keep Codex tool namespace descriptions bounded (#3128)
  fix(messages): show "New messages" in channels longer than one page (#3071)
  Keep shared agent guidance generic (#3134)
  fix(typing): a thread reply also ends the agent's channel-level typing (#3148)
  Stream protected evidence across agent runtimes (#2882)
  feat(identity): consolidate key and account controls (#3069)
  Add portrait-colored foil and animated agent card reveal (#3144)
  NEXUS-4190: Disclose unavailable saved Solo choices (#2544)
  docs: mark the plugin API as preview and say which parts are steady (#3129)
  Open the app with a saved key; check the account's key in the background (#3064)
  fix(federated-identity): name only communities that require NIP-FI as affected by a switch (#3072)
  feat(pairing): signed in with Builderlab, say to get the app instead of pairing (#3039)
  Show Add agent button on shared agent previews (#3131)
  NEXUS-4224: Preserve peer unread intent during automatic reads (#2641)
  fix(plugins): review a pinned link to an installed plugin's source as an update (#3024)
  perf(profiles): resume verified-profile batches after a planned renewal (#2293)
  ...

Signed-off-by: Gil Birman <gil@squareup.com>

# Conflicts:
#	docs/buzz-help.md
kazemek21 added a commit that referenced this pull request Nov 10, 2026
## TL;DR
Expose optional plugin update discovery and explicit review queues
through the existing `pluginInstaller` service. Reuse the host's
retained checker and importer; a missing result remains unknown, not
proof that a plugin is current.

## What
- `getSnapshot`, `subscribe`, and `refresh` expose aggregate status,
known candidates, and known errors. Plugin-triggered refreshes share a
one-minute minimum interval.
- `queueUpdates` accepts opaque tokens for current candidates from a
recent completed check. Each item opens the existing confirmation
dialog, identifies its requesting plugin, and preserves source,
publisher, access, and saved enabled-choice guards.
- Queue snapshots support observation and cancellation. A confirmed
import keeps its review slot until the native operation settles,
including after the watchdog, cancellation, or consumer unmount.
- Stable provider and request IDs bind replay to the exact ordered,
deduplicated token list. Request IDs are namespaced by calling plugin
ID; a remounted consumer can reconcile its prior request. Both
subscriptions are released with the caller's lifetime.
- `getQueueRequest` returns `admitted`, `not-admitted`, `unknown`, or
`conflict` without submitting. Only `not-admitted` from the same live
provider proves non-admission. Replacement, restart, or queue eviction
stays unknown and cannot create a duplicate on replay.
- A fresh snapshot miss does not establish that an individual plugin was
checked, is eligible, or is current. Distinct submissions retain
independent confirmation and cancellation; only an exact identified
replay shares a queue.

## Validation and limits
Focused regression coverage covers review drift and missing candidates,
busy-manager admission, late native settlement, caller cleanup, request
isolation, and provider replacement. [Hosted
CI](https://github.com/block/buzz-app/actions/runs/42895615087) passed
on `affbcd72`, including all JavaScript shards and changed-file
repetitions. The repairs were not run locally; normal precommit checks
passed.

No native installed/runtime or fail-before/pass-after proof is claimed.
Queue state lasts only for the host provider lifetime. The frontend
checks and immutable prepared import preserve the existing boundary;
this does not add native enforcement or cross-restart idempotency. No
second checker or per-plugin checked-current result is added.

## Tracking
Fixes NEXUS-4337
Pinned-link classification and ref-change disclosure are in
[#3024](#3024).

Generated with [Codex](https://openai.com/codex) (gpt-6.1-sol, high) on
behalf of kylez

Signed-off-by: Kyle Zemek <kylez@squareup.com>
Co-authored-by: Codex <noreply@openai.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.

4 participants