Idle Tasks page slow and repeated reads
Follow-up from Task 12181. That task fixed the read relay sending slow reads twice, refreshing off-window expanded rows, `setup` reads cancelling each other, and State-count reads cancelling each other. These bugs remain on an idle /tasks page (prod shows 3–13 s per read):
1. **Restore of remembered expanded rows**: on every page load, each id in the stored outline (`loadExpandedTaskIds`, `apps/web/src/pages/Tasks.tsx` restore effect) costs one `GET /api/tasks/{id}`, even when the row is not on the board. The stored set is never pruned. Restore only rows the board draws, and cap the stored set.
2. **Worktrees re-read on every `task` event**: `fetchWorktrees` runs in the task live-refetch (`Tasks.tsx`). Drive it from worktree/slot events, or throttle it separately.
3. **`GET /api/tasks/tree` is the slowest read** (up to 13 s). It runs a full-board `count_rows` plus three `has_project_key` calls per project (`apps/api/app/task_tree.py:182-223`), on a 30 s poll and on every task event. Cache it per org, or compute it incrementally, and batch the permission checks.
4. **Expanded-parent refresh is N detail reads**: `GET /api/tasks/{id}` runs about a dozen sequential queries (`apps/api/app/routes/tasks/read.py:101`). Add a batch rollup read for expanded parents, or a lighter detail mode.
5. **`GET /api/org/setup` is heavy**: every call decrypts the GitHub App secret (`git_access.app_config`, `org_setup.py:200`), opens a second session, and calls `effective_access` per connected user (`org_setup.py:245`). Cache the app config, and batch the access check.
6. **`/api/health/components`** polls every 30 s and also refetches on every window focus (`refetchOnWindowFocus: 'always'`, `apps/web/src/hooks/useHealth.ts`). Drop the `'always'` focus refetch.
Out of scope: the read relay, the expanded-row refresh filter, and the setup/counts `cancelRefetch` changes, all shipped in Task 12181.
Done means: on a seeded local stack with 50+ tasks and 5 expanded rows (2 off-window), a 60 s idle capture of /tasks shows no detail read for an off-window row, no worktrees read per task event, and `tree`/`setup` server time cut (cite before/after timings). `./dc check quick` and the changed-area tests pass.
Outcome
Artifacts
Activity
- Created
- Run
- Runner started