User reported that outgoing direct calls from macOS show up in the
history list as "missed" even when the call completes successfully.
Adds two changes to fix / diagnose:
1. history::log now dedupes by call_id. If an entry for this call_id
already exists in the store, it updates the existing row's
direction + timestamp in place instead of appending a duplicate.
Protects against double-emit (caller side adding Missed on top of
Placed, or any future signal loop that fires twice). One row per
call_id, which matches what the user intuitively expects.
2. history::log now logs every write with tracing::info — call_id,
peer_fp, direction, alias. Plus an extra line when we replace
an existing entry: "history::log replacing existing entry
from=Placed to=Missed" etc. Makes it easy to see in the desktop
stderr which side is writing what, so we can find the outgoing =>
missed regression immediately if it recurs.
3. main.ts now renders an explicit text label next to the direction
arrow: "Outgoing", "Incoming", or "Missed" instead of just the ↗
↙ ✗ icons. Removes any ambiguity about what the icon means so
future users can't misread a Placed entry as Missed based on icon
shape alone.
Side fix for scripts/build-windows-cloud.sh:
- die() and the do_full ERR trap now respect WZP_KEEP_VM=1 so a failed
build doesn't auto-destroy the debug VM (previously the trap fired
before the KEEP_VM check and tore down the VM on any error).
- Bump default server type cx23 → cx33. 4GB RAM is not enough for a
cold tauri + rustls + quinn + wzp-client cross-compile — the cx23
run got "Read from remote host ... Connection reset by peer"
partway through rustc, which is the classic signature of an OOM
kill on the SSH session. cx33 has 8GB RAM and 8 vCPU which should
comfortably fit the build.