Files
vdm/docs/agents/AGENT-EXT.md
T
samiandClaude Opus 5 8bb683b09d scaffold: project structure, wire contract, roadmap and agent briefs
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]>
2026-09-09 18:21:11 +04:00

3.8 KiB
Raw Blame History

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

  1. transport/ — the Transport interface, WebSocketTransport (port discovery over 5200052016 + session.hello verification), pairing flow with token in browser.storage.local, reconnect with backoff, then NativeTransport, then transport/index.ts picking at runtime with a manual override in Options.
  2. capture/headers.tsonBeforeSendHeaders stash keyed by requestId, ring buffer, 5-minute TTL, bounded size (a leak here eats the browser's memory).
  3. capture/rules.tsshouldCapture() exactly as specified in docs/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.
  4. capture/index.ts — the onHeadersReceived blocking hook: gather cookies, call capture.offer with a 750 ms budget, {cancel: true} only on take. Fail-open is a hard requirement — daemon down, slow, or erroring means Firefox downloads normally. Write that test before the feature.
  5. capture/downloads-api.ts — the downloads.onCreated safety net for what slips past.
  6. context-menus.ts, popup/ (live progress from relayed events, pause/resume, status dot), options/ (transport, pairing/unpair, monitored types synced via capture.getRules, min size, exclusions, default category, bypass modifier).
  7. content/ media detection.m3u8/.mpd/MIME sniffing plus a MediaSource observer; in-page "Download this video ▾" panel listing variants from media.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 lint clean; no remote code, no eval, no CDN script — AMO rejects those.
  • shouldCapture test 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.