Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
5398e5a
feat(coordinator): deferred status, applyDefer, MAX_OPEN_TABS ceiling…
DustinVK Jul 1, 2026
768d1d3
docs: carry Slice-1 review findings into sidebar-nav plan
DustinVK Jul 1, 2026
508e6da
feat(types): sidebar/challenge messages + broker search.guidance; mov…
DustinVK Jul 1, 2026
4a79712
docs: add missing 'done' view to sidebar-nav §3 (gap A); note resting…
DustinVK Jul 1, 2026
fa1dc0f
feat(sidebar): pure SidebarView state machine + types
DustinVK Jul 1, 2026
b373bc1
docs: add sticky-view contract to sidebar-nav §5 (Slice-3 review)
DustinVK Jul 1, 2026
6bf6270
feat(content): strip overlay to headless challenge reporter
DustinVK Jul 1, 2026
4889191
docs: challenge flag clears on on-host navigation (Slice-4 review)
DustinVK Jul 1, 2026
057f878
feat(bg): pin run to window (windowId)
DustinVK Jul 1, 2026
55f7d0a
feat(bg): sidebar view plumbing + challenge flag
DustinVK Jul 1, 2026
913ba8e
feat(bg): focus-driving, DEFER, verdict-close
DustinVK Jul 1, 2026
83fd2c6
refactor(bg): remove reinject/PING/GET_ITEM; resume handling
DustinVK Jul 1, 2026
9b33823
fix(challenge): report state per-load; drop onUpdated clear misfire
DustinVK Jul 1, 2026
46502a4
feat(bg): FOCUS_ITEM + promoteToOpen; start-run view push
DustinVK Jul 1, 2026
1de0829
feat(build): sidebar_action manifest + build entry; drop dead scripti…
DustinVK Jul 1, 2026
87a7179
feat(sidebar): checklist UI over deriveView + transient states
DustinVK Jul 1, 2026
8442273
feat(popup/options): open sidebar on Start; remove Restore-overlay; s…
DustinVK Jul 1, 2026
4861a6b
docs: mark sidebar-nav §1-§7 done; Decision A; progress doc overlay→s…
DustinVK Jul 1, 2026
2c37c54
chore(manifest): drop unused webNavigation permission
DustinVK Jul 1, 2026
7dc112d
fix(sidebar): carry focusId in revisit view (button no longer races l…
DustinVK Jul 1, 2026
1de71e4
fix(privacy): self-host fonts; stop loading from Google CDN
DustinVK Jul 1, 2026
0fa2370
fix(sidebar): don't auto-open on install (open_at_install: false)
DustinVK Jul 1, 2026
226721b
feat(popup): re-open the sidebar via a Show scan panel button
DustinVK Jul 1, 2026
47f7c3d
fix(bg): refresh sidebar on Stop / Delete-all (external run mutations)
DustinVK Jul 1, 2026
a1c4b4c
feat(sidebar): honest `stopped` view distinct from `done`
DustinVK Jul 1, 2026
ce367e8
docs: Q-015 empirically confirmed — double gesture works in Firefox 140
DustinVK Jul 1, 2026
d39a1b6
fix(sidebar): confirm verdict ACK before showing recorded (retry on f…
DustinVK Jul 1, 2026
74d99da
fix(sidebar): scope the checklist to the run's window (clear on no-run)
DustinVK Jul 1, 2026
b088188
fix(bg): guard handleVerdict against re-verdicting a recorded item (n…
DustinVK Jul 1, 2026
23233ce
fix(sidebar): warn on off-host paste + navigate the item's own tab
DustinVK Jul 1, 2026
9f7380e
test(sidebar): prove the off-host paste-warning DOM path; make it mor…
DustinVK Jul 1, 2026
a5639d7
fix(sidebar): offsite view — no verdict controls off the broker's host
DustinVK Jul 1, 2026
a7a6cc2
fix(sidebar): keep transient latch through the recorded animation
DustinVK Jul 1, 2026
6b39949
test: exclude sidebar/index.ts entrypoint from coverage; cover state.…
DustinVK Jul 1, 2026
e4eb87d
wherefore capture
DustinVK Jul 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion build.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as esbuild from 'esbuild';
import { copyFileSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
import { copyFileSync, cpSync, mkdirSync, readFileSync, writeFileSync } from 'fs';

const watch = process.argv.includes('--watch');

Expand All @@ -20,6 +20,8 @@ const entries = [
{ entryPoints: ['src/popup/style.css'], outfile: 'dist/style.css' },
{ entryPoints: ['src/options/index.ts'], outfile: 'dist/options.js' },
{ entryPoints: ['src/options/style.css'], outfile: 'dist/options.css' },
{ entryPoints: ['src/sidebar/index.ts'], outfile: 'dist/sidebar.js' },
{ entryPoints: ['src/sidebar/style.css'], outfile: 'dist/sidebar.css' },
];

function copyStatics() {
Expand All @@ -28,6 +30,11 @@ function copyStatics() {
writeFileSync('dist/manifest.json', manifest);
copyFileSync('src/popup/index.html', 'dist/popup.html');
copyFileSync('src/options/index.html', 'dist/options.html');
copyFileSync('src/sidebar/index.html', 'dist/sidebar.html');
// Self-hosted fonts: fonts.css is loaded by all three surfaces; its url()s resolve to
// dist/fonts/*.woff2 (copied verbatim — not bundled, so esbuild never touches the woff2).
copyFileSync('src/styles/fonts.css', 'dist/fonts.css');
cpSync('src/styles/fonts', 'dist/fonts', { recursive: true });
}

if (watch) {
Expand Down
11 changes: 8 additions & 3 deletions manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@
"default_popup": "dist/popup.html",
"default_title": "expurge"
},
"permissions": ["storage", "tabs", "downloads", "scripting", "webNavigation"],
"sidebar_action": {
"default_panel": "dist/sidebar.html",
"default_title": "expurge",
"open_at_install": false
},
"permissions": ["storage", "tabs", "downloads"],
"host_permissions": [
"*://updates.expurge.dev/*"
],
Expand All @@ -38,9 +43,9 @@
}
},
"_notes": {
"webNavigation": "In permissions for background webNavigation.onErrorOccurred (load-error skipping). Not yet wired in background/index.ts — implement when adding M9 brokers.",
"webNavigation": "Removed — was reserved for background webNavigation.onErrorOccurred (load-error skipping) but never wired. Re-add to permissions when M9 wires webNavigation.onErrorOccurred.",
"host_permissions_update_server": "updates.expurge.dev: confirm subdomain before M7 ships. Background fetch needs host_permissions (not optional) to bypass CORS without user consent. If URL changes, update here.",
"m9_new_brokers": "Each new broker domain needs TWO entries: (1) optional_host_permissions so browser.permissions.request() can offer it at run start; (2) content_scripts.matches so the overlay injects. Both are required — either alone does not work.",
"m9_new_brokers": "Each new broker domain needs TWO entries: (1) optional_host_permissions so browser.permissions.request() can offer it at run start; (2) content_scripts.matches so the headless challenge reporter injects (challenge detection). Both are required — either alone does not work. Verdict UI lives in the window-level sidebar (sidebar_action), which needs no per-domain entry.",
"m8_no_new_permissions": "Persistence opt-ins (M8) use storage.local only — no new permissions needed.",
"firefox_ignores_underscore_keys": "Firefox logs a warning for unknown top-level keys but loads the extension. Remove _notes before AMO submission if it causes review friction."
}
Expand Down
27 changes: 18 additions & 9 deletions plan/expurge-progress.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,24 @@ sections, redesigned popup (run-control-panel only). No persistence opt-ins.
The popup currently contains the profile form and draft surfaces. Per the design interview,
these move to the options page in M4+. The popup becomes a compact run control panel only.

### Planned: overlay → sidebar migration (decided 2026-07-01, not yet built)

The shipped in-page shadow-DOM overlay (`src/content/index.ts`) and its Restore-Overlay /
PING / reinjection machinery are slated for replacement by a Firefox native **sidebar** — a
persistent run-wide checklist that drives navigation. Adds a first-class `deferred` work-item
state, a `MAX_OPEN_TABS=15` ceiling, per-broker `search.guidance`, and shrinks the content
script to a headless challenge reporter. Full plan in **`plan/sidebar-nav.md`**; rationale in
wherefore `2026-07-01-sidebar-run-navigation` (resolves Q-013, opens Q-015). The `content` /
`popup` / `background` rows above document the **current** overlay build, not the target.
### Done: overlay → sidebar migration (decided + built 2026-07-01)

The in-page shadow-DOM overlay was **replaced by a Firefox native `sidebar_action`** — a
persistent, window-level run-wide checklist that drives navigation itself. Beyond what the
per-tab overlay could do, the sidebar adds an **interactive checklist** (grouped In progress /
Waiting / Done; click any non-terminal row to jump to that tab) and an always-available
**Defer** control. The migration also added a first-class `deferred` work-item state, a
`MAX_OPEN_TABS=15` ceiling, per-broker `search.guidance`, a shared `progressOf`/`isComplete`
definition, and shrank the content script to a **headless challenge reporter** (no UI, ~45
lines). The reinjection machinery (Restore-Overlay / PING / `reinjectIfMissing` / `GET_ITEM`)
is gone, and the dead `scripting` permission was dropped.

View truth lives in one pure function, `deriveView` (`src/sidebar/state.ts`); the background
builds its inputs and pushes `SIDEBAR_UPDATE`, and the sidebar renders without re-deriving.
Full plan (§-by-§ with commit refs) in **`plan/sidebar-nav.md`**; rationale in wherefore
`2026-07-01-sidebar-run-navigation` (resolves Q-013; Q-015 pending empirical Firefox check).
The `content` / `popup` / `background` rows above describe the **pre-migration** build and are
superseded by the sidebar architecture — see `sidebar-nav.md` for the current shape.

---

Expand Down
Loading
Loading