Files
kandev/docs/plans/plugin-shortcut-settings/plan.md
T
2026-09-04 17:38:05 +00:00

8.2 KiB

created, status, requirements, system_design, legacy_specs
created status requirements system_design legacy_specs
2026-09-04 complete
REQ-PLUGINS-PLUGIN-SHORTCUT-SETTINGS-001
../../specs/plugins/system-design/plugin-shortcut-settings.md

Implementation Plan: Plugin Shortcut Settings

Overview

Move dynamic plugin shortcut editors out of Preferences > Keyboard Shortcuts and into each plugin's detail page while preserving the existing per-user override map, shared Save behavior, full conflict comparison, and dispatch rules. Implement the vertical frontend behavior and its desktop/member/mobile evidence first, then reconcile the public plugin references with the shipped location.

The plugin system owns this plan because manifest-declared keybindings and their namespaced overrides are plugin contracts. The UI system supplies the existing save coordinator and responsive settings shell without taking ownership of the plugin behavior.

Scope

In scope

  • Render Kandev-owned shortcuts only on the global keyboard-shortcuts page.
  • Render one selected plugin's declared shortcuts on that plugin's detail route for members and administrators.
  • Preserve namespaced portable overrides, draft/reset/clear semantics, conflict warnings, core precedence, and inactive-plugin behavior.
  • Keep the phone flow within the existing direct plugin detail route, with touch-usable controls and no page-level horizontal overflow.
  • Update user-facing plugin docs, the manifest reference, and the maintained frontend plugin API contract to name the new configuration location and permission split.

Out of scope

  • Backend, manifest-schema, plugin SDK, registry, or shortcut-dispatch changes.
  • A new Settings route, drawer, plugin shortcut search index, or plugin-list shortcut badge/count.
  • Changing access to plugin-authored settings, plugin config, or lifecycle actions.
  • Cleaning up stored shortcut overrides during uninstall.
  • Updating the core keyboard-shortcuts documentation screenshot, which remains accurate as a core-only settings view.

Technical approach

Core and plugin shortcut presentation

Keep KeyboardShortcutsSettings responsible for the chat-submit preference and the Kandev shortcut draft. Continue loading plugin declarations there only so core rows can report cross-source conflicts. Refine KeyboardShortcutsCard so its rendered entries are always CONFIGURABLE_SHORTCUTS, while its conflict input can still include every plugin entry.

Add a plugin-focused shortcut settings component under apps/web/components/settings/plugins/. It receives the selected plugin and complete installed plugin list, filters visible entries to the selected owner, and reuses the current recorder and conflict-label logic. Place it outside PluginDetail's canManage block, after operator configuration and before the manifest card. Do not render it for a plugin without parseable keybindings. When an active bundle replaces the exact plugin detail route, wrap its content and append the same host-owned card so the supported route and keybinding capabilities remain composable.

Persistence and permissions

Register a route-local plugin-shortcuts:{pluginId} save contributor. Its draft contains the existing complete StoredShortcutOverrides map and saves through updateUserSettings({ keyboard_shortcuts: ... }); it never calls the plugin configuration endpoint. Synchronize the baseline after initial hydration and later portable-settings updates, rebase local changes onto the newest complete map at save time, reject stale response authority, and preserve edits made while the request is pending. Preserve the existing namespaced keys so no migration or dispatcher change is needed. When an administrator changes both plugin config and a personal shortcut, the shared coordinator owns partial success, retry, discard, and navigation protection across the two contributors.

Responsive composition

Reuse the existing direct phone path demonstrated by mobile-plugin-settings-row.spec.ts: Settings navigation sheet > Plugins > full plugin row > detail page. Keep the card inline rather than introducing a drawer. On narrow/coarse-pointer layouts, let shortcut rows stack as needed, give recorder/reset/clear controls a 44 px active dimension, retain the page's single vertical scroll owner, and assert no document horizontal overflow. Desktop keeps the denser inline row arrangement.

Copy and documentation

Add localized, self-documenting copy explaining that plugin shortcuts are personal and only run while the plugin is active. Update English, Portuguese, Simplified Chinese, and generated Traditional Chinese catalogs, plus the pseudo-locale through the existing scripts.

Update docs/public/plugins.md, docs/public/plugins-manifest.md, and docs/public/plugins-authoring.md, whose dominant types remain explanation, reference, and how-to respectively. Reconcile the maintained docs/plans/plugins/PLUGIN-API.md contract comment. No public screenshot currently shows plugin rows on the core page, so no image replacement is required.

Tests

  • apps/web/components/settings/keyboard-shortcuts-card.test.tsx proves the global card renders core entries only while still reporting a conflict with a plugin binding.
  • A focused plugin-shortcut card test under apps/web/components/settings/plugins/ proves selected-owner rendering, no empty card, draft/reset behavior, and shortcut-only persistence without a plugin-config mutation.
  • apps/web/src/settings-routes.plugin.test.ts proves an exact plugin detail route replacement retains both the plugin-owned content and host shortcut surface.
  • apps/web/lib/keyboard/plugin-shortcuts.test.ts and apps/web/lib/keyboard/shortcut-conflicts.test.ts preserve entry identity, labels, defaults, and core/plugin comparison behavior.
  • apps/web/hooks/use-plugin-shortcuts.test.ts remains targeted regression evidence that the relocated override still dispatches and core bindings win.

E2E tests

  • Extend apps/web/e2e/tests/auth/plugin-settings-member.spec.ts for AC-PLUGINS-PLUGIN-SHORTCUT-SETTINGS-001.1 through .5: install as an administrator, sign in as a member, prove the plugin recorder is absent from the global page and present on the plugin detail page while operator controls remain hidden, then save and reload the member's override.
  • Extend apps/web/e2e/tests/plugins/mobile-plugin-settings-row.spec.ts for AC-PLUGINS-PLUGIN-SHORTCUT-SETTINGS-001.6 and .7: enter through the existing full-card tap after disabling the fixture plugin, edit and save its shortcut, reload, and verify touch geometry, internal vertical scrolling, and zero document horizontal overflow. Capture and restore the persisted shortcut baseline so the worker does not leak settings state.

Both scenarios must be written and observed failing for the old placement before the production UI changes are made.

Work orders

Verification results

  • Task 01 targeted unit, typecheck, lint, i18n, E2E sleep-ratchet, authenticated member E2E, and mobile E2E checks passed.
  • Task 02 scoped documentation searches, public-doc tests/validation, and whitespace checks passed.
  • Review remediation removed unrelated generated locale churn and covered the exact-root plugin settings-route compatibility path.
  • Review remediation rebased shortcut drafts across hydration, live settings updates, and in-flight saves, and made both persistence E2E scenarios await the successful settings response before reload.

Risks

  • The plugin detail page currently groups its configuration UI under an administrator gate; placing the new personal card inside that block would silently remove member access.
  • Separating rendered lists can accidentally narrow conflict detection to the visible page and hide core-versus-plugin or plugin-versus-plugin collisions.
  • Saving still uses the complete-map backend contract, so the contributor must continue rebasing its local delta onto the latest authoritative store map.
  • Mobile recorder rows currently use compact desktop geometry and need an explicit narrow/coarse-pointer composition to avoid clipped actions.