gabriel / muse public
fix BREAKING fix/76-status-dir-only-ignored-content #1 / 1
AI Agent gabriel · 2 hours ago · Oct 21, 2026 · Diff

fix: muse status no longer misclassifies directories with only ignored files as untracked (muse#76)

Root cause confirmed exactly as scoped in the ticket: CodePlugin.stage_status()'s os.walk loop pruned a directory from the walk only when the DIRECTORY NAME ITSELF matched an ignore pattern. A file-level pattern (e.g. "onlyignored/lockfile.txt") doesn't prune the directory -- os.walk still descends into it, adds it to on_disk_dirs, then correctly excludes the one ignored file from workdir_files. dirs_with_workdir_files is derived only from workdir_files, so the directory never lands in it. empty_on_disk_dirs (on_disk_dirs - dirs_with_workdir_files) then classified the directory as an "empty on-disk directory" -- even though its only content is legitimately ignored, not actually empty -- and it flowed into dir_added, rendered by `muse status` as "untracked directory: ...".

Fix (Phase 2, exactly as scoped): track a new set, dirs_with_any_file, populated for EVERY regular file encountered during the walk (all ancestor path components, matching dirs_with_workdir_files's own prefix-walk semantics) -- BEFORE the is_ignored check, so it includes directories whose only content is ignored. empty_on_disk_dirs now subtracts both dirs_with_workdir_files AND dirs_with_any_file, so a directory with only ignored content is excluded from the empty-dir candidate set entirely. No change to the directory-NAME-level ignore pruning (dirnames[:] = ...) -- that mechanism was already correct and unrelated to this bug, per the ticket's explicit scope.

New regression tests in tests/test_status_directory_tracking.py (TestDirectoryWithOnlyIgnoredContent), matching the ticket's Phase 1 spec exactly: - STATUSDIR_01: directory with only an individually-ignored file must not appear in `untracked`. Confirmed genuine RED against current code before the fix. - STATUSDIR_02: `muse status` and `muse diff` must agree -- committed the ignore-pattern change first so it isn't itself a pending change, isolating the exact cross-command disagreement the ticket reported (diff.has_changes == false, status still flagged the directory). Confirmed genuine RED. - STATUSDIR_03: a genuinely empty directory (no ignore involved) must still be reported as untracked/addable -- regression guard for the pre-existing empty-dir-tracking feature. Already passed pre-fix, as expected (this is a guard, not a repro). - STATUSDIR_04: a directory with one ignored file and one real file must surface in untracked only via the real file's own path, and `muse code add` on the directory must stage only the real file, never a directory sentinel. Already passed pre-fix, as expected.

Live-reproduced the ticket's exact repro (mkdir onlyignored + TOML .museignore pattern) via muse-dev in a disposable /tmp sandbox before and after: `onlyignored/` disappeared from `untracked` after the fix, while a sibling genuinely-empty directory and a mixed ignored+real-file directory both continued to behave correctly.

Targeted regression suite (Phase 3, exactly as scoped) -- test_status_directory_tracking.py (14, including the 4 new tests), test_directory_tracking.py, test_dir_lifecycle.py, test_directories_feature.py, test_cmd_status.py, test_cmd_code_add.py -- all pass (285 passed), zero regressions.

Co-Authored-By: Claude Sonnet 5 <[email protected]>

sha256:8ab72466cbde2db46324e13860aec931ec612c075bd0ef9e0f2245914089664b sha
+5 ~2 symbols
2 changed · 1216 in snapshot files
sha256:e1b2640ed883d793217609538f826f8db12b270d5cd0c5791c1b72c3dc5d52fa snapshot
+5
symbols added
~2
symbols modified
2
files changed
1216
files in snapshot
0
dead code introduced
Semantic Changes 7 symbols
~ muse/plugins/code/plugin.py .py 2 symbols modified
+ TestDirectoryWithOnlyIgnoredContent class class TestDirectoryWithOnlyIgnoredContent L244–340
+ test_STATUSDIR_01_dir_with_only_ignored_file_not_untracked method method test_STATUSDIR_01_dir_with_only_ignored_file_not_untracked L251–266
+ test_STATUSDIR_02_status_and_diff_agree method method test_STATUSDIR_02_status_and_diff_agree L268–294
+ test_STATUSDIR_03_genuinely_empty_dir_still_untracked method method test_STATUSDIR_03_genuinely_empty_dir_still_untracked L296–310
+ test_STATUSDIR_04_mixed_dir_only_real_file_surfaces method method test_STATUSDIR_04_mixed_dir_only_real_file_surfaces L312–340
Files Changed
~2
1216 in snapshot
← Older Oldest on fix/76-status-dir-only-ignored-content
All commits
Newer → Latest on fix/76-status-dir-only-ignored-content

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:8ab72466cbde2db46324e13860aec931ec612c075bd0ef9e0f2245914089664b --body "your comment"