docs: add dispatch prompts and correct the toolchain survey
- docs/agents/PROMPTS.md: six copy-paste agent prompts, wave ordering (PROTO + PKG/QA first, the other four at contract freeze) and the git worktree commands - Correct the bootstrap section: an earlier check ran with a restricted PATH and wrongly reported the machine as bare. git 2.53, CMake 4.2.3, g++ 15.2, ninja, Qt 6 dev, libcurl, SQLite, nlohmann-json, ffmpeg and clang-format/tidy are all present; only libqt6svg6-dev, libsecret-1-dev, nodejs/npm and clang are missing. Flag that CMake 4.x rejects cmake_minimum_required below 3.5. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -32,6 +32,8 @@ Start here:
|
|||||||
|
|
||||||
Per-lane briefs live in [docs/agents/](docs/agents/) — one per agent, each with an owned
|
Per-lane briefs live in [docs/agents/](docs/agents/) — one per agent, each with an owned
|
||||||
directory list, a definition of done, and the files it must never touch.
|
directory list, a definition of done, and the files it must never touch.
|
||||||
|
**To dispatch the agents, use [docs/agents/PROMPTS.md](docs/agents/PROMPTS.md)** — six
|
||||||
|
copy-paste prompts plus the worktree commands and the wave order.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,390 @@
|
|||||||
|
# Dispatch prompts
|
||||||
|
|
||||||
|
Copy-paste one prompt per agent session. Each is self-contained.
|
||||||
|
|
||||||
|
## Dispatch order — this matters
|
||||||
|
|
||||||
|
```
|
||||||
|
WAVE 1 (start now, in parallel) WAVE 2 (start at contract freeze)
|
||||||
|
┌──────────────┐ ┌──────────────┐ ┌──────┐ ┌────────┐ ┌─────┐ ┌─────┐
|
||||||
|
│ PROTO │ │ PKG/QA │ │ CORE │ │ DAEMON │ │ GUI │ │ EXT │
|
||||||
|
│ the contract │ │ build + CI + │ └──────┘ └────────┘ └─────┘ └─────┘
|
||||||
|
│ is the │ │ testserver │ all four run fully in parallel
|
||||||
|
│ blocker │ │ │ and never block each other
|
||||||
|
└──────────────┘ └──────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**Do not start Wave 2 before PROTO announces the freeze.** Four agents guessing at the
|
||||||
|
protocol is precisely the failure this structure exists to prevent. PKG/QA runs in Wave 1
|
||||||
|
because CORE's definition of done is written against `tools/testserver`, which PKG/QA
|
||||||
|
builds.
|
||||||
|
|
||||||
|
## Running each lane in its own worktree
|
||||||
|
|
||||||
|
Branches already exist. Give each agent its own working copy:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /home/sami/vdm
|
||||||
|
git worktree add ../vdm-proto lane/proto
|
||||||
|
git worktree add ../vdm-pkg lane/pkg-qa
|
||||||
|
git worktree add ../vdm-core lane/core
|
||||||
|
git worktree add ../vdm-daemon lane/daemon
|
||||||
|
git worktree add ../vdm-gui lane/gui
|
||||||
|
git worktree add ../vdm-ext lane/ext
|
||||||
|
```
|
||||||
|
|
||||||
|
Then start a Claude Code session in each directory and paste that lane's prompt.
|
||||||
|
Lanes merge to `main` via PR; `main` stays green.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# WAVE 1
|
||||||
|
|
||||||
|
## → PROTO
|
||||||
|
|
||||||
|
```
|
||||||
|
You are lane PROTO on the Velox Download Manager project (worktree: ../vdm-proto,
|
||||||
|
branch lane/proto).
|
||||||
|
|
||||||
|
Read these first, in order:
|
||||||
|
1. CLAUDE.md — rules of engagement, lane ownership
|
||||||
|
2. docs/agents/AGENT-PROTO.md — your brief; it is the spec, not background
|
||||||
|
3. contracts/README.md — the v1 method surface you must formalize
|
||||||
|
4. docs/01-architecture.md §4-§5 — why the contract works the way it does
|
||||||
|
|
||||||
|
You own contracts/, tools/mockd/, tests/conformance/ and nothing else. You are the
|
||||||
|
only committer to contracts/ for the life of the project.
|
||||||
|
|
||||||
|
You are the blocker for four other lanes, so work in this order and announce each
|
||||||
|
completion:
|
||||||
|
1. JSON Schema (draft 2020-12) for every type, method and event in
|
||||||
|
contracts/README.md. Two templates exist — contracts/schema/types/
|
||||||
|
TaskSummary.schema.json and contracts/schema/methods/capture.offer.schema.json.
|
||||||
|
Match their shape, including the x-privileged / x-transports / x-deadlineMs
|
||||||
|
annotations.
|
||||||
|
2. contracts/codegen/gen_cpp.py -> core/generated/velox_proto.{hpp,cpp}
|
||||||
|
contracts/codegen/gen_ts.py -> extension/src/shared/protocol/
|
||||||
|
Commit the generated output. Other lanes must never run the generator to build.
|
||||||
|
3. contracts/fixtures/ — a success fixture for every method, plus error fixtures
|
||||||
|
for auth failure, timeout and not-found. Use $uuid / $isoDate placeholders.
|
||||||
|
4. tools/mockd — Node/TS mock daemon serving the fixtures over BOTH transports
|
||||||
|
(Unix socket NDJSON and loopback WebSocket), emitting synthetic progress events
|
||||||
|
at 4 Hz, with flags --slow --flaky --drop-connection --refuse-pairing --tasks N.
|
||||||
|
GUI and EXT build against this for all of M1, so it must land early and be solid.
|
||||||
|
5. tests/conformance/ — replays every fixture against a live veloxd and through the
|
||||||
|
generated TS client. Coordinate with PKG/QA to make it a required CI check.
|
||||||
|
|
||||||
|
Definition of done: mockd answers every fixture on both transports; both generated
|
||||||
|
clients round-trip every fixture; conformance is a required CI check; contracts/VERSION
|
||||||
|
is set to 1.0.0 and you have announced the freeze.
|
||||||
|
|
||||||
|
Constraints:
|
||||||
|
- Do not write outside your owned directories. Ever.
|
||||||
|
- Node/npm are not installed yet — `sudo apt install -y nodejs npm` first.
|
||||||
|
- Ask before inventing a method that is not in contracts/README.md; that list was
|
||||||
|
designed against the GUI and extension specs and additions have downstream cost.
|
||||||
|
|
||||||
|
Start by reading the four documents, then post a short plan of the schema files you
|
||||||
|
intend to create before writing them.
|
||||||
|
```
|
||||||
|
|
||||||
|
## → PKG/QA
|
||||||
|
|
||||||
|
```
|
||||||
|
You are lane PKG/QA on the Velox Download Manager project (worktree: ../vdm-pkg,
|
||||||
|
branch lane/pkg-qa).
|
||||||
|
|
||||||
|
Read these first:
|
||||||
|
1. CLAUDE.md
|
||||||
|
2. docs/agents/AGENT-PKG-QA.md — your brief
|
||||||
|
3. docs/07-packaging.md
|
||||||
|
4. docs/06-risks-and-spikes.md — R1 (snap Firefox) and R5 (Qt LGPL) are yours later
|
||||||
|
|
||||||
|
You own packaging/, .github/workflows/, tools/testserver/, tests/integration/,
|
||||||
|
tests/e2e/, and the root build files (CMakeLists.txt, CMakePresets.json, .clang-format,
|
||||||
|
.clang-tidy, .editorconfig, .gitignore). Never write feature code in a lane's directory.
|
||||||
|
|
||||||
|
Work in this order — lanes CORE and DAEMON are blocked on item 2:
|
||||||
|
1. tools/bootstrap.sh — installs the full apt list for a clean 26.04 machine.
|
||||||
|
This machine already has git 2.53, CMake 4.2.3, g++ 15.2, ninja, Qt 6 dev,
|
||||||
|
libcurl, SQLite, nlohmann-json, ffmpeg, clang-format/tidy. Missing here:
|
||||||
|
libqt6svg6-dev, libsecret-1-dev, nodejs, npm, clang.
|
||||||
|
⚠ CMake 4.x hard-errors on cmake_minimum_required below 3.5 — verify every
|
||||||
|
dependency, and record anything that breaks in docs/adr/.
|
||||||
|
2. tools/testserver — a deliberately hostile HTTP server. CORE's entire definition
|
||||||
|
of done is written against it, so it is your highest-priority deliverable.
|
||||||
|
Modes, each selectable by URL path or flag:
|
||||||
|
no-range, lies-about-accept-ranges, etag-changes, flaky-reset, slow-loris,
|
||||||
|
redirect-chain, 401-basic, 401-digest, 403-without-referer, 416-always,
|
||||||
|
content-length-mismatch, expiring-signed-url, throttled, chunked-no-length,
|
||||||
|
utf8-content-disposition, legacy-content-disposition
|
||||||
|
3. Flesh out CMakeLists.txt and CMakePresets.json (presets already drafted: dev
|
||||||
|
with ASan/UBSan, tsan, release with LTO, ci). C++23, -Wall -Wextra -Werror.
|
||||||
|
4. CI in .github/workflows/: gcc+clang matrix, unit tests, ASan/UBSan/TSan jobs,
|
||||||
|
clang-format --dry-run -Werror, clang-tidy, web-ext lint, and PROTO's conformance
|
||||||
|
suite as a required check on every PR.
|
||||||
|
|
||||||
|
Then: nightly integration runs, Playwright e2e, the 72-hour soak job, and in M6 the
|
||||||
|
.deb/PPA, Flatpak and AMO packaging per docs/07-packaging.md.
|
||||||
|
|
||||||
|
Definition of done for M0: one command builds from a clean checkout on a clean 26.04
|
||||||
|
VM; CI goes red on format, tidy, sanitizer, conformance or web-ext lint failure.
|
||||||
|
|
||||||
|
Start with bootstrap.sh and testserver — two other lanes are waiting on the latter.
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# WAVE 2 — start only after PROTO announces the contract freeze
|
||||||
|
|
||||||
|
## → CORE
|
||||||
|
|
||||||
|
```
|
||||||
|
You are lane CORE on the Velox Download Manager project (worktree: ../vdm-core,
|
||||||
|
branch lane/core). You are on the project's critical path.
|
||||||
|
|
||||||
|
Read these first:
|
||||||
|
1. CLAUDE.md
|
||||||
|
2. docs/agents/AGENT-CORE.md — your brief
|
||||||
|
3. docs/04-engine-design.md — read every word; this is your specification
|
||||||
|
4. docs/01-architecture.md §3 — the layering rule you must not violate
|
||||||
|
|
||||||
|
You own core/, tools/bench/, tools/fuzz/. You never touch daemon/, gui/, extension/
|
||||||
|
or contracts/. If the daemon needs something, expose it as a core API and tell lane
|
||||||
|
DAEMON — do not reach into their tree.
|
||||||
|
|
||||||
|
Hard constraints, enforced in review:
|
||||||
|
- No JSON, no SQL, no Qt, no RPC anywhere in core/. Your API takes a DownloadSpec
|
||||||
|
and emits typed callbacks. If you are including a protocol header, stop.
|
||||||
|
- C++23, -Wall -Wextra -Werror, no raw new/delete, no naked pthread.
|
||||||
|
- Errors are returned as Result<T> on the transfer path, not thrown.
|
||||||
|
- Zero allocation in the curl write callback. The ring buffer is preallocated at
|
||||||
|
task start. This is checked by review and by a bench assertion.
|
||||||
|
|
||||||
|
Build in this order (each step lands with tests):
|
||||||
|
1. util/ — Result<T>, event bus, thread pool, logging, byte spans
|
||||||
|
2. net/http_client — libcurl multi wrapper, one curl_multi per worker thread
|
||||||
|
3. net/probe — HEAD then ranged-GET fallback; Content-Disposition per RFC 5987/6266
|
||||||
|
including legacy forms. Give it a test table and a fuzz target — this is a
|
||||||
|
classic mojibake source.
|
||||||
|
4. io/sparse_file + io/write_buffer — posix_fallocate, per-segment ring buffer sized
|
||||||
|
by buffer_bytes (the user-facing "buffer" setting), pwrite at absolute offsets,
|
||||||
|
posix_fadvise(DONTNEED), timed fdatasync
|
||||||
|
5. meta/veloxpart — the resume sidecar in docs/04 §5. Write the READER first and
|
||||||
|
fuzz it; this file lives in a download directory and is attacker-adjacent.
|
||||||
|
6. segment/segmenter + segment/stealer — dynamic segment stealing per docs/04 §3
|
||||||
|
7. rate/token_bucket — hierarchical global -> queue -> task
|
||||||
|
8. task/download_task — the state machine in docs/04 §1, retry/backoff, mirrors
|
||||||
|
9. rules/ — filename sanitization, collision policy, category matching (pure fns)
|
||||||
|
|
||||||
|
Leave core/src/media/ empty — HLS/DASH is M4.
|
||||||
|
|
||||||
|
Definition of done for M1:
|
||||||
|
- 5 GB download saturates 1 Gbit at <=8% of one core, recorded in tools/bench/
|
||||||
|
- kill -9 at ~60%, resume, SHA-256 matches the reference byte for byte
|
||||||
|
- every hostile mode in tools/testserver handled
|
||||||
|
- ASan + UBSan + TSan clean under a 20-task load test
|
||||||
|
- fuzz targets for Content-Disposition, the .veloxpart.meta reader and URL parsing
|
||||||
|
run 1M+ execs with no crash
|
||||||
|
- public API documented in core/include/vdm/README.md and reviewed by DAEMON
|
||||||
|
|
||||||
|
Do not start with io_uring — it is a post-1.0 experiment gated on a >=10% bench win.
|
||||||
|
|
||||||
|
Start with util/ and net/http_client, and post your DownloadSpec/callback API design
|
||||||
|
for DAEMON to review before you build on top of it.
|
||||||
|
```
|
||||||
|
|
||||||
|
## → DAEMON
|
||||||
|
|
||||||
|
```
|
||||||
|
You are lane DAEMON on the Velox Download Manager project (worktree: ../vdm-daemon,
|
||||||
|
branch lane/daemon). You own all persistent state in this system.
|
||||||
|
|
||||||
|
Read these first:
|
||||||
|
1. CLAUDE.md
|
||||||
|
2. docs/agents/AGENT-DAEMON.md — your brief
|
||||||
|
3. docs/01-architecture.md §2-§5
|
||||||
|
4. contracts/README.md — the methods you implement
|
||||||
|
5. docs/05-extension-spec.md §4 — you implement the daemon half of pairing
|
||||||
|
|
||||||
|
You own daemon/, cli/, nmhost/, packaging/nativehost/. Never write in core/, gui/,
|
||||||
|
extension/ or contracts/.
|
||||||
|
|
||||||
|
Build in this order:
|
||||||
|
1. rpc/ — uds_server (NDJSON on $XDG_RUNTIME_DIR/velox/velox.sock, mode 0600,
|
||||||
|
SO_PEERCRED same-UID check) and ws_server (bind 127.0.0.1 ONLY, first free port
|
||||||
|
in 52000-52016, write it to ws.port). One dispatcher generated from contracts/.
|
||||||
|
Never block the RPC loop on disk or DNS.
|
||||||
|
2. Auth and pairing — session.pair triggers a user prompt (GUI dialog if connected,
|
||||||
|
else a notification with actions). 256-bit tokens stored hashed, per-install,
|
||||||
|
revocable. Failed-auth rate limit 5/min then 60s lockout. Enforce x-transports
|
||||||
|
and x-privileged from the schema; refuse privileged methods over WS with -32003.
|
||||||
|
3. store/ — SQLite WAL: tasks, segments, categories, queues, rules, settings,
|
||||||
|
history, pairings. Numbered migrations applied at startup, with a forward-only
|
||||||
|
test from every released version. Credentials go to the Secret Service via
|
||||||
|
libsecret, NEVER into SQLite.
|
||||||
|
4. sched/ — concurrency governor (global, per-queue, per-host caps), time windows,
|
||||||
|
days of week, one-shot vs periodic, on-queue-complete actions.
|
||||||
|
5. Event fan-out — per-subscription filtering, and event.task.progress BATCHED into
|
||||||
|
one array message at <=4 Hz. One message per task per tick will burn a core in
|
||||||
|
the GUI; do not do it.
|
||||||
|
6. capture.offer — must answer within 750 ms, always. Apply the rules table, resolve
|
||||||
|
the category folder, dedupe against active tasks, return take/ignore. If anything
|
||||||
|
is slow internally, answer "ignore" and let Firefox have the download. Never make
|
||||||
|
the browser wait.
|
||||||
|
7. integration/ — systemd user units (velox.service + velox.socket for socket
|
||||||
|
activation), single-instance lock, XDG autostart, desktop notifications,
|
||||||
|
graceful shutdown that flushes buffers and meta files.
|
||||||
|
8. cli/ — velox add|ls|pause|resume|rm|queue|settings with --json. Build this EARLY;
|
||||||
|
it is how you test the daemon before any GUI exists.
|
||||||
|
9. nmhost/ — 4-byte-length-prefixed stdio <-> Unix socket pump. Under 300 lines,
|
||||||
|
zero business logic, exits cleanly when Firefox closes the pipe. Install
|
||||||
|
manifests to all four locations in docs/05 §4.
|
||||||
|
|
||||||
|
Definition of done for M1: full conformance suite passes as a server over both
|
||||||
|
transports; daemon restart mid-download reloads every task with correct state and
|
||||||
|
resumes; 1000 tasks -> download.list paged under 50 ms; pairing works from real
|
||||||
|
Firefox and unpair revokes immediately; systemctl --user socket activation verified
|
||||||
|
from cold; security review passes (loopback only, no path traversal in saveDir —
|
||||||
|
canonicalize and check allowed roots, returning -32011 — no plaintext secrets).
|
||||||
|
|
||||||
|
Do not put download logic here; that is CORE. You schedule and persist, CORE transfers.
|
||||||
|
Do not invent protocol fields — file a request with PROTO.
|
||||||
|
|
||||||
|
Start with rpc/ and the CLI so you have something testable end to end on day one.
|
||||||
|
```
|
||||||
|
|
||||||
|
## → GUI
|
||||||
|
|
||||||
|
```
|
||||||
|
You are lane GUI on the Velox Download Manager project (worktree: ../vdm-gui,
|
||||||
|
branch lane/gui). You develop entirely against tools/mockd and never wait for the
|
||||||
|
real daemon.
|
||||||
|
|
||||||
|
Read these first:
|
||||||
|
1. CLAUDE.md
|
||||||
|
2. docs/agents/AGENT-GUI.md — your brief
|
||||||
|
3. docs/03-gui-spec.md — screen-by-screen spec; build in its order
|
||||||
|
4. docs/06-risks-and-spikes.md R2 — the Wayland clipboard constraint, before you
|
||||||
|
write any clipboard code
|
||||||
|
|
||||||
|
You own gui/ and nothing else. Qt 6 Widgets, C++23. Zero download logic: a grep for
|
||||||
|
curl, pwrite or sqlite in gui/ must come back empty.
|
||||||
|
|
||||||
|
Build in this order:
|
||||||
|
1. rpc/ client — wrap the generated C++ client. Async calls on a worker thread, Qt
|
||||||
|
signals on the main thread, auto-reconnect with exponential backoff, an offline
|
||||||
|
BANNER rather than a modal error, connection dot in the status bar. Everything
|
||||||
|
else depends on this, so get it right first.
|
||||||
|
2. models/DownloadTableModel — QAbstractItemModel over TaskSummary. Apply
|
||||||
|
event.task.progress batches as row patches with narrow dataChanged ranges.
|
||||||
|
Never beginResetModel() on a progress tick. QSortFilterProxyModel for the
|
||||||
|
category tree selection.
|
||||||
|
3. Main window — menus, toolbar, splitter, category tree, table, status bar,
|
||||||
|
column layout persisted in QSettings.
|
||||||
|
4. widgets/ — ProgressDelegate (in-cell bar), SegmentBarsWidget, SpeedGraphWidget
|
||||||
|
(60s rolling, 1 Hz, QPainterPath, no per-frame allocation).
|
||||||
|
5. Dialogs in this order: Add URL -> Download File Info (async probe with a spinner)
|
||||||
|
-> Download Progress -> Options (every control bound to a settings.* key that
|
||||||
|
actually exists in the schema) -> Scheduler -> Speed Limiter -> Batch -> Grabber.
|
||||||
|
6. Tray icon and the frameless always-on-top drop target.
|
||||||
|
7. clipboard/ — read docs/06 R2 FIRST. Under Wayland an app cannot passively observe
|
||||||
|
other apps' clipboard changes. Implement the explicit paths as primary (Add-URL
|
||||||
|
prefill, portal global shortcut) and treat passive monitoring as a bonus that
|
||||||
|
spike S2 may unlock. Do not advertise it in the UI until S2 answers.
|
||||||
|
8. Theming — resources/qss/idm-like.qss and dark.qss, all colours in one variables
|
||||||
|
block, follow QStyleHints::colorScheme().
|
||||||
|
|
||||||
|
Definition of done for M1: every screen in docs/03-gui-spec.md exists and is driven
|
||||||
|
only by mockd; 10000 synthetic rows scroll at 60 fps with flat memory over 10 minutes
|
||||||
|
(mockd --tasks 10000); mockd --slow/--flaky/--drop-connection produce a banner and
|
||||||
|
clean recovery, never a freeze; all strings in tr() with a stub Arabic .ts proving RTL
|
||||||
|
survives; no blocking call on the UI thread, verified by a 200 ms debug watchdog.
|
||||||
|
|
||||||
|
Icons: ship an ORIGINAL or compatibly-licensed set (Papirus/Breeze-derived is fine)
|
||||||
|
in IDM's layout positions. Do not copy IDM's artwork. Record the licence in
|
||||||
|
gui/resources/icons/LICENSE.
|
||||||
|
|
||||||
|
libqt6svg6-dev is not installed yet — apt install it before starting.
|
||||||
|
|
||||||
|
Start with the rpc client and the table model; get one live-updating row on screen
|
||||||
|
from mockd before building any dialog.
|
||||||
|
```
|
||||||
|
|
||||||
|
## → EXT
|
||||||
|
|
||||||
|
```
|
||||||
|
You are lane EXT on the Velox Download Manager project (worktree: ../vdm-ext,
|
||||||
|
branch lane/ext). You develop against tools/mockd over the WebSocket transport and
|
||||||
|
never wait for the real daemon.
|
||||||
|
|
||||||
|
Read these first:
|
||||||
|
1. CLAUDE.md
|
||||||
|
2. docs/agents/AGENT-EXT.md — your brief
|
||||||
|
3. docs/05-extension-spec.md — full spec
|
||||||
|
4. docs/06-risks-and-spikes.md — R1 (snap Firefox) and R3 (AMO review)
|
||||||
|
|
||||||
|
You own extension/ only. Not nmhost/ — that belongs to DAEMON; file a request if you
|
||||||
|
need it changed. Zero download logic: you collect URL + headers + cookies and hand
|
||||||
|
them over. That is the whole job.
|
||||||
|
|
||||||
|
YOUR FIRST TASK IS A SPIKE, NOT CODE.
|
||||||
|
Spike S1 (2 days): Firefox on this machine is the Mozilla snap (firefox 154.0). Snap
|
||||||
|
confinement has a long history of blocking native-messaging hosts. On a clean 26.04 VM,
|
||||||
|
determine empirically which of the four manifest locations in docs/05 §4 snap Firefox
|
||||||
|
can actually launch, 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 outcome — snap connections firefox shows network and network-bind
|
||||||
|
connected, so loopback is the one path known to work here.
|
||||||
|
|
||||||
|
Build in this order:
|
||||||
|
1. transport/ — the Transport interface; WebSocketTransport (port discovery across
|
||||||
|
52000-52016 verified by session.hello, pairing token in browser.storage.local,
|
||||||
|
reconnect with backoff); then NativeTransport; then runtime selection with a
|
||||||
|
manual override in Options.
|
||||||
|
2. capture/headers.ts — onBeforeSendHeaders stash keyed by requestId, ring buffer,
|
||||||
|
5-minute TTL, bounded size. A leak here eats the browser's memory.
|
||||||
|
3. capture/rules.ts — shouldCapture() exactly per docs/05 §2. Write the test table
|
||||||
|
BEFORE the implementation. This function is where the bugs will be: too eager and
|
||||||
|
you hijack page navigations, too shy and you are not a download manager. Cover
|
||||||
|
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.
|
||||||
|
4. capture/index.ts — the blocking onHeadersReceived hook: gather cookies, call
|
||||||
|
capture.offer with a 750 ms budget, return {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. A download manager that
|
||||||
|
eats downloads when its daemon is down is worse than none.
|
||||||
|
5. capture/downloads-api.ts — downloads.onCreated safety net for what slips past.
|
||||||
|
6. context-menus.ts, popup/ (live progress at <=4 Hz, pause/resume, status dot),
|
||||||
|
options/ (transport, pair/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,
|
||||||
|
and the 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 for 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 with no error dialog); pairing works, unpair revokes, token
|
||||||
|
survives a browser restart, wrong token is rejected and rate-limited; web-ext lint
|
||||||
|
clean with no remote code, no eval, no CDN script; permission justification written
|
||||||
|
for AMO.
|
||||||
|
|
||||||
|
Do not add React/Vue for a popup and an options page — plain TS keeps the bundle and
|
||||||
|
the AMO review small. Do not invent protocol fields; file a request with PROTO.
|
||||||
|
|
||||||
|
nodejs and npm are not installed yet — apt install them first.
|
||||||
|
|
||||||
|
Start with spike S1 and the WebSocket transport in parallel.
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Integration discipline (all lanes)
|
||||||
|
|
||||||
|
- Rebase on `main` daily. `main` stays green.
|
||||||
|
- A contract problem is a PR to `contracts/` filed with PROTO — **never** a local
|
||||||
|
workaround. That single rule is what makes M2 an integration week instead of a rewrite.
|
||||||
|
- Record real decisions as ADRs in `docs/adr/`. The next agent has none of your context.
|
||||||
|
- Code + tests + docs in the same change. A feature with no test does not exist.
|
||||||
Reference in New Issue
Block a user