* fix(shell): version-gate crash markers, pin the WebView repair contract, run the Rust suite in CI
Two deferred items from the recurrence audit, plus the CI gap that made
them possible:
- crash.rs: a persisted "backend crashed" marker now only surfaces for
the release that wrote it. After an upgrade, markers from the previous
version (quite possibly the build whose crash the upgrade fixed) are
ignored and pruned on read instead of resurfacing unacknowledged as if
the new build had crashed. backend_version gains #[serde(default)] so
legacy version-less markers still deserialize — as "", which the gate
treats as stale by design. Preview stamps (X.Y.Z-N) count as their
release.
- commands.rs: the #879 WebView2 cache repair's filesystem half is
extracted into clear_webview_cache_at() (paths + retry policy as
parameters, zero behavior change) and its contract is pinned by tests:
no marker → nothing touched; marker consumed first, unconditionally
(one-shot — a failing repair can never loop across launches); missing
cache is success; a locked cache is retried then abandoned with a log,
never bricking startup.
- ci.yml: the Tauri shell check only ran `cargo check`, which neither
compiles nor runs #[cfg(test)] code — so the shell's ~90 unit tests
(crash.rs, reset.rs, bootstrap.rs, …) never executed anywhere in CI.
`cargo test --lib` now runs them natively on all three OSes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(shell): crash-notice read path is strictly read-only — a prune-save there could destroy a fresh marker
Greptile's P1 is real, and hotter than stated: get_last_backend_crash is
not just a startup check — streamDropError (#1119) polls it every second
for 8 s after a stream drops, which is exactly when the death watcher is
inside record_crash's load→push→save. The previous commit's read path did
load→prune→save when stale-version markers existed (the post-upgrade
state), so a poll could load the pre-crash snapshot, lose the race, and
save over the freshly recorded marker — silently deleting the only
evidence of the crash it was being polled to find.
Smallest fix: reads never write. The read path (extracted as
read_notice_from(path, version) so the contract is testable) filters
stale-version markers in memory only; disk pruning stays on the write
paths (record_crash, acknowledge_backend_crash), where load-modify-save
already existed pre-PR and is paced by a crash or a user click rather
than a 1 Hz poll. Regression test pins the file as byte-identical across
reads, stale markers filtered and current ones surfacing as before.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: mergetest <nizam4103@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>