gabriel / muse public
issue-103-cannot-untrack-empty-dir-sentinel-still-on-disk.md markdown
98 lines 4.0 KB
Raw
sha256:91dfaef4311e4b2c583365d1d249abe23ddfe8e30a384dbde1def25b4e4988b1 docs: add local source-of-truth for muse#103 (cannot untrac… Sonnet 5 1 day ago

No command can untrack a committed empty-directory sentinel whose physical directory still exists on disk

Background

Found while cleaning up ~/ecosystem/musehub's .museignore (adding a .vscode/ pattern). The directory .vscode was already tracked two ways: its one file (.vscode/settings.json, untracked cleanly via muse rm --cached) and, separately, .vscode itself as an explicit empty-directory sentinel in the commit's directories list. After untracking the file, muse status still reported:

"deleted": [".vscode/"]

The directory still physically exists on disk (never removed) -- .museignore now excludes its contents from every live-tree walk, but nothing removes the stale sentinel from the committed snapshot's directories list.

Repro -- every removal path fails

muse rm --cached .vscode --json
# fatal: not removing '.vscode' recursively without -r.

muse rm -r --cached .vscode --json
# fatal: pathspec '.vscode' did not match any tracked files.

muse rm -r --cached ".vscode/" --json
# same: pathspec '.vscode' did not match any tracked files.

muse code add . --json
# {"staged": 0, "added": 0, "modified": 0, "deleted": 0, "files": []}
# -- silently no-ops; does not detect or stage the removal at all.

No command available today can express "stop tracking this directory sentinel" when the directory is still physically present on disk.

Root cause

muse/cli/commands/code_stage.py's deleted_committed_dirs detection (the pass that stages EMPTY_DIR_OID "D" sentinels for committed empty dirs) only fires when the directory is gone from disk:

for _rel_dir in sorted(head_dirs):
    if (root / _rel_dir).is_dir():
        continue  # still exists on disk
    ...
    deleted_committed_dirs.append(_rel_dir)

This never considers the case where the directory still exists but its entire contents are now excluded by .museignore (added or changed after the directory was originally tracked). From the walker's perspective nothing looks different -- the directory is still there -- so there's no signal that the sentinel should be removed.

Separately, muse rm --cached <path>'s pathspec resolution apparently only matches entries present in the file manifest (head_manifest), not directory-only sentinel entries in directories -- hence the "did not match any tracked files" error even when passed the exact literal path shown in muse status's own output.

Why this matters

This is the same underlying design gap muse#101 and muse#102 are both instances of: the empty-directory sentinel system has several transition edges (file→dir, dir→file, dir still-present-but-now-ignored) that the staging/removal commands don't fully cover. This is the first one found with no workaround at all through the CLI -- #101 and #102 both have escape hatches (add real content; wait for the file/dir history to naturally resolve), but there is currently no command that untracks a still-present, now-ignored directory sentinel.

Scope

  1. code_stage.py's empty-dir deletion detection should also fire when a committed empty directory's path is now fully excluded by .museignore (not just when physically absent from disk) -- i.e. muse code add . should detect and stage the removal automatically.
  2. muse rm --cached <dir> (with or without -r) should recognize and remove a directory-only sentinel entry, independent of whether any files exist under that path in the manifest.
  3. Add regression tests for both: (a) ignoring a previously-tracked, still-present directory and running muse code add . untracks it; (b) muse rm --cached on a directory-only sentinel entry succeeds.

Acceptance criteria

  • At least one command can untrack a committed empty-directory sentinel whose directory still physically exists on disk, whether that's automatic detection via .museignore changes, an explicit muse rm --cached fix, or both.
  • ~/ecosystem/musehub's .vscode directory can actually reach a clean muse status after this fix, without manual object-store surgery.
File History 1 commit
sha256:91dfaef4311e4b2c583365d1d249abe23ddfe8e30a384dbde1def25b4e4988b1 docs: add local source-of-truth for muse#103 (cannot untrac… Sonnet 5 1 day ago