fix(agents): a claude purge takes directories only for a canonical uuid (Issue #31, Mac review)

projects/<key>/memory/ (Claude Code's auto memory) sits beside the session
dirs, and `purge claude memory` removed it whole. Only an 8-4-4-4-12 hex id
now reaches the session's directories, session files, jobs and tmp dirs. Any
other id keeps the pre-#31 reach, the `<id>.jsonl` file alone (test_a4 still
purges "uuid-c"); its residual is that file and nothing holds it in use.
The shared _plausible_id is unchanged for the other adapters.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
GodopuandClaude Opus 5.5 committed 2026-10-16 03:19:02 +00:00
1 parent 26fb1c4130
commit bd09c6a133
2 files changed
+61 -5

No files matched your search

+38 -1
View File
@@ -262,18 +262,55 @@ def test_claude_residual_lists_leftovers_then_nothing(home, tmp_path, conv, othe
assert adapter.residual_artifacts(conv, ctx) == [str(stray)]
@pytest.mark.parametrize("bad", ["", ".", "..", "*", "../x", "a/b"])
@pytest.mark.parametrize("bad", ["", ".", "..", "*", "../x", "a/b", "memory", " ", "notes",
"12345678-1234-1234-1234-12345678901g", "{conv} ", "x{conv}"])
def test_claude_rejects_malformed_uuid(home, tmp_path, conv, bad):
bad = bad.format(conv=conv)
ws = tmp_path / "ws"
ws.mkdir()
t = _tree(home, ws, conv, tmp_path / "ctmp")
# Claude Code's auto memory sits beside the session dirs, under the one
# non-uuid name there.
memory = home / ".claude" / "projects" / workspace_key(str(ws)) / "memory" / "MEMORY.md"
memory.parent.mkdir()
memory.write_text("m")
named = [home / ".claude" / d / bad / "x" for d in ("file-history", "session-env")
if bad.strip(". ") and "/" not in bad and "*" not in bad]
for p in named:
p.parent.mkdir(parents=True)
p.write_text("x")
adapter = get_adapter("claude")
ctx = _ctx(ws, home)
assert adapter.purge_artifacts(bad, ctx) == []
assert adapter.residual_artifacts(bad, ctx) == []
assert adapter.has_artifacts(bad, ctx) is False
assert adapter.conversation_in_use(bad, ctx) is False
assert all(p.exists() for p in t.values())
assert memory.exists() and all(p.exists() for p in named)
def test_a_non_uuid_id_takes_only_its_transcript_file(home, tmp_path):
"""The pre-#31 reach, kept for ids that are not uuids (test_a4 purges
"uuid-c"): the `<id>.jsonl` file, never a directory of that name."""
ws = tmp_path / "ws"
ws.mkdir()
proj = home / ".claude" / "projects" / workspace_key(str(ws))
proj.mkdir()
jsonl = proj / "uuid-c.jsonl"
jsonl.write_text("{}\n")
kept = [proj / "uuid-c" / "a", home / ".claude" / "file-history" / "uuid-c" / "b"]
for p in kept:
p.parent.mkdir(parents=True)
p.write_text("x")
adapter = get_adapter("claude")
ctx = _ctx(ws, home)
assert adapter.has_artifacts("uuid-c", ctx) is True
assert adapter.residual_artifacts("uuid-c", ctx) == [str(jsonl)]
assert adapter.purge_artifacts("uuid-c", ctx) == [str(jsonl)]
assert not jsonl.exists() and all(p.exists() for p in kept)
assert adapter.residual_artifacts("uuid-c", ctx) == []
def test_purge_cli_resolves_claude_from_leftovers_only(home, tmp_path, conv):