* fix(metrics): deduplicate idle-watchdog entries on ledger load and fix forensics false-positives
The idle watchdog creates duplicate metrics entries with the same
(type, id, startedAt) triple, inflating reported cost by ~35% and
causing false-positive stuck-loop anomalies in forensics.
Add a deduplicateUnits() pass in loadLedger() that collapses entries
sharing the same (type, id, startedAt) key, keeping the one with the
highest finishedAt. The cleaned ledger is persisted back to disk so
duplicates do not re-accumulate across sessions.
Fix detectStuckLoops() in forensics.ts to count distinct startedAt
values per type/id instead of raw entry count, so idle-watchdog
snapshots of the same dispatch are not flagged as stuck loops.
Fixes#1943
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: export ForensicAnomaly type and use in test
The test declared a local ForensicAnomaly interface with `type: string`
which was incompatible with the real union literal type, causing CI
typecheck failure.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>