# Hidden thread timers: before/after measurement

Evidence for `perf(mobile): pause elapsed-time timers on hidden thread screens`.

## What was measured

`battery-measure.test.tsx` renders a probe component in jsdom with React 19 and
Vitest fake timers. `useIsFocused` and `AppState` are mocked so each scenario
fixes focus and app state. For each scenario the probe runs for 60 simulated
seconds, one `act` per second, and counts:

- `armed-interval-seconds`: how many of those seconds had a JS timer pending
- `commits/min`: React commits of the probe
- `label-clock-at-end`: the clock value the label would show, relative to start

"before" is the timer logic copied verbatim from the parent commit
(`WorkingTimer` and `ProviderSubagentBar`). "after" is `useVisibleSecondClock`.

Run it by copying the file next to `use-visible-second-clock.ts` in
`apps/mobile/src/features/threads/` and running
`vp test run <file>` from `apps/mobile`. Set `MEASUREMENT_OUT` to choose where
the table is written.

## Results (`measurement.txt`)

| Timer | Scenario | Before | After |
|---|---|---|---|
| both | visible (focused, active) | 60 commits/min | 60 commits/min |
| both | unfocused retained route | 60 commits/min | 0 |
| both | focused, app background | 60 commits/min | 0 |
| both | focused, app inactive | 60 commits/min | 0 |
| WorkingTimer | 600 s background, then active | 600 commits while hidden | 0, label shows +600 s on the first active render |

## Limits

- These are fake-clock JS interval callbacks and React commits in jsdom. They
  are not OS wakeups, CPU time, or battery measurements.
- No device, simulator, or native build was used. Real-device energy
  impact is not measured here.
- Only the two elapsed-time labels changed in this PR were measured. This is not
  a full mobile battery audit.
