* fix: record crash telemetry for unhandled promise rejections
The crash handler only listened on uncaughtExceptionMonitor, which never
fires for a rejection that has a listener — and the TUI always registers
one, converting rejections into a silent exit(1) with no telemetry at
all. Observe unhandledRejection directly so those crashes still leave a
trace. Since registering a real listener suppresses Node's default
crash-on-rejection, rethrow when we are the only listener (print /
server modes), deduped so the monitor does not double-report.
* fix: fall back to text paste when the clipboard image handler rejects
The Ctrl+V image-paste dispatch chained off the async handler without a
rejection branch, so any failure inside it became an unhandled
rejection — which the CLI's crash path turns into a silent exit(1).
Treat a rejection like "no image available" and paste as text.
* fix: dedupe all rethrown rejection reasons at the crash monitor
Non-Error rejection reasons (plain objects, strings, null) were recorded
by the rejection handler but not added to the dedupe set, so the
uncaughtExceptionMonitor pass after the rethrow reported a second crash
for the same failure; null/undefined reasons also crashed the monitor's
own error-type extraction. Use a Set so primitives dedupe by value, add
every rethrown reason, and classify monitor crashes null-safely.
- Drop numeric telemetry properties whose absolute value exceeds Number.MAX_SAFE_INTEGER before enqueue, and reject them again during payload assembly as a backstop.
- Omit constrained_memory_bytes when process.constrainedMemory() is not a safe non-negative integer so Linux no-cgroup sentinels do not overflow int64 parsing downstream.
- Add telemetry tests for unsafe numeric properties and constrained_memory_bytes filtering.
* feat(telemetry): add system metrics collection
Add periodic CPU and memory telemetry sampling with warmup capture, lifecycle cleanup, and tests.
* fix(telemetry): attach prompt session to system metrics