fix(capture): audit remediation for redaction, capture lifecycle, contract validation and snapshot performance
Merged
TH
4h ago+1448+1448+0123456789012345678901234567890123456789-315-315-012345678901234567890123456789
Summary
Fixes 13 correctness findings and 4 performance findings from the 2026-11-10 audit, in self-contained commits. Review fixes followed, and origin/main is merged in with #4357's app-log rotation kept.
- Redaction: shared references are no longer marked
[Circular]. A shared subtree is redacted once, so a diamond-shaped input is no longer exponential. - App-log redact patterns:
- Commas inside
{m,n}quantifiers,[...]and(...)stay in their pattern. - A pattern that does not compile fails
logs startwithINVALID_ARGS(app_log_redact_pattern_invalid,patternIndex). The pattern text is not echoed.
- Commas inside
- Typed errors:
alert waittimeouts carrydetails.reason: alert-wait-timeout.- An admitted operation whose interactor method is missing reports
runtime-contract-invalid. This covers hover, which used to reportUNSUPPORTED_OPERATION. An operation the runtime does not advertise is still refused withUNSUPPORTED_OPERATION. - Scroll-edge capture keeps typed and cancel errors.
- Contracts: the summary and activation readers reject values their types forbid. The merge uses at most three weighted points per run, which give the same values the old per-sample rebuild did. One
BackendSnapshotResultremains. - Events: every page returns an absolute
endCursor, so a reader following the log can resume without replaying events. - Capture lifecycle:
- App-log capture survives a failed PID poll or a slow provider read.
- No read is started while an abandoned one is still in flight, and
finishkeeps the reader until that read settles. - The recovery deadline is renamed to say it bounds only acquisition.
- React Native overlay hint: passive app text such as "Error: …" no longer triggers the hint. A bare "Error:"/"Warning:" prefix counts only with React Native context on screen; the
!,LogBox banner label is still detected on its own. - Performance:
- The Android helper presentation and overlay labels were O(n²) or worse. They now run in linear passes, and tests count parent-link reads to pin that.
- Runner presentation validates an unchanged payload once instead of twice.
- The snapshot diff change is a constant-factor reduction: typed trace slices instead of Map copies, plus a prefix skip. The trace is still O(D²) memory.
- The Android, overlay, diff and runner outputs are identical to the merge-base on fixtures and random trees.
Deferred: CMD-2 (needs its own PR), CAP-5, CAP-6, CAP2-5, CAP-9. Follow-ups: one shared children-by-parent builder, and the quadratic memory of the diff trace.
Validation
check:affected --runat7d70a9165, exactCommit=true: format, lint, typecheck, layering, fallow and build pass.vitest-relatedfailed 3 tests:- Two are the root-chmod baseline (BASE-1).
runner-lease-accessibilitytimed out at 5 s with host load average around 11. It passed 3 of 3 alone, which does not prove contention. This PR does not touch apple-runner.
- The eager-closure budget test passes.
- Live device runs are still required and are not attached. See the review thread.
Generated by Claude Code