Repository navigation
feat(plugins): a first install takes effect when the user approves it (L1) - #511
Closed
nt-nerdtechnic wants to merge 6 commits into
Closed
nt-nerdtechnic wants to merge 6 commits into
nt-nerdtechnic wants to merge 6 commits into
Conversation
…next launch Installing a plugin (from a file or the Marketplace) stages it as a candidate; only plugins:restart promoted it. Reopening the App without pressing Restart left the lifecycle selector with a candidate and no active package, so the plugin never loaded, the startup scan fell back to <root>/<id>/manifest.json and logged a misleading "installed plugin quarantined: ... manifest.json is not valid UTF-8: ENOENT", and nothing was shown on screen. - plugins:restart's body becomes restartStagedCandidate(id); the handler keeps its authorization and target checks and calls it. - New controller method activateStagedFirstInstalls(), run at startup: promotes each candidate that has no active package, no activation in progress and nothing loaded under its id (a factory rollback also leaves only a candidate), exactly as Restart would. Updates and packages a rollback displaced stay staged: the selector does not tell them apart. - The startup scan skips a staged first install instead of reporting it as a broken package (a legacy package at the root still loads as before). - A candidate that cannot be promoted stays staged, is logged with the real reason, and the main window shows a toast naming the plugin, the reason and Settings -> Navide Plugins (Restart / Discard). en-US, zh-TW, ja-JP. Not a 0.2.27 regression: the scan fallback dates from 088b4ca (#133) and the promote path is unchanged since v0.2.26. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…Apply now" A package staged beside the active one (an update installed without Restart, or the package a rollback displaced) is not applied for the user at launch: the selector does not tell the two apart. Reopening Navide used to run the old version with nothing on screen. - pluginIpc: stagedUpdates() lists every record with an active package, a candidate and no activation in progress. - index.ts: after the first-install activation, the list goes to the main window through pluginStagedCandidateRelay (now carrying both notices, held until a main window has loaded). - Renderer: an announcements-centre row per package, "The Navide plugin X has version Y waiting to be applied; version Z is running", with "Apply now" (plugins:restart for that package, only while the same version is still staged beside the same active one), plus a toast. en-US, zh-TW, ja-JP. - Tests for the three relaunch cases: first install (promoted), update (stays staged, disclosed) and rollback (the rollback stands, disclosed). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… (L1) Live activation L1 (ANALYSIS-plugin-live-activation, approved 2026-10-20 23:46). Approving an install used to only stage the package; it ran after the user found Restart in Settings, or (since #505) on the next launch. - plugins:commitInstall and plugins:commitLocalInstall now promote a first install (candidate, no active package, nothing loaded under the id) right after the commit, outside its transaction, through the same restartStagedCandidate cutover Restart runs: trust and digest re-verification, the version-bound grant from this approval, the activation the Host's backend admission gate uses. Nothing runs under the id yet, so nothing is drained. A native backend still asks for its own consent before it starts. - The answer says what happened: restartRequired false with activatedVersion, or the candidate stays staged (Restart and Discard remain) with activationError, which the install flow shows. An update is left for Restart (L3). - plugins:restart on a plugin that is already active with nothing staged answers success with nothing to do, so a flow that still follows the commit with Restart keeps working. - The launch-time rule from #505 shares the same isStagedFirstInstall check. Consent is unchanged: nothing is written before the approval, and the approval is what activates. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This was referenced Oct 20, 2026
…pproval (L1) CI on #511 (classified, not rerun): pluginRegistry.e2e (3) still asserted the pre-L1 contract (commit only stages, the grant waits for Restart). It now checks that the approved commit activates 0.1.0 with its grant, and that a Restart that still follows has nothing left to do. Locally the suite was skipped for lack of the Registry venv; with it, 13/13 pass. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…l1-first-install # Conflicts: # src/main/plugins/pluginIpc.localInstall.test.ts # src/main/plugins/pluginIpc.ts
nt-nerdtechnic
marked this pull request as ready for review
October 20, 2026 22:21
nt-nerdtechnic
added a commit
that referenced
this pull request
Oct 20, 2026
… (L1) (#511) Squash-merged from origin/pr-511. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Collaborator
Author
|
Squash-merged into main as 2e22e4a. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Live activation L1: approving the install of a plugin that is not installed yet makes it take effect immediately. There is no Restart button to find and no relaunch (ANALYSIS-plugin-live-activation, approved by the user 2026-10-20 23:46).
Stacked on #505 (
fix/sideload-relaunch-promote, head ed5808b). L1 reuses therestartStagedCandidateextraction from #505. Once #505 merges, this branch merges main normally (no rebase), and the diff shrinks to the L1 commit c5030ae.What changed (commit c5030ae)
plugins:commitInstallandplugins:commitLocalInstall: after the commit, outside its transaction lock, a first install is promoted through the samerestartStagedCandidatecutover Restart runs. A first install here means a candidate with no active package, no activation in progress and nothing loaded under the id. A factory package or an update is left untouched.restartRequired: false, activatedVersion, or, when activation fails,restartRequired: true, activationError. On failure the candidate stays staged with Restart and Discard, and the install flow shows the reason (settings.extensions.activationFailed, en-US/zh-TW/ja-JP).plugins:restarton a plugin that is already active with nothing staged returns success with nothing to do, so a flow that still calls Restart after the commit keeps working.isStagedFirstInstallcheck.Disclosure
Test plan (red → green)
Red against #505's
pluginIpc.ts,pnpm vitest run src/main/plugins/pluginIpc.localInstall.test.ts -t "L1" --maxWorkers 1: 2 failed, 1 passed.is active right after the commit, with no Restart and no relaunchstays staged with Restart and Discard, and says why, when the activation failsleaves an update from a file for RestartGreen: all three pass.
Assertions that encoded the old "commit only stages" contract were updated (10 tests):
installedAtare now written on approval instead of on RestartThe
installLocalhelper calls Restart only while something is staged. The relaunch tests from #505 leave a first install staged by failing its activation once ("the App went away").Local run before the coordinator paused local tests:
pnpm vitest run pluginIpc.localInstall pluginIpc pluginIpc.localInstall.review pluginIpc.agentFileInstall pluginIpc.developerMode pluginIpc.testplace pluginIpc.digestBlock navideBrowserRegistryInstall pluginRegistry.e2e pluginAgentAction --maxWorkers 2: 10 files, 331 passed, 12 skippedpnpm typecheck: exit 0Review fixes (planb/0228/review-live-activation.md)
pluginRegistry.e2e (3)still asserted the pre-L1 contract. It now checks that the approved commit activates 0.1.0 with its grant, and that a following Restart has nothing to do. Local run with the Registry venv: 13/13 pass. Commit 2b0d415.Protection check
git diff origin/main -- 'backend/agent_team_backend/credential_*.py' 'backend/agent_team_backend/quota_*.py' 'backend/agent_team_backend/usage_*.py' src/renderer/src/composables/useQuotaFailover.ts | wc -lgives 0.pluginIpc.ts,preload/index.tsandusePluginInstallFlow.tsshows nothing removed.commitInstall/commitLocalInstallresult type widens fromrestartRequired: truetorestartRequired: booleanplus optionalactivatedVersionandactivationError(preload andenv.d.ts). No caller readsrestartRequired.plugins:restartgains the already-active, nothing-to-do answer.🤖 Generated with Claude Code