v0.12.0
latest2026-09-20A project split across two labels raises no error, so doctor now volunteers it
+ Added
- +memgit doctor reports scope losses by default, and --audit adds every row. A split label passes fsck, raises nothing and generates no bug report, so the only way anyone learns of one is a report that volunteers it. Four mechanisms are detected: the directory moved, the label was misspelled by hand, a short label was used where the workspace label was meant, and the two derivations disagreed. Measured on a 4,957-memory store: 2,190 memories did not surface in the workspace that owns them, and 2,168 of those were one relabel away
- +Which label survives a repair is decided by the directory, not by the memory count. On a real store, healing toward the bigger pile would have kept a dead label holding 1,819 memories over the live one holding 18, and a misspelling holding 75 over the spelling holding 18, stranding both projects a second time
- +Successor guessing is narrow on purpose. Matching a stranded label to a live one by its last path segment paired two different clients who happened to share a segment, which would have filed one client's memories under another. A candidate must be a trailing segment run of the stranded label and already hold memories, and ties break on directory depth
✓ Fixed
- ✓The two project-label derivations disagreed, and a test asserted the disagreement was correct. A label derived from a path and a label derived from a Claude Code projects directory name are supposed to agree byte for byte, or scoping silently breaks. They did not: the munge regex kept the underscore character and Claude Code rewrites it as a dash, so one directory produced two labels and neither half of that project could see the other. Zero of the roughly 2,000 directories in a real Claude Code projects folder contain an underscore. The parity test passed because it paired a path holding an underscore with a hand-written directory name that kept it, so both sides were built from the same wrong assumption and the one test written to catch this could not see it
- ✓Labels written before that fix are not stranded by it. Comparison folds the two forms and storage is untouched, so anything written under the old form keeps resolving, including memories arriving from an older writer or another machine, and nothing stored is rewritten