61b6788dd4
The Bots editor's model write (profiles.configure) was the one switch surface that bypassed the data-policy / expensive-model selection guard: a guarded pick (e.g. muse-spark contributor tier) was applied silently, with no confirm flow anywhere — the #95293 remainder after the core picker's confirm handshake landed in use-model-controls. Gateway: profiles.configure now answers confirm_required + confirm_message for a guarded model (same handshake as config.set model) and writes NOTHING until the client resends with confirm_expensive_model: true. Other sections still apply; the pending model section is not reported as failed. Desktop: the confirm flow is extracted out of use-model-controls into one shared applier (lib/guarded-model-switch.ts, exported through the plugin SDK) — warning toast, staleness-guarded Confirm, single confirmed resend, never a retry loop. The core picker and the Bots editor now consume the SAME handler; the Bots editor's Confirm resends only the model section with confirm_expensive_model: true. Fixes #95293 (Bots surface remainder).
Bundled plugins
Drop a <name>/plugin.{ts,tsx} here that default-exports a HermesPlugin and
it registers automatically at boot (vite glob in ../contrib/plugins.ts), with
the same inventory + live enable/disable contract as runtime plugins.
Keep this tree for real shipped plugins (and the small authoring fixtures that
dogfood the SDK). One-off demos that rebuild a core chrome piece 1:1 do not
belong here — they double the UI and confuse Settings ▸ Plugins. Publish those
in the companion
hermes-example-plugins
repo instead.
User- and agent-authored plugins load at runtime from
$HERMES_HOME/desktop-plugins/<name>/plugin.js (the disk door) — see the
hermes-desktop-plugins skill.