From e88edd5bd6cd6f6347147ebb854e660691abf6f3 Mon Sep 17 00:00:00 2001 From: sami Date: Wed, 9 Sep 2026 18:23:12 +0400 Subject: [PATCH] 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 --- README.md | 2 + docs/agents/PROMPTS.md | 390 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 392 insertions(+) create mode 100644 docs/agents/PROMPTS.md diff --git a/README.md b/README.md index 37ee49f..20f4001 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,8 @@ Start here: 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. +**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. --- diff --git a/docs/agents/PROMPTS.md b/docs/agents/PROMPTS.md new file mode 100644 index 0000000..f752014 --- /dev/null +++ b/docs/agents/PROMPTS.md @@ -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 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, 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.