# Task Center Bandwidth Summary Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Show real-time aggregate download speed next to the Task Center heading, while rendering upload speed as a placeholder. **Architecture:** Reuse existing per-worker `speed_bytes_per_sec` values already stored in `job_workers`, aggregate them in the dashboard payload as `transfer_stats`, and render/update a single Task Center header node from server-rendered HTML plus dashboard refreshes. Upload remains explicitly unimplemented and is shown as a placeholder string. **Tech Stack:** FastAPI, Jinja2, vanilla JavaScript, `unittest` --- ### Task 1: Lock the API and page contract with tests **Files:** - Modify: `tests/catalogsync/test_ops_api.py` - [ ] **Step 1: Write the failing API test** Add coverage that seeds a running download worker with `speed_bytes_per_sec=2 * 1024 * 1024`, calls `/api/dashboard`, and asserts: ```python self.assertEqual("2.0 MB/s", payload["transfer_stats"]["download_speed_text"]) self.assertEqual("-", payload["transfer_stats"]["upload_speed_text"]) ``` Also render `/dashboard` and assert the Task Center area includes: ```python self.assertIn("Task Center", html) self.assertIn("Down 2.0 MB/s", html) self.assertIn("Up -", html) ``` - [ ] **Step 2: Run test to verify it fails** Run: `python -m unittest tests.catalogsync.test_ops_api.OperationsApiTests.test_dashboard_transfer_stats_exposes_download_speed_and_upload_placeholder -v` Expected: FAIL because `transfer_stats` and the new header text do not exist yet. ### Task 2: Lock the browser refresh behavior with a frontend test **Files:** - Modify: `tests/catalogsync/test_ops_frontend.py` - [ ] **Step 1: Write the failing frontend test** Expose `updateDashboard`, create a fake `[data-task-center-transfer]` node, call: ```javascript api.updateDashboard({ transfer_stats: { download_speed_text: "2.0 MB/s", upload_speed_text: "-" } }); ``` and assert the node text becomes: ```javascript "Down 2.0 MB/s | Up -" ``` - [ ] **Step 2: Run test to verify it fails** Run: `python -m unittest tests.catalogsync.test_ops_frontend.OperationsFrontendTests.test_update_dashboard_refreshes_task_center_transfer_summary -v` Expected: FAIL because no Task Center transfer node is updated yet. ### Task 3: Implement backend aggregation and initial render **Files:** - Modify: `musicdl/catalogsync/ops/web.py` - Modify: `musicdl/catalogsync/templates/ops/dashboard.html` - [ ] **Step 1: Add backend transfer aggregation** In `musicdl/catalogsync/ops/web.py`, extend worker serialization to include numeric speed fields and add a helper that returns: ```python { "download_speed_bytes_per_sec": ..., "download_speed_text": ..., "upload_speed_bytes_per_sec": 0, "upload_speed_text": "-", } ``` using the sum of active download worker `speed_bytes_per_sec`. - [ ] **Step 2: Add the server-rendered Task Center summary node** In `musicdl/catalogsync/templates/ops/dashboard.html`, change the Task Center heading area to include: ```html Down {{ transfer_stats.download_speed_text }} | Up {{ transfer_stats.upload_speed_text }} ``` - [ ] **Step 3: Run the API test to verify it passes** Run: `python -m unittest tests.catalogsync.test_ops_api.OperationsApiTests.test_dashboard_transfer_stats_exposes_download_speed_and_upload_placeholder -v` Expected: PASS ### Task 4: Implement live refresh wiring **Files:** - Modify: `musicdl/catalogsync/static/ops/app.js` - [ ] **Step 1: Update the dashboard refresh path** In `updateDashboard(payload)`, look up `[data-task-center-transfer]` and set: ```javascript "Down " + downloadSpeedText + " | Up " + uploadSpeedText ``` with defaults of `"0 B/s"` for missing download speed and `"-"` for upload. - [ ] **Step 2: Run the frontend test to verify it passes** Run: `python -m unittest tests.catalogsync.test_ops_frontend.OperationsFrontendTests.test_update_dashboard_refreshes_task_center_transfer_summary -v` Expected: PASS ### Task 5: Regression verification **Files:** - Modify: none - [ ] **Step 1: Run focused regression** Run: ```bash python -m unittest tests.catalogsync.test_ops_api tests.catalogsync.test_ops_frontend -v node -e "new Function(require('fs').readFileSync('musicdl/catalogsync/static/ops/app.js','utf8')); console.log('app.js syntax ok')" ``` Expected: all selected tests PASS and `app.js syntax ok` prints. - [ ] **Step 2: Sync to NAS and restart** Sync these files to `/volume4/Music_Cloud/catalogsync/app/...`: ```text musicdl/catalogsync/ops/web.py musicdl/catalogsync/templates/ops/dashboard.html musicdl/catalogsync/static/ops/app.js ``` Then restart: ```bash nohup bash /volume4/Music_Cloud/catalogsync/bin/serve_console.sh >/dev/null 2>&1 & ``` - [ ] **Step 3: Verify deployed page** Check: ```bash http://127.0.0.1:18080/dashboard http://127.0.0.1:18080/api/dashboard?include_task_rows=false ``` Expected: the Task Center heading shows `Down ... | Up -`.