From c2a1134d56a901076632a866d5a0fbfbb7f0f2a9 Mon Sep 17 00:00:00 2001 From: Ally Founder Date: Tue, 11 Aug 2026 16:47:11 -0400 Subject: [PATCH] docs: add RosePlugs design spec --- .../specs/2026-08-11-roseplugs-design.md | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 docs/superpowers/specs/2026-08-11-roseplugs-design.md diff --git a/docs/superpowers/specs/2026-08-11-roseplugs-design.md b/docs/superpowers/specs/2026-08-11-roseplugs-design.md new file mode 100644 index 0000000..d0236fc --- /dev/null +++ b/docs/superpowers/specs/2026-08-11-roseplugs-design.md @@ -0,0 +1,123 @@ +# RosePlugs — design spec + +## Purpose + +A new Revenge/Vendetta plugin that gives Rosie's own plugins a home of their own in +Discord's Settings, instead of leaving them buried inside Revenge's generic Plugins +list. Adds a new top-level settings section titled **"Rosie's Plugs"**, whose first +row is a quick-install browser for Rosie's plugins, followed by a direct settings +shortcut for each of Rosie's plugins that's currently installed. + +Explicitly separate from the existing private "RP Admin" plugin. RP Admin will +eventually be migrated to live inside this section too, but that's a future, +separate task — not part of this build. + +## Non-goals + +- Does not touch, hide, or replace Revenge's own "Plugins" management screen + (enable/disable/uninstall stays there). +- Does not manage plugins by other authors — only plugins whose manifest lists + "Rosie" as an author. +- No in-browser uninstall for v1 — that stays a one-tap trip to Revenge's own + Plugins screen. + +## Architecture + +RosePlugs is fully self-contained. No changes to any of the other ~20 plugins in +this repo. Two independent patch mechanisms, both variations on the +`SETTING_RENDERER_CONFIG` / `createList` pattern already live-verified and shipping +in Raiden's Themes (`plugins/raidens-themes/src/patches/settings.ts`): + +1. **New top-level section.** Raiden's Themes appends a row into the *existing* + "Revenge" section's `settings` array. RosePlugs instead inserts a whole new + section object — `{ label: "ROSES_PLUGS", title: "Rosie's Plugs", settings: [...] }` + — into `config.sections` itself, as a sibling of the "Revenge" section rather than + a row inside it. Same array, same object shape; confirmed directly against the + Revenge client source at `/root/repos/revenge-bundle` (`core/ui/settings/pages/...`), + not inferred from behavior alone. Patches both surfaces Raiden's Themes patches + (the mobile list via `createList`, and the tablet/desktop panel via + `renderTitle`/`sections`, with the same defensive try/catch since that second + surface may not exist on a given build). + +2. **Auto-discovering Rosie's other installed plugins.** At render time, reads + `@vendetta/plugins`' `plugins` record (every installed plugin, keyed by id), + filters to entries whose `manifest.authors` includes "Rosie", excludes RosePlugs + itself, and adds one settings row per remaining plugin that actually exports + settings. Opening that row calls the plugin's own `getSettings(id)` — the same + generic Vendetta API Revenge's own plugin browser uses. Nothing to maintain here + when a new plugin ships under Rosie's name; it appears automatically next time + Settings is opened. + +Rejected alternative: having each of the 20 plugins explicitly register itself with +RosePlugs (a shared call added to each plugin's `index.ts`). Rejected because +`manifest.authors` + `getSettings` already provides everything needed generically, +and touching 20 already-shipping files for no functional gain is unnecessary risk. + +## Components + +- `src/index.ts` — plugin entry, wires the two patches on load, cleans up on unload. +- `src/patches/settings.ts` — the section-insertion + row-injection patch, adapted + from Raiden's Themes' `patches/settings.ts` (new-section insertion instead of + row-append; adds the discovery loop over `@vendetta/plugins`). +- `src/patches/discoverPlugins.ts` — builds the list of Rosie-authored installed + plugins (id, manifest, `getSettings` result) from the `@vendetta/plugins` API. +- `src/ui/PluginsBrowser.tsx` — the "Plugins" screen: fetches, caches, and renders + the categorized quick-install list. +- `src/ui/PluginDetailSheet.tsx` — the per-plugin detail/install action sheet shown + on row tap. +- `src/lib/nexusApi.ts` — fetch + in-memory cache of + `https://rp.jarviscli.dev/plugins-data.json`. +- `src/ui/Settings.tsx` — RosePlugs' own minimal settings screen (short description + + a "refresh plugin list" button that busts the cache in `nexusApi.ts`). + +## Data flow + +1. Settings screen opens → RosePlugs' `createList`/panel patch runs → inserts the + "Rosie's Plugs" section with a "Plugins" row plus one row per installed + Rosie-authored plugin with settings. +2. Tapping "Plugins" navigates to `PluginsBrowser`, which calls `nexusApi.ts` (cached + after first fetch this session) and renders plugins grouped by `category`, each + row showing name, tagline, and a status badge when status isn't the default. +3. Tapping a plugin row opens `PluginDetailSheet` with the full tagline/status note + and an Install button (or an "Installed" indicator if already present in + `@vendetta/plugins`' `plugins` record). +4. Install calls `installPlugin(installUrl)` from `@vendetta/plugins` directly — no + deep link needed, confirmed against the Revenge client source. The row reflects + loading → installed/error state. +5. Tapping one of the per-plugin settings rows back in the main section calls that + plugin's `getSettings(id)` and navigates to the result, same as Revenge's own + plugin browser does internally. + +## Error handling + +- `nexusApi.ts` fetch failure: `PluginsBrowser` shows an inline error state with a + retry button. Scoped to that one screen — it can't affect the main Settings list, + since it only runs after navigating into "Plugins." +- Missing/unavailable `SETTING_RENDERER_CONFIG` or `createList` module: patch + function logs a warning and returns without throwing, matching Raiden's Themes' + existing defensive style. +- A Rosie-authored plugin with a broken `getSettings` (throws on render): not + specially guarded beyond React's own error boundary at the settings-screen level — + consistent with how Revenge's own plugin browser handles the same case today. + +## Testing / live verification + +Standard for this repo: build, deploy, purge cache, then live-verify via +revenge-devtools before considering any part done: + +- "Rosie's Plugs" section appears in Settings, in the right position, with the + right title. +- "Plugins" row opens the browser; data is real and categorized correctly; status + badges match the live JSON. +- Installing a not-yet-installed plugin actually installs it and the row updates. +- An already-installed Rosie-authored plugin shows a settings row that opens the + correct screen. +- No regression to Revenge's own Plugins screen or to any other installed plugin's + settings. + +## Manifest + +- id: `rose-plugs` +- name: `RosePlugs` +- author: `Rosie` +- section label/title: `Rosie's Plugs`