The spec prescribed replaceAll's string form and the plan hard-coded it,
so the $-substitution defect originated in the design documents rather
than in execution. Both now specify the function replacer.
Also replaces the spec's frame-reporting idea with the document.hasFocus()
gate that shipped; frame provenance was only ever needed for auto-submit,
which Appendix B rejects.
The plan pinned strict_min_version to 112.0 for the ES-module background
floor, but the existing data_collection_permissions key requires Firefox
140 desktop / 142 Android, so addons-linter warned and warningsAsErrors
failed the build. Measured: 112.0 -> 2 warnings, 140.0 -> 1, 142.0 ->
clean, omitted -> clean. 142.0 was rejected because it locks out ESR 140.
Omitting excludes nobody and degrades gracefully below 112.
Also syncs the plan's background.js block with the rejection guards added
in 22fc754, and reworks two of those comments for clarity.
Two verification passes, driving real Firefox 153.0.1 under Xvfb rather than
reading docs, changed several load-bearing decisions.
Added back: the keyboard shortcut now acts on selected text. activeTab adds
no install-prompt line (confirmed by running Firefox's own
formatPermissionStrings: ["activeTab","storage","menus"] yields msgs: []),
and ext-commands.js grants activeTab before firing onCommand. Records the
three failure shapes of executeScript, one of which resolves silently to
[null] on parent-process about: pages, and that commands.getAll() reports a
suggested_key as registered even when Firefox has silently overridden it.
Rejected with evidence, in Appendix B: auto-submitting the prompt. The
scheme authenticated navigation provenance when auto-submit needs text
provenance, and a hostile page can smuggle ~16 KB of invisible instructions
into info.selectionText. webNavigation.transitionType is not a security
boundary either -- the marker is consumed on commit, so an uncommitted
urlbar navigation leaves it armed for the next navigation to inherit
(demonstrated at 10.47s), and its freshness guard is dead code. Prefill-only
keeps the human checkpoint that makes the context menu safe.
Also rejected: a bundled extension page as search_url (Firefox refuses to
install), and browser.omnibox -- which works and needs no permissions, but
moves the transmitter of search terms from Firefox to extension code, the
change that puts data_collection_permissions ["none"] at risk. Declined to
minimise AMO exposure.
New Risk 6 records the residual AMO question and that it should be asked
before submission, since a forced searchTerms declaration would add the
install line this design exists to avoid.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Design for an options panel reachable from about:addons, configuring a
context-menu entry on selected text and an Alt+Shift+G shortcut. Adds
storage and menus permissions only, both in Firefox's no-prompt class, so
the install dialog gains no lines and data_collection_permissions stays
"none". The gpt <query> search provider is deliberately untouched.
Technical claims were verified rather than assumed: MV2 background
type:"module" works from Firefox 112 (tested in 153.0.1), so no background
HTML shim is needed; package.json needs "type":"module" or node --test
fails on Node 22.0-22.6; the ChatGPT model/hints/temporary-chat params are
undocumented and unreliable, so every label is written at hint strength.
q= no longer auto-submits, only prefills.
Also excludes docs/ and test/ from the packaged ZIP. Verified: without
this the spec doc itself shipped inside the extension, and a bare glob
alone leaves empty directory entries behind.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>