fix: muse shelf save silently dropped unstaged modifications when any other file was staged -- DATA LOSS (musehub#207)
Root cause: run_save() (and its programmatic twin _shelf_push_programmatic) computed the working-tree manifest via plugin.snapshot(root)[files]. For a StagePlugin (the code domain), snapshot() is documented and used by muse commit to mean 'what would be committed right now' -- when any file is staged, it overlays staged object IDs onto HEAD content, making every OTHER tracked file's genuine unstaged edit invisible by design (correct for commit's selective-commit model, since unstaged changes must never leak into a commit). Shelf save reused that same commit-semantics manifest as if it were the complete working-tree manifest its own docstring promises -- it is not, whenever a stage is active.
Confirmed live, exactly matching the reported repro: with file_b.txt staged and file_a.txt separately edited but never staged, the computed manifest's file_a.txt entry equaled its HEAD value byte-for-byte despite the real on-disk content differing. The subsequent working-tree revert to HEAD then silently overwrote file_a.txt's real edit with no error, no warning, and status: shelved reported as success.
A second, compounding symptom traced to the same interaction: the stage index was never cleared after a successful unscoped shelve, so a staged-only file's content correctly reverted to HEAD on disk but its stale stage entry remained -- the same path then appeared in both staged.modified and unstaged.modified simultaneously.
Fix: - Added _true_workdir_manifest(): uses plugin.workdir_snapshot() -- already the existing, tested method muse diff --working uses to bypass the stage overlay -- for StagePlugin-conformant plugins, falling back to snapshot() unchanged for domains with no staging concept at all. Applied at both manifest-computation call sites (run_save and _shelf_push_programmatic). This also fixes the same latent bug in muse shelf save --path, which shared the same buggy manifest source. - Call plugin.clear_stage(root) after a successful unscoped apply_manifest() revert, at both call sites -- the shelf now fully captures every staged AND unstaged change, so any remaining stage entry afterward would be stale.
Semantic Changes
22 symbols
Files Changed
+1
~1
1261 in snapshot
0 comments
muse hub commit comment sha256:3c17bfbda4675d79c8fd3f331c927292363bd41abfbaa7b8d3c4da7c161b00a5 --body "your comment"
No comments yet. Be the first to start the discussion.