Part of #14 (delivery step 3). Depends on the request-scoped extraction; parallel with the lifecycle issue.
Что сделать
- Async providers in shared mode: Git (
git.ts), usage/Keychain (usage-fetch.ts), custom-command (custom-command.ts) via async child_process — sync child-process APIs block the event loop and would let one slow command stall every session.
- Custom-command capture: adapt
custom-command-capture.ts to an asynchronous result in the daemon, retaining output limits, timeouts, EPIPE handling and descendant/process-group cleanup. Do not call the sync Node-spawning helper unchanged inside the server.
- Git review cache: route the detached refresh path through the same async scheduler instead of re-entering the Node executable. Audit remaining providers for self-spawns and caller-global state (one-process invariant). Legacy sync path stays for one-shot mode.
- Prefetch: gather data for configured widgets into RenderContext before synchronous widget formatting consumes it (existing registry/formatter/parser reused).
- Scoped caches (epic table): key by absolute config path + revision / auth profile + credential generation / worktree + cwd / canonical transcript identity. In-flight refresh dedup per key; account/profile separation before any memory-cache fast return; TTL zero still executes per eligible request; missing credentials never select another profile's cached usage.
- Transcript reuse: validated whole-analysis reuse via file identity/size/mtime/replacement; invalidation tests for truncation, replacement, compaction, partial trailing records, subagent updates. No unconditional full rescan of unchanged files. Incremental tail parsing stays out (conditional follow-up).
- Concurrency: bounded queues; at most one active + one newest pending render per exact display context; superseded requests resolved explicitly; provider work cancelled when it has no remaining consumers without killing shared refreshes; a slow command or usage fetch never blocks cached responses of other sessions.
- Bounded memory: cap caches, active jobs and idle retention; never retain full envs, tokens or transcript contents in diagnostics.
Файлы
src/utils/git.ts, src/utils/git-review-cache.ts, src/utils/custom-command.ts, src/utils/custom-command-capture.ts, src/utils/usage-fetch.ts, src/utils/jsonl-metrics.ts, src/daemon/, src/types/RenderContext.ts.
Эталон
PR #9 (jsonl test discipline for truncation/compaction edge cases), PR #2 (provider cost discipline).
Acceptance (from epic)
Simultaneous different configs/accounts/worktrees/widths cannot exchange data; account switch/logout invalidates relevant caches; one slow/hung command does not stall other sessions; memory stays bounded and is reclaimed after idle.
Оценка
- LOC: ~700–1000 (src ~550 / tests ~350)
- Размер: XL
- Время (код): ~100–180 мин
- Время (review): ~90–120 мин (база 45–60 ×2: concurrency + subprocess management)
- Время (итого): ~190–300 мин
Priority: medium.
Part of #14 (delivery step 3). Depends on the request-scoped extraction; parallel with the lifecycle issue.
Что сделать
git.ts), usage/Keychain (usage-fetch.ts), custom-command (custom-command.ts) via async child_process — sync child-process APIs block the event loop and would let one slow command stall every session.custom-command-capture.tsto an asynchronous result in the daemon, retaining output limits, timeouts, EPIPE handling and descendant/process-group cleanup. Do not call the sync Node-spawning helper unchanged inside the server.Файлы
src/utils/git.ts,src/utils/git-review-cache.ts,src/utils/custom-command.ts,src/utils/custom-command-capture.ts,src/utils/usage-fetch.ts,src/utils/jsonl-metrics.ts,src/daemon/,src/types/RenderContext.ts.Эталон
PR #9 (jsonl test discipline for truncation/compaction edge cases), PR #2 (provider cost discipline).
Acceptance (from epic)
Simultaneous different configs/accounts/worktrees/widths cannot exchange data; account switch/logout invalidates relevant caches; one slow/hung command does not stall other sessions; memory stays bounded and is reclaimed after idle.
Оценка
Priority: medium.