Files
orca/src
OrcaWinandm4air 22857cd8a0 fix(crash-reporting): stop periodic emitters from evicting the crash trail (#20639)
* fix(crash-reporting): stop a once-a-minute sampler from evicting the crash trail

The breadcrumb ring is 30 entries and evicts oldest-first, so any emitter that
repeats outlasts the whole lifecycle trail. Across 293 field reports three
periodic emitters hold 77% of every slot ever shipped and 39% of reports arrive
with no lifecycle crumb at all — the "Recent activity" section cannot say what
the app was doing.

Charge the overflow to the most crowded name instead of the oldest event, so a
series is thinned from its oldest end and singletons survive. No allowlist, so a
new periodic emitter cannot reopen the hole.

* test(crash-reporting): pin coalesced-burst accounting under mid-ring eviction

* fix(crash-reporting): scope eviction per origin and spare live coalescing owners

Round-1 review found two ways the name-only policy was worse than plain FIFO:

- Counting ignored `origin` while the snapshot filters by it, so a busy popout's
  samples made the main window's singleton look redundant and deleted it.
- Names like `renderer_error` carry many independent coalesce keys, so the name
  became "crowded" out of genuinely distinct errors — and the entry taken was the
  oldest, i.e. a key still accumulating `suppressedSinceLast`. A crash report is
  the last snapshot, so an orphaned owner is never re-claimed and the burst count
  simply vanished.

Group by (name, origin), skip an entry a coalesce key still owns unless every
candidate is owned, and never consider the crumb that just arrived — its coalesce
state is linked after the push, so it would always look unowned.

* fix(crash-reporting): trim the report window by the same policy as eviction

Round 2 found the fix defeating itself. Fair-share eviction parks one-off crumbs
at the ring's HEAD and the repeating series at its tail — and the snapshot then
took a plain tail slice of `MAX_BREADCRUMBS - retained.length`, trimming exactly
what eviction had just protected. Measured on the previous commit: one retained
`renderer_memory_highwater` cost one lifecycle crumb, and three erased the
lifecycle trail from the report entirely. That lane fills under the same memory
pressure that produces the `renderer_memory` flood, so the two cancelled out
precisely when the trail matters most.

Trim with `evictionIndex` instead, and route `isCoalescedCrumbStillInEvidence`
through the same window — a predicate that disagrees with the snapshot would drop
an owner's handle and lose the burst count from the crumb the reader sees.

Also strengthens the uncoalesced-burst test, whose only remaining delta against
its coalesced twin was the slot count: it now asserts the pane population is
absent on the uncoalesced side, which is the signal coalescing exists to keep.

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
2026-09-15 16:21:36 -04:00
..