diff --git a/docs/superpowers/specs/2026-10-05-advanced-context-menu-design.md b/docs/superpowers/specs/2026-10-05-advanced-context-menu-design.md new file mode 100644 index 0000000..38129cb --- /dev/null +++ b/docs/superpowers/specs/2026-10-05-advanced-context-menu-design.md @@ -0,0 +1,219 @@ +# Advanced context menu design + +Status: agreed conversational design, awaiting written-spec review. + +## Purpose and scope + +Preserve today's quick selection action while offering an optional advanced +menu with useful built-in prompts. Adapt the advanced menu to selected text, +links, or the current page. Translation is useful but optional, so it is hidden +until enabled. Firefox Desktop remains the only target. + +This work includes settings migration, contextual menus, dedicated prompts, +translation and truncation dialogs, documentation, and tests. It does not +include custom action editing, full-page extraction, model/effort selection, +omnibox changes, MV3 migration, containers, or automatic submission. + +## Settings and migration + +Replace the existing context-menu checkbox with **Context menu**: + +- **Off:** no extension context menu. +- **Simple:** today's direct **Ask ChatGPT** item, only for selected text. +- **Advanced:** one **Ask ChatGPT** submenu with contextual actions. + +Only the selected menu variant is visible; do not leave the other grayed out. +The keyboard shortcut continues to run the default selection action in every +mode, including Off, and opens a blank chat when no selection is available. + +New settings in the existing sync storage: + +| Key | Values | Default | +| --- | --- | --- | +| `contextMenuMode` | `off`, `simple`, `advanced` | `simple` | +| `showTranslate` | Boolean | `false` | +| `translationMode` | `ask`, `preferred` | `ask` | +| `translationLanguage` | Trimmed free text, maximum 100 Unicode code points | Empty | + +Retain existing temporary-chat, web-search, open-location, and prompt-template +settings. Read the legacy `showContextMenu` key during migration even though it +is no longer in the new defaults. A valid new mode takes precedence; otherwise +legacy false maps to Off and legacy true or absence maps to Simple. A subsequent +save writes the new mode. Invalid stored values fall back safely. + +Advanced mode reveals **Show Translate in advanced menu**, initially unchecked. +When checked, reveal **Translate into** with **Ask each time** and **Preferred +language**. Preferred language reveals a free-text field; it accepts Spanish +or any other language without a fixed language list. Empty preferred language +shows inline guidance and invokes the language dialog rather than constructing +an incomplete prompt. Turning a feature off hides its controls but retains its +preferences. Restore defaults resets all extension settings, including these, +without changing Firefox's engine settings or keyboard shortcut. + +## Context selection and menu layout + +Choose one group for each opening, in this priority order: + +1. Nonempty selected text, including selection inside a link. +2. A clicked link when there is no selection. +3. Page background when there is no selection or link. + +Do not add special image, video, password-field, or browser-chrome actions. +Native editable-field behavior must be checked in Firefox before claiming it +is supported. Use menu event data for selection and URLs; no background page +scraping or automatic navigation to the linked site. + +| Context | Children, in order | +| --- | --- | +| Selection | Ask normally; separator; Explain; Summarize; Debug code; Translate when enabled | +| Link | Ask about this link; Review link safety | +| Page | Ask about this page; Summarize this page | + +The selection presets are always present in Advanced mode except Translate. +Do not infer whether text is code. Debug code appears for any selection and +the user decides when it applies. With a valid preferred language, label the +translation item **Translate to Spanish** (substituting the user's language); +otherwise use **Translate…**. Escape menu-label access-key characters in +user-supplied language names so the displayed text remains literal. + +Use Firefox menu visibility updates when the menu opens to enforce precedence, +then refresh the native menu. Serialize registration and settings updates, as +the existing implementation does. Validate click data again before launching; +visibility is not input validation. + +## Prompt behavior + +**Ask normally** and the keyboard shortcut apply the user's existing prompt +template. Every other action uses its own dedicated prompt without appending +or wrapping it in that template. All actions respect the existing open-location, +temporary-chat, and web-search preferences. Hints retain their existing +best-effort status. The address-bar search provider is unchanged. + +Dedicated prompts should express these instructions, followed by a clearly +labeled source block: + +| Action | Instructions | +| --- | --- | +| Explain | Explain the selected text clearly, defining unfamiliar terms. | +| Summarize | Summarize the selected text, preserving its main points and qualifications. | +| Debug code | Identify likely problems and suggest fixes; explain the reasoning and ask for missing context when necessary. | +| Translate | Translate the selected text into the specified language, preserving meaning and formatting where practical. | +| Ask about link/page | Help the user understand the supplied URL, ask what they would like to know, and say if its content cannot be accessed. | +| Review link safety | Review suspicious indicators and available evidence; distinguish URL inspection from checks actually performed, state uncertainty, and do not guarantee that the link is safe. | +| Summarize page | Summarize the content at the URL; if it cannot be accessed, say so and ask the user to supply the text rather than inventing a summary. | + +Source text and URLs are data, not extension instructions. Explicit framing +helps communicate this but is not a security boundary. Users still review and +submit in ChatGPT; no auto-submit or internal ChatGPT request modification. + +Link/page actions share the relevant URL only, without reading page text or +adding titles. Accept only HTTP(S) URLs. Reject malformed URLs, URLs containing +embedded username/password credentials, and unsupported schemes with a clear +message. Preserve accepted URLs intact, including their query/fragment rather +than silently changing the destination. Documentation must explain that URLs +can contain private information and are sent to ChatGPT by the chosen action. + +## Translation and other dialogs + +Use a packaged extension dialog window, not a JavaScript prompt injected into +the source page. Reuse one small dialog surface for language entry, truncation +confirmation, and actionable errors, with appropriately distinct copy. + +For Ask each time, Translate focuses the language input. Enter with a nonempty +trimmed language continues; Escape, Cancel, or closing the window cancels. +The one-time language choice does not silently change the saved preference. +Preferred language bypasses this dialog when valid. + +Do not put selected text or source URLs in the dialog URL or persistent/sync +storage. Use an opaque request identifier and extension-internal messaging to +transfer the pending action. Scope requests to their dialog, allow concurrent +requests without mixing data, and release them on completion or cancellation. +Keep the nonpersistent background lifecycle in mind: do not depend on a global +Map surviving while the user types. Transfer the snapshot to the dialog through +an initial handshake while the launch handler is active; after acknowledgment, +the dialog owns its in-memory snapshot and can complete the launch itself. +If initialization fails or context is lost, show a retry message and never send +partial or mismatched input. Do not persist pending selections to survive a +browser restart. Disable Continue while launching to prevent duplicate tabs. + +Capture the action, selected source, and settings together so later tab changes +or preference updates do not alter an already-open dialog's operation. If the +dialog window cannot open, attempt the same extension page in a tab. Launch +failures within the dialog remain visible and allow retry or cancellation. + +## Length limits and launch behavior + +Retain the current 8,000-character serialized URL budget. Preserve dedicated +instructions and language in full; shorten only selected source text, on Unicode +code-point boundaries with a whitespace boundary where practical. Include any +shortening marker in the budget calculation. If even the instructions cannot +fit, explain the problem instead of emitting a misleading prompt. + +When selected text must be shortened, show a brief confirmation before opening +ChatGPT, with **Continue with shortened text** and **Cancel**. This applies to +Simple, Advanced, and the keyboard shortcut so they share one launch contract. +For Translate with Ask each time, calculate the final budget after language +entry and present confirmation in the same dialog if needed. Never truncate a +link/page URL: explain that it is too long and stop that action. + +On successful continuation, reuse new-tab, background-tab, and new-window +behavior, including the existing new-window failure fallback to a tab. Close +the dialog after a successful launch. Direct-launch failures should use the +same error surface when it remains available; avoid silent success messages. + +## Code boundaries + +- Pure modules under `lib/` own action definitions, prompt assembly, context + selection, settings validation/migration, and budget calculations. No browser + APIs in these modules. +- The background owns Firefox menu registration/events and entry-point routing. +- A shared browser-facing launch helper owns tab/window opening and fallback. +- The packaged dialog owns input, confirmation, and its pending action after + transfer; it uses the same pure prompt and URL logic as direct launches. +- Options remain inline in `about:addons` and use existing visual styles. + +Preserve the current `storage`, `menus`, and `activeTab` permissions. No new +host permissions, telemetry, intermediary service, runtime dependency, or API +key is part of this design. Re-read the original options design and Appendix B +before any proposed permission or submission change. A discovered inability +to meet this constraint requires revisiting the design, not silently adding +permissions. + +## Verification and documentation + +Meaningful unit tests cover legacy migration/new-key precedence, invalid +settings, context precedence, literal source substitution, dedicated-template +isolation, language validation, URL validation, and encoded-length boundaries. +Verify that long source truncation preserves instructions and that URLs are +never partially sent. Test dialog state transitions and cancellation/duplicate +submission behavior at browser boundaries where feasible. + +Run `npm test` with a nonzero test count. Inspect the built ZIP: include the +dialog assets; exclude `test/` and `docs/`, including empty directory entries. + +Manual Firefox checks: +- Off/Simple/Advanced updates immediately and persists; legacy users retain mode. +- Selection, linked selection, bare link, and page background show the correct + group with no duplicate or disabled alternate root. +- All actions construct the intended prompts; keyboard shortcut remains default. +- Translation visibility, preferred language, blank preferred fallback, Enter, + Escape, Cancel, and closing the dialog behave as specified. +- Concurrent dialogs, source-tab changes, background idle/wakeup, and failed + dialog initialization do not mix or silently lose selections. +- Long selected text requires consent; oversized/unsupported URLs do not launch. +- Tab/window preferences and failure fallback work from direct and dialog paths. +- Settings/dialogs work in light/dark themes, narrow layouts, and by keyboard. +- Run the existing AGENTS.md frame-focus and restricted-page shortcut checks. + +Update README, changelog, and privacy text for menu modes, presets, URL sharing, +translation, and truncation. Remove the unsuccessful temporary model/effort +URL-test controls as part of release cleanup. Do not promise that ChatGPT can +access every supplied URL or perform a definitive security audit. + +## Review outcome + +The design separates selection text from whole URLs in its length handling, +keeps translation opt-in, preserves legacy menu behavior, and leaves Firefox's +search provider and shortcut ownership unchanged. The next step after written +spec approval is an implementation plan; this document authorizes no additional +features beyond the agreed scope.