gabriel / muse public
fix BREAKING task/git-export-ignored-file-deletion #1 / 1
AI Agent gabriel · 11 days ago · Jul 5, 2026 · Diff

fix: git-export deletes ignored/untracked local files not owned by any prior export

GitExporter.sync_to_git deleted every file under --git-dir not on a hardcoded/--exclude list, without consulting ignore rules or checking whether Muse had ever actually written that path. Ignored, untracked local files (.env, config/local.yaml) that were never part of any Muse snapshot were permanently deleted and unrecoverable.

Fix, per the ticket's requested design:

1. Track the manifest paths written by the previous successful export in a sidecar JSON file (muse/core/bridge/state.py::_SidecarData). Delete candidates are now computed as owned_before - owned_now — never an unconditional sweep of the whole working tree. A path Muse never wrote can never appear in owned_before, so it can never be deleted, on the first export or any subsequent one.

2. Within the delete-candidate set, consult git check-ignore --stdin (batched, one subprocess call) and .museignore's global patterns; skip ignored paths unless --allow-delete-ignored is passed. This is defense-in-depth for a path that was legitimately Muse-owned before but has since been reused by an ignored local file.

Note: git check-ignore never reports a path as ignored while it's still tracked in the git index (correct, standard git behavior) — a reused path that was previously tracked by the bridge needs .museignore, not .gitignore, for ignore-based protection until something actually untracks it. Documented directly in GitExporter._ignored_paths.

Verified against the exact reproduction in the ticket: .env and config/local.yaml both survive a git-export run that previously deleted them. git-import was investigated and found to have no delete pass at all — it only reads git commits into the Muse object store, never touches git working-tree files — so the ticket's '(and git-import)' framing doesn't apply to any code path that actually exists.

5 new regression tests in tests/test_bridge_git_export.py (TestIgnoredFileProtection). All 282 existing bridge tests still pass (one test mock updated for the new sync_to_git parameter).

Closes #65.

sha256:d25a7c7c4fbf0db573ca9a8db4f8f88f8e88ae732d8c7cdfa2624ebeabd130f0 sha
+15 ~14 symbols
4 changed · 1128 in snapshot files
sha256:745b7f5c63e1570c106d8366aa539ac521aa2772b5e1e31421720d8ac75ca6de snapshot
+15
symbols added
~14
symbols modified
4
files changed
1128
files in snapshot
0
dead code introduced
Semantic Changes 29 symbols
~ muse/core/bridge/exporter.py .py 9 symbols added, 11 symbols modified
+ _ignored_paths method method _ignored_paths L161–207
+ _read_owned_paths method method _read_owned_paths L142–151
+ _write_owned_paths method method _write_owned_paths L153–159
+ _SidecarData import import _SidecarData L29–29
+ git_bridge_sidecar_path import import git_bridge_sidecar_path L38–38
+ is_ignored import import is_ignored L37–37
+ load_ignore_config import import load_ignore_config L37–37
+ load_json_file import import load_json_file L40–40
+ resolve_patterns import import resolve_patterns L37–37
~ muse/core/bridge/state.py .py 1 symbol modified
~ tests/test_bridge_git_export.py .py 6 symbols added
+ TestIgnoredFileProtection class class TestIgnoredFileProtection L738–930
+ test_allow_delete_ignored_flag_overrides_protection method method test_allow_delete_ignored_flag_overrides_protection L892–930
+ test_previously_owned_file_removed_when_dropped_from_manifest method method test_previously_owned_file_removed_when_dropped_from_manifest L795–830
+ test_reused_path_protected_when_currently_museignored method method test_reused_path_protected_when_currently_museignored L832–890
+ test_untracked_gitignored_file_survives_export method method test_untracked_gitignored_file_survives_export L741–769
+ test_untracked_unignored_file_survives_first_export method method test_untracked_unignored_file_survives_first_export L771–793
Files Changed
~4
1128 in snapshot
← Older Oldest on task/git-export-ignored-file-deletion
All commits
Newer → Latest on task/git-export-ignored-file-deletion

0 comments

No comments yet. Be the first to start the discussion.

To add a comment, use the Muse CLI: muse hub commit comment sha256:d25a7c7c4fbf0db573ca9a8db4f8f88f8e88ae732d8c7cdfa2624ebeabd130f0 --body "your comment"