gabriel / muse public
issue-101-files-double-recorded-as-directories.md markdown
107 lines 4.6 KB
Raw
sha256:03b0962049d66187f340e162a5ffdc50de6a7f7ad5bc81e4b7649d696de8eaa8 docs: add local source-of-truth for muse#101 (files double-… Sonnet 5 2 days ago

Some commits record a tracked file's exact path a second time in directories, causing false "deleted" status

Background

Discovered incidentally while merging an unrelated doc-only commit into ~/ecosystem/presentations/build-with-muse's dev branch. muse status reported 19 files as deleted immediately after a clean branch switch, even though every one of those files exists on disk, unmodified, with correct content.

Repro / evidence

Repo: ~/ecosystem/presentations/build-with-muse, commit sha256:07c10b6184a651841b238710523048c817c5c062f2435c64628f6e407e9d55e3 ("Fix stale 'under seven minutes' claim in THE POINT section"), snapshot sha256:f7b950d6fecd6a30cf3b1063b172364d4e5776e567e5f7f5eaaae969477cc257.

muse read-snapshot sha256:f7b950d6fecd6a30cf3b1063b172364d4e5776e567e5f7f5eaaae969477cc257 --json

The manifest (files) correctly lists these paths with real content hashes:

"episode-03/everything-is-content-addressed.md" -> sha256:635d415d4b32e6c729b9cc0d4e2b1ea29c5295e44c3471f02622f5b94040d4e6

But the same snapshot's directories list also contains the exact same path:

"episode-03/everything-is-content-addressed.md"

19 paths across episode-03 through episode-21 are affected this way (full list in the JSON payload, all .md episode-script files). No real directory exists at any of these paths on disk — a regular file does.

Effect

muse status compares the committed directories list against the live working tree. Since no directory exists where one is (incorrectly) recorded, every one of these paths is reported as a deleted directory:

"deleted": [
    "episode-03/everything-is-content-addressed.md/",
    "episode-04/identity-without-passwords.md/",
    ... 17 more ...
]

This is misleading and alarming (it reads as data loss) but is not actual data loss — the files are intact, correctly tracked in manifest, and readable normally. It's a display/bookkeeping bug in how the affected commits' snapshots were constructed, not a working-tree or object-store integrity problem.

Root cause — not yet identified, hypothesis only

muse/core/snapshot.py::walk_workdir_with_dirs (the function that computes (manifest, directories) together from a live os.walk during commit) looks correct on inspection: it only ever appends real dirpath values from os.walk, never a file's own path. That rules out ordinary muse commit as the direct cause, unless a same-named directory genuinely existed on disk at commit time (unlikely for 19 different episode scripts).

More likely candidates, not yet investigated:

  • A merge/rebase/replay path (muse/core/rebase.py::replay_one or the merge engine) that unions a parent commit's directories with a new manifest without pruning entries that transitioned from directory-with-content to plain file (or vice versa) across the merge.
  • A commit created via a path that doesn't go through walk_workdir_with_dirs at all (e.g. commit-tree, a scripted/API commit, or an older code path predating musehub#60 Phase 1's SnapshotRecord.directories schema work).
  • These .md files may have started life as placeholder directories (e.g. someone ran mkdir episode-03/everything-is-content-addressed.md by mistake, committed it as an empty tracked directory, then later replaced it with a real file without the old directory entry ever being explicitly removed from a subsequent commit's carried-forward state).

Suggested investigation

  1. Walk this repo's commit history (muse log --json) and bisect which commit first introduced the duplicate entry for one of the affected paths (muse read <commit> --json --manifest at each step, checking both manifest and the snapshot's directories).
  2. Once the introducing commit is found, identify what command sequence produced it — that pins down whether this is a live commit bug, a merge/replay bug, or a stale-migration artifact.
  3. Add an invariant check (muse check or muse verify?) that flags any snapshot where a path appears in both manifest and directories simultaneously — that state should never be valid, and should be either rejected at commit time or at least surfaced as a warning rather than silently producing misleading status output later.

Acceptance criteria

  • Root cause identified and documented (which code path produces this).
  • A regression test reproducing the exact commit-time bug.
  • muse status no longer reports a false "deleted" for a path that is correctly tracked as a file.
  • Ideally: a muse verify/muse check invariant catches this class of corruption at write time, not just at read/status time.
File History 1 commit
sha256:03b0962049d66187f340e162a5ffdc50de6a7f7ad5bc81e4b7649d696de8eaa8 docs: add local source-of-truth for muse#101 (files double-… Sonnet 5 2 days ago