gabriel / muse public
test docs/90-empty-file-poisoning-regression-test #1 / 1
AI Agent gabriel · 14 hours ago · Oct 21, 2026 · Diff

test: add muse#90's exact path-poisoning regression to the empty-dir-sentinel suite

muse#90 ("zero-byte files silently mis-tracked as directory nodes, poisoning the path for all future commits") was already fixed as part of a broader, independently-filed effort: commit 47e554234 (2026-09-22, "fix: eliminate EMPTY_DIR_OID/empty-file collision with explicit kind discriminator (muse#101,#102,#103,#104)"). That fix addressed the exact same root cause #90 reported -- EMPTY_DIR_OID (blob_id(b"")) is both the sentinel for a tracked empty directory AND the legitimate content hash of a genuinely empty file, and every call site inferring file-vs-directory from that equality alone treated staged empty files as directory sentinels, silently excluding them (and, per #90's "poisoning" report, any later real content written to the same path) from the commit manifest. The fix added an explicit kind: "file" | "dir" discriminator to StagedEntry (stage schema v4) and updated all ~19 call sites.

Live-reproduced #90's exact scenario against current code in disposable /tmp sandboxes via muse-dev to confirm the fix already covers it: - Single zero-byte file: stages/commits correctly, present in manifest with size_bytes=0, not classified as a directory. - 19 zero-byte placeholder files + 1 real file in one commit (ticket's exact repro numbers): all 22 paths land in the manifest, none silently dropped. - Overwriting a previously-poisoned path with 10KB of real content in an isolated commit (the ticket's specific "poisoning" claim): lands correctly in the manifest with the real object_id -- no rename workaround needed.

tests/test_empty_dir_sentinel_invariants.py already had 9 passing tests covering this mechanism (muse#101-#104) but none matched #90's specific reported scenario verbatim: a path poisoned by a committed 0-byte file, then real content committed there in isolation. Added test_path_poisoned_by_empty_file_accepts_real_content_later to close that gap and anchor #90 to its actual fix in history.

Targeted regression suite -- test_empty_dir_sentinel_invariants.py (10, including the new test), test_cmd_code_add.py, test_cmd_status.py, test_cmd_mv.py, test_cmd_diff.py -- all pass (294 passed), zero regressions.

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

sha256:d2dc1ad1242cf18f8b17e8311abe3fd3f596d4fb73b60e411699e42681a24653 sha
+1 ~1 symbols
1 changed · 1216 in snapshot files
sha256:9a01c1db295d1a436e0a1bd83af4762db052103c99f65050c8fde3b1bcaebd7c snapshot
+1
symbol added
~1
symbol modified
1
file changed
1216
files in snapshot
0
dead code introduced
Semantic Changes 2 symbols
~ tests/test_empty_dir_sentinel_invariants.py .py 1 symbol added, 1 symbol modified
+ test_path_poisoned_by_empty_file_accepts_real_content_later method method test_path_poisoned_by_empty_file_accepts_real_content_later L115–163
Files Changed
~1
1216 in snapshot
← Older Oldest on docs/90-empty-file-poisoning-regression-test
All commits
Newer → Latest on docs/90-empty-file-poisoning-regression-test

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