pmacs/tests
Levi Neuwirth 1205329c34 fix(persistence): never clobber unclaimed crash data; buffer-keyed cleanup
Addresses the PR #100 review.

- HIGH data loss: sweep could overwrite an existing crash recovery before
  the user ran recover-file. Reopen a file after a crash, edit it, and the
  next autosave wrote the current buffer over the recovery key --- losing
  exactly what autosave exists to protect. New ownership rule (Q#AS12): a
  per-session `owned` set records which path hashes THIS session wrote or
  adopted. A recovery file at a key we do not own is unclaimed crash data;
  the sweep refuses to write that buffer, counts it `blocked`, and says so
  ("autosave paused for N file(s) with unclaimed recovery"). recover-file
  ADOPTS the copy once its contents are in the buffer; discard-recovery
  removes it. Either resumes normal autosave. sweep() now returns
  (written, blocked).

- MEDIUM cleanup missed paths autosave can write. Kill/save cleanup now
  goes through `discard_buffer(BufferId)`, which removes BOTH the buffer's
  current-path key and the key its last sweep actually wrote (they differ
  after a rename --- an LSP WorkspaceEdit changes the path while the
  BufferId stays; a path-captured callback deleted the wrong key). And a
  sweep-time GC deletes the recovery of any buffer that left the registry,
  which is the backstop for argv `[new file]` buffers: they fire no
  after-load, so no removal callback is ever registered for them.

- LOW/MEDIUM recover-file pinned only on the active path. Two buffers can
  visit one path (pmacs.buffer.from_file does not dedup), so focus drift
  could recover into the wrong buffer. It now captures and compares the
  origin buffer handle as well as the path.

- LOW write_private left a pre-existing lax autosave/ directory alone. The
  birth-mode only applies to dirs that call creates, so a 0755 autosave/
  from an older run still leaked recovery-file names, sizes, and mtimes
  despite 0600 contents. It is now tightened to 0700 --- but never `base`
  itself, which is shared with history/recentf/desktop and may predate us.
  New `state::exists` (an existence check, no read) backs the ownership
  gate.

Tests (autosave_acceptance now 20): sweep_never_overwrites_unclaimed_
crash_recovery (blocked, crash copy byte-identical, adopt resumes),
discarding_an_unclaimed_recovery_unblocks_the_sweep,
killing_a_new_file_buffer_gcs_its_recovery,
saving_after_a_rename_removes_the_recovery_written_under_the_old_path,
a_pre_existing_lax_autosave_dir_is_tightened.

Gates: fmt + workspace clippy clean; lib 1499; crdt 1670; autosave 20;
desktop 11; persistence 5; m4 90; m7_8 5; GPU 58; git diff --check clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 10:52:10 -04:00
..
common M11.1: semantic-frontend protocol scaffolding (wire + capability) 2026-05-18 19:39:07 -04:00
fixtures V0.2-prerequisite pull-forward + M10.11 clean audit round 2026-05-18 10:31:31 -04:00
acceptance.rs Collapse if-let nests into let-chains (MSRV-1.95 collapsible_if sweep) 2026-05-18 14:29:36 -04:00
autosave_acceptance.rs fix(persistence): never clobber unclaimed crash data; buffer-keyed cleanup 2026-07-09 10:52:10 -04:00
completion_popup_acceptance.rs fix(completion): address TUI-validation findings (LSP query gaps, scoping, prefix keys, window scope) 2026-07-07 16:54:14 -04:00
cua_region_acceptance.rs CUA type-over is a single undo step (Q#U1) 2026-06-15 20:00:53 -04:00
desktop_acceptance.rs fix(persistence): reliable daemon gate, unarm, per-pane after-load 2026-07-08 22:27:24 -04:00
listview_acceptance.rs feat(panels): listview module, Q#P6 round-trip seam, references panel 2026-07-07 20:15:46 -04:00
m3_acceptance.rs Initial commit: v0.1.0 2026-05-03 19:51:06 -04:00
m4_acceptance.rs style(test): factor fake-LSP bootstrap out of the panel tests 2026-07-07 22:16:49 -04:00
m5_5_acceptance.rs Collapse if-let nests into let-chains (MSRV-1.95 collapsible_if sweep) 2026-05-18 14:29:36 -04:00
m5_6_acceptance.rs Initial commit: v0.1.0 2026-05-03 19:51:06 -04:00
m5_7_acceptance.rs CI fixes 2026-05-18 12:24:35 -04:00
m5_8_acceptance.rs tests: widen backoff timing signal 2026-05-25 13:32:54 -04:00
m5_perf_acceptance.rs M11.1: semantic-frontend protocol scaffolding (wire + capability) 2026-05-18 19:39:07 -04:00
m6_4_repl_acceptance.rs Fix PTY final-output drain race 2026-05-04 09:44:30 -04:00
m6_5_repl_acceptance.rs tests: quarantine macOS PTY marker cases 2026-05-25 13:02:46 -04:00
m6_7_scrollback_acceptance.rs Initial commit: v0.1.0 2026-05-03 19:51:06 -04:00
m6_8_multi_repl_acceptance.rs Collapse if-let nests into let-chains (MSRV-1.95 collapsible_if sweep) 2026-05-18 14:29:36 -04:00
m6_perf_acceptance.rs tests: tune M6 hosted perf profile 2026-05-25 13:43:28 -04:00
m7_3_acceptance.rs Fix CI and Documentation issues 2026-05-04 10:19:19 -04:00
m7_5_acceptance.rs fix(packages): basename-collision reject, SHA-256 cache key, timeout thread join, commit→revision, dead-code (F-005/F-009–F-012) 2026-07-03 18:47:23 -04:00
m7_6_acceptance.rs fix(packages): basename-collision reject, SHA-256 cache key, timeout thread join, commit→revision, dead-code (F-005/F-009–F-012) 2026-07-03 18:47:23 -04:00
m7_7_acceptance.rs M7 tail: package system, audit lint, lockfile, resolver 2026-05-07 16:50:37 -04:00
m7_8_acceptance.rs M7 tail: package system, audit lint, lockfile, resolver 2026-05-07 16:50:37 -04:00
m7_9_acceptance.rs M7 tail: package system, audit lint, lockfile, resolver 2026-05-07 16:50:37 -04:00
m7_10_acceptance.rs fix(packages): basename-collision reject, SHA-256 cache key, timeout thread join, commit→revision, dead-code (F-005/F-009–F-012) 2026-07-03 18:47:23 -04:00
m7_11_acceptance.rs M7 tail: package system, audit lint, lockfile, resolver 2026-05-07 16:50:37 -04:00
m7_review_acceptance.rs M7 tail: package system, audit lint, lockfile, resolver 2026-05-07 16:50:37 -04:00
m8_1_acceptance.rs Pin toolchain to 1.95.0 + mechanical clippy/rustc fixes 2026-05-18 11:38:57 -04:00
m8_1c_acceptance.rs M7 tail: package system, audit lint, lockfile, resolver 2026-05-07 16:50:37 -04:00
m8_1d_acceptance.rs M7 tail: package system, audit lint, lockfile, resolver 2026-05-07 16:50:37 -04:00
m8_2_acceptance.rs tests: stabilize hosted perf gates 2026-05-25 13:20:18 -04:00
m8_3_acceptance.rs M7 tail: package system, audit lint, lockfile, resolver 2026-05-07 16:50:37 -04:00
m8_5_acceptance.rs M7 tail: package system, audit lint, lockfile, resolver 2026-05-07 16:50:37 -04:00
m8_6_acceptance.rs M7 tail: package system, audit lint, lockfile, resolver 2026-05-07 16:50:37 -04:00
m8_7_acceptance.rs M7 tail: package system, audit lint, lockfile, resolver 2026-05-07 16:50:37 -04:00
m8_9_acceptance.rs V0.2-prerequisite pull-forward + M10.11 clean audit round 2026-05-18 10:31:31 -04:00
m8_10_acceptance.rs V0.2-prerequisite pull-forward + M10.11 clean audit round 2026-05-18 10:31:31 -04:00
m9_1_acceptance.rs T M4.5 async bridge: LSP requests settle async-runtime jobs 2026-05-18 19:36:17 -04:00
m9_2_acceptance.rs style: from_secs(1) for the m9_2 harvest wait (clippy duration units) 2026-06-10 12:07:08 -04:00
m9_3_acceptance.rs Collapse if-let nests into let-chains (MSRV-1.95 collapsible_if sweep) 2026-05-18 14:29:36 -04:00
m9_4_acceptance.rs M9 ship gate 2026-05-09 15:04:23 -04:00
m9_5_acceptance.rs M9 ship gate 2026-05-09 15:04:23 -04:00
m9_6_acceptance.rs M9 ship gate 2026-05-09 15:04:23 -04:00
m9_7_acceptance.rs M9 ship gate 2026-05-09 15:04:23 -04:00
m9_8_acceptance.rs M9 ship gate 2026-05-09 15:04:23 -04:00
m10_2_perf.rs M10.10 ship gate 2026-05-13 16:28:46 -04:00
m10_10_perf.rs M10.10 ship gate 2026-05-13 16:28:46 -04:00
m10_10_postcard_unknown_variant.rs M10.10 ship gate 2026-05-13 16:28:46 -04:00
m10_11_acceptance.rs M11.1: semantic-frontend protocol scaffolding (wire + capability) 2026-05-18 19:39:07 -04:00
m10_11_perf.rs M10.11: adversarial two-laptop acceptance + jitter; the M10 arc verified 2026-05-15 20:51:00 -04:00
m11_5_semantic_acceptance.rs M11.5: semantic frontend<->instance glue (SemanticClient + e2e) 2026-05-18 21:24:36 -04:00
overlay_reattach_acceptance.rs fix(panels): follow active buffer on semantic frontends; re-attach overlays on switch 2026-07-07 20:46:50 -04:00
persistence_acceptance.rs fix(persistence): symlink confinement, real test-inertness, view_top restore 2026-07-08 18:21:46 -04:00
query_replace_acceptance.rs fix(query-replace): pin the session to its origin buffer (wrong-buffer guard) 2026-07-08 17:07:08 -04:00
worker_shutdown_acceptance.rs fix(completion): address TUI-validation findings (LSP query gaps, scoping, prefix keys, window scope) 2026-07-07 16:54:14 -04:00