Every dated command re-walks and re-stats every provider tree before it can
decide what the cache already covers. That sweep was strictly serial at every
level -- one readdir, one stat, one state.json read at a time, and one provider
after another -- so on a 21k-file / 9-provider corpus it owned most of a warm
run's wall clock with the machine idle waiting on the kernel.
Measured per warm `today` pass on that corpus before this change: 859 ms in
discoverAllSessions (kimicode 467, codex 143, claude 135, grok 77) and 727 ms in
the Claude project walk + fingerprint pass.
- fs-utils: mapWithConcurrency + FS_SCAN_CONCURRENCY, one bounded, order-
preserving helper for the whole sweep.
- providers/index: run provider discovery concurrently, concatenated in
registry order.
- claude/codex/grok/kimicode: walk each level with the level fanned out,
re-concatenated in readdir order before anything reconciles.
- parser: the Claude dir walk and both fingerprint passes (scanProjectDirs and
parseProviderSources) fan out, then reconcile serially in discovery order,
which is what changedFiles ordering and the seenMsgIds pre-seed depend on.
- parser: collectJsonlFiles reads entries with their types, so a plain file no
longer costs a wasted subagents/ probe.
- codex-cache: share one in-flight load between concurrent readers. The memo is
only populated after the read + parse resolves, so concurrent discovery had
every caller re-reading and re-parsing the same (here 59 MB) file.
No reconciliation logic changed: the same fingerprints reach the same cache
comparison in the same order. Warm `today` 5.30s -> 2.99s, cold 34.7s -> 31.1s
(medians of 5 / 2, isolated HOME + cache). today/report -p month/models/sessions
JSON, warm and cold, per-provider and combined, are byte-identical apart from
the run's own `generated` timestamp.
Closes#1104