Lays out Velox Download Manager (IDM-class download manager for Ubuntu 26.04) as a monorepo ready for parallel lane development. No implementation code by design. - docs/: architecture, roadmap M0-M7, IDM-parity GUI spec, engine design, Firefox extension spec, risks/spikes, packaging - contracts/: wire-contract skeleton (JSON Schema + fixture templates) — the single synchronization point between lanes - docs/agents/: one brief per lane (PROTO, CORE, DAEMON, GUI, EXT, PKG/QA) with owned directories, build order and definition of done - CLAUDE.md: rules of engagement — lane ownership, layering, non-negotiables - CMake scaffolding with dev/tsan/release/ci presets Two environment findings shape the design: Firefox here is the Mozilla snap (native-messaging risk, so the extension carries a loopback-WebSocket fallback), and Wayland forbids passive clipboard monitoring (so clipboard capture is explicit-action-first). Co-Authored-By: Claude Opus 5 <[email protected]>
3.8 KiB
Agent brief — EXT (Firefox extension)
Starts the day PROTO freezes the contract. Develops against tools/mockd over the
WebSocket transport — you never wait for veloxd.
You own
extension/**
Read contracts/, docs/. Never write in core/, daemon/, gui/, or nmhost/
(the native host belongs to DAEMON; if you need a change there, file it).
Read first
docs/05-extension-spec.md in full, then docs/06 R1 (snap Firefox) and R3 (AMO).
Your first task is a spike, not code
Spike S1 (2 days, blocks nothing else): on a clean Ubuntu 26.04 VM with snap Firefox,
determine empirically which of the four native-messaging manifest locations actually work,
and whether the launched host can reach $XDG_RUNTIME_DIR. Write
docs/adr/0003-native-messaging-under-snap.md. Then build the WebSocket transport first
regardless of the answer — it is the one that is known to work here
(snap connections firefox shows network/network-bind connected).
Build order
transport/— theTransportinterface,WebSocketTransport(port discovery over 52000–52016 +session.helloverification), pairing flow with token inbrowser.storage.local, reconnect with backoff, thenNativeTransport, thentransport/index.tspicking at runtime with a manual override in Options.capture/headers.ts—onBeforeSendHeadersstash keyed byrequestId, ring buffer, 5-minute TTL, bounded size (a leak here eats the browser's memory).capture/rules.ts—shouldCapture()exactly as specified indocs/05§2. Table-driven tests before implementation. This function is where the bugs will be: too eager and you hijack page navigations; too shy and you're not a download manager.capture/index.ts— theonHeadersReceivedblocking hook: gather cookies, callcapture.offerwith a 750 ms budget,{cancel: true}only ontake. Fail-open is a hard requirement — daemon down, slow, or erroring means Firefox downloads normally. Write that test before the feature.capture/downloads-api.ts— thedownloads.onCreatedsafety net for what slips past.context-menus.ts,popup/(live progress from relayed events, pause/resume, status dot),options/(transport, pairing/unpair, monitored types synced viacapture.getRules, min size, exclusions, default category, bypass modifier).content/media detection —.m3u8/.mpd/MIME sniffing plus aMediaSourceobserver; in-page "Download this video ▾" panel listing variants frommedia.listVariants. The extension never parses manifests — the daemon does. Detect DRM/EME and grey the button out with "Protected content".
Definition of done (M1)
- Intercepts a real download in real Firefox and hands it to
mockd. - Fail-open proven by an automated test: kill the mock mid-flow, the file still downloads through Firefox, no error dialog, no lost download.
- Pairing works, unpair revokes, token survives a browser restart, and a wrong token is rejected and rate-limited.
web-ext lintclean; no remote code, noeval, no CDN script — AMO rejects those.shouldCapturetest table covers: attachment, monitored extension, monitored MIME, size threshold, excluded host, HTML navigation, blob URL, bypass modifier held, streaming media, and a range request the page itself issued.- Popup shows live progress at ≤ 4 Hz without pinning a core.
- Permission justification written and committed for AMO submission.
Do not
- Do not implement any download logic in the extension. You collect URL + headers + cookies and hand them over. That's the whole job.
- Do not add a framework (React/Vue) for a popup and an options page; plain TS keeps the AMO review and the bundle small.
- Do not invent protocol fields — file a request with PROTO.