The README enumerated every menu item, accelerator, and label behavior;
state only the capability and its platform condition. The Agent Note now
records the verified Electron mechanism instead of a bare claim: role
labels are English literals in Electron, re-applied to the native items
before the menu opens.
While the Host runs an install, the dialog's close control was disabled. It now asks the Host to stop the run, the same request as Cancel install, and closes the dialog once the Host confirms the stop; when the Host answers too late or cannot confirm, the dialog stays with that word. Escape and the mask keep waiting while the Host owns the operation. The control is labelled 取消安装并关闭 / Cancel install and close while it does this.
The cards and the pages of the Plugins page repeated their head (icon, opening title, tags, one-liner) and their top (crumb, icon, actions); CardHead and DetailTop carry them once, which is what the duplication gate asked for. DOM and behavior are unchanged.
- A bundle row with a configuration page is opened from its name, which carries an inline chevron like the plugin cards; the separate configure button and its `configure` label are gone. Status and switch stay at the right.
- The three install-guide examples carry an "示例:" / "Example: " label before the code.
- README and Agent Note record that a bundle's pages live with the row that carries its browser half: `dsh-client-modules` attaches that half to the row named by the bare package name, so a page keyed to a subpath row disappears with the root row.
Add the standard application hide commands (Cmd+H, Option+Cmd+H, Show All) and
pin them with the window commands in the startup test, drop the redundant mock
cast that failed the lint gate, move the Agent Note to bug-fix, and state the
English role labels and the Dock-activation condition in both READMEs.
The custom application menu replaces Electron's default one, so macOS lost
File > Close Window (Cmd+W) and Window > Minimize (Cmd+M) while the traffic
light and the Dock activation path still closed and reopened the window.
Declare the fileMenu and windowMenu roles on macOS, keep Windows and Linux on
the application and Edit menus, and pin the per-platform template.
The Plugins page declares three slots as children of its main entry:
`plugins.item` lists an official plugin's page in the Official group,
`plugins.bundle.config` renders a bundle's own form on its page, and
`plugins.row.config` gives a row a configure control opening the row's
page. Every entry renders in the `summary` and `page` views the page
passes as owner props; the page draws the title, icon, and crumb and
projects the ledgers beside its store, naming no configurable plugin.
`ui-settings-plugins` registers its four host-plane pages into
`plugins.item` while the Host serves their namespaces and withdraws them
when it stops; the forms keep edits until a save and drop them on leaving
the page, so the discard control and the unsaved marker are gone. The
Settings section becomes the Built-in plugins shell around the inventory
tab, and `settings.plugin.item` is retired.
The Official group opens with the optional bundles the installation
ships, tagged Beta where the feature is one and without an official tag,
followed by the configuration pages. Auto review leaves the optional
bundles and the CLI's dependencies; the install guide names it as its
example spec. The version tag is a capsule like the other tags.
The `plugin-config` web lane drives the pages through the real wire and
opens a community fixture's row page after switching its bundle on; the
settings lanes re-record the renamed navigation entry.
The document preview declares two child slots handing the previewed file
and its Host path to other plugins: the header actions after its own
controls, and the empty state of a file it cannot render, where Retry stood.
Empty-state read failures now name their recourse: not-text and too-large
offer the handoff, not-found and non-regular paths offer nothing, and the
rest keep Retry. The unsupported-suffix empty state offers the same seat.
ui-open-in-app fills both seats with an "Open" split button (default
application, or the file manager reveal from its menu) and an empty-state
"Open in default app" button. Both call the Session Remote the Host already
publishes: canOpenWorkspacePath once per page decides whether they render,
openWorkspacePath runs each gesture. Only the pressed control disables while
its gesture settles; a failure announces once through a transient toast.
The delivery cards keep their own opener this iteration. The design, slot
pair, failure classification, and toast rule come from Yifffan's PR #4120.
The mapping holds forty host suffixes, not thirty-eight: WeChat and QQ
each keep their own suffix, and Telegram and WhatsApp each add a second
short-link host.
Review asked for the sites a general audience visits. The vocabulary
grows from fourteen developer sites to thirty-four marks across search
(Google, Baidu, DuckDuckGo), video and audio (TikTok, Netflix, Spotify),
social and messaging (Facebook, Instagram, Reddit, Telegram, WhatsApp,
WeChat, QQ, Weibo), shopping (Taobao, AliExpress, eBay), reference and
community (Quora, V2EX), and Apple.
Matching now takes the longest host suffix, so weixin.qq.com keeps the
WeChat mark while qq.com keeps QQ. The spec covers one URL per site,
still requires distinct marks, and pins the Telegram and WhatsApp
aliases as well; the README and Agent Note record the categories, the
bounded per-site cost, and the licensing and trademark position.
Each unwrapped split column is its own scroll container, and only the
horizontal offset was mirrored onto the other side, so wheel-scrolling one
column left the other behind and the paired rows drifted apart. Mirror the
vertical offset the same way.