fix(agents): claude follows CLAUDE_CONFIG_DIR (Issue #31, review)

CLAUDE_CONFIG_DIR moves claude's whole config root, sessions/ included, so a
live session started under it was not seen and a stopped one left
file-history and the rest behind. The config root is now CLAUDE_CONFIG_DIR,
else <home>/.claude; the purge and residual scans look at ctx.claude_dir and
the root's own projects/, each once. The test guard drops the variable for
every test like the other agent-home variables (test_issue55 l1 requires
every *_DIR the adapters read to be accounted for).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
GodopuandClaude Opus 5.5 committed 2026-10-15 16:00:40 +00:00
1 parent 8edb8d6f0f
commit 8a4f651bdf
2 files changed
+38 -20

No files matched your search

+37 -19
View File
@@ -5,7 +5,21 @@ from lib_py.verify_session import workspace_key
def _config_dir(ctx: DiscoveryContext) -> str:
return os.path.join(ctx.home_dir, ".claude")
"""claude's config root: CLAUDE_CONFIG_DIR moves all of it (sessions/,
file-history/, session-env/, jobs/, projects/)."""
return os.environ.get("CLAUDE_CONFIG_DIR") or os.path.join(ctx.home_dir, ".claude")
def _projects_dirs(ctx: DiscoveryContext) -> list:
"""ctx.claude_dir (CLAUDE_PROJECT_DIR, else <home>/.claude/projects) and
the config root's own projects/, each once."""
dirs, seen = [], set()
for d in (ctx.claude_dir, os.path.join(_config_dir(ctx), "projects")):
real = os.path.realpath(d)
if real not in seen:
seen.add(real)
dirs.append(d)
return dirs
def _tmp_roots() -> list:
@@ -211,10 +225,12 @@ class ClaudeAgentAdapter(BaseAgentAdapter):
if not _plausible_id(uuid):
return []
cfg = _config_dir(ctx)
jsonl = self.artifact_path(uuid, ctx)
paths = [p for p in (jsonl, jsonl[:-len(".jsonl")],
os.path.join(cfg, "file-history", uuid),
os.path.join(cfg, "session-env", uuid)) if os.path.lexists(p)]
paths = []
for pdir in _projects_dirs(ctx):
base = os.path.join(pdir, ctx.ws_key, uuid)
paths += [p for p in (base + ".jsonl", base) if os.path.lexists(p)]
paths += [p for p in (os.path.join(cfg, "file-history", uuid),
os.path.join(cfg, "session-env", uuid)) if os.path.lexists(p)]
job = self._owned_job(uuid, ctx)
if job:
paths.append(job)
@@ -264,20 +280,22 @@ class ClaudeAgentAdapter(BaseAgentAdapter):
if not _plausible_id(uuid):
return []
cfg = _config_dir(ctx)
found = set(scan_names(cfg, uuid, skip=(os.path.join(cfg, "projects"), ctx.claude_dir)))
try:
keys = sorted(os.listdir(ctx.claude_dir))
except OSError:
keys = []
for key in keys:
kdir = os.path.join(ctx.claude_dir, key)
if uuid in key:
found.add(kdir)
elif os.path.isdir(kdir):
try:
found.update(os.path.join(kdir, n) for n in os.listdir(kdir) if uuid in n)
except OSError:
pass
pdirs = _projects_dirs(ctx)
found = set(scan_names(cfg, uuid, skip=pdirs))
for pdir in pdirs:
try:
keys = sorted(os.listdir(pdir))
except OSError:
keys = []
for key in keys:
kdir = os.path.join(pdir, key)
if uuid in key:
found.add(kdir)
elif os.path.isdir(kdir):
try:
found.update(os.path.join(kdir, n) for n in os.listdir(kdir) if uuid in n)
except OSError:
pass
job = self._owned_job(uuid, ctx)
if job:
found.add(job)
+1 -1
View File
@@ -18,7 +18,7 @@ import tempfile
# The pane-inherited variables conftest._isolate_agent_homes drops for every
# test, so HOME (which the tests set) governs, as it does in a plain shell.
DROPPED_VARS = ("HOME_DIR", "CLAUDE_PROJECT_DIR", "CODEX_HOME", "LOCAL_BIN")
DROPPED_VARS = ("HOME_DIR", "CLAUDE_PROJECT_DIR", "CLAUDE_CONFIG_DIR", "CODEX_HOME", "LOCAL_BIN")
# Read by the code under test but left alone, on purpose: HOME is where the
# real herdr tests and the shim bootstrap find the server socket, and it is
# what the suite's own tests set for an isolated home; XDG_CONFIG_HOME and