Skip to content

Add the disk-hygiene plugin for session-owned cleanup - #48

Merged
cdeust merged 3 commits into
mainfrom
feat/disk-hygiene-plugin
Sep 26, 2026
Merged

cdeust merged 3 commits into
mainfrom
feat/disk-hygiene-plugin

Conversation

@cdeust

@cdeust cdeust commented Sep 26, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds plugins/disk-hygiene, a shared cleanup hook for Claude Code and Codex, moved out of fix(hooks): share cleanup across Claude and Codex, retain transcripts Cortex#645 because cleanup of session files does not belong to a memory server.
  • The removal logic is unchanged. Fixed from the review of that PR: push detection reads only the command of a shell tool; the ledger lock waits up to 10 seconds and is not taken by ordinary tool calls; DISK_HYGIENE_CLEANUP=off disables every hook; the context-guard checkpoint follows the transcript policy; a corrupt or foreign end-of-session intake file is skipped and reported; a symlinked config directory is resolved; the Cortex completion receipt for Codex rollouts is optional.
  • Transcripts are kept by default. Deleting them is opt-in.
  • Refs MCP server holds a multi-GB memory plateau per session; orphaned servers survive their client #47. This does not fix the memory plateau measured there, which still needs a profile of one server.

Test plan

  • 132 tests for the new plugin pass locally, including false-positive push detection, lock contention, the global switch and the invalid intake case.
  • CI on this branch.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Mkvy5MtGG89cNLuQSU8xLe

Move the shared cleanup hooks out of the Cortex plugins, where they were
proposed as a pull request, into an independent plugin for Claude Code and
Codex. The removal logic is unchanged; the review findings are fixed:

- Push detection reads only the command of a shell tool, so file content,
  grep patterns, commit messages, heredoc bodies and --dry-run no longer
  purge a live session.
- The ledger lock waits up to 10 seconds instead of failing at once, an
  unchanged ledger is not rewritten, and ordinary tool calls take no lock.
- DISK_HYGIENE_CLEANUP=off disables every hook and mutating command.
- The context-guard checkpoint follows the transcript policy.
- A corrupt or foreign end-of-session intake file is skipped and reported
  instead of blocking every hook.
- A symlinked config directory is resolved instead of silently disabling
  cleanup, and the Cortex completion receipt for Codex rollouts is optional.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mkvy5MtGG89cNLuQSU8xLe
Signed-off-by: cdeust <cdeust@icloud.com>
Comment thread tests/test_disk_hygiene_fixes.py Fixed
@cdeust cdeust mentioned this pull request Sep 26, 2026
1 of 2 tasks
The CI job installs ruff 0.16.8, which flags 38 issues in the new plugin
that an older local ruff did not: unsorted imports, unused noqa comments,
nested with statements, subprocess.run without an explicit check argument,
one file handle without a context manager and a shebang without the
executable bit. Fix them without changing behavior. The purgers fixture
moves to tests/conftest.py instead of being re-imported by alias.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mkvy5MtGG89cNLuQSU8xLe
Signed-off-by: cdeust <cdeust@icloud.com>

def holder(lock_path, seconds):
"""Hold the ledger lock from another thread's file descriptor."""
handle = open(lock_path, "a+") # noqa: SIM115 - held until the release thread ends

def test_active_file_prevents_removal(self):
with (
open(Path(self.path, "open.tmp"), "w"),
An end-of-session intake with a valid shape but a session id that is not a
UUID was written by SessionEnd, then made the host import raise on every
later hook, so no host cleanup ran for any session. The host consumer now
reports and skips such a file while the worktree consumer, which only needs
an owner key, still reads it. A test covers both consumers.

Also state in the README what really happens to an intake recorded under
other roots, and document the migration of the ledger location and of the
CORTEX_CLAUDE_DIR variable in the README and the CHANGELOG.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mkvy5MtGG89cNLuQSU8xLe
Signed-off-by: cdeust <cdeust@icloud.com>
@cdeust

cdeust commented Sep 26, 2026

Copy link
Copy Markdown
Owner Author

ZETETIC-REVIEW: REQUEST_CHANGES

Independent read-only review of 3d6ca63 and 42977e3 against the original files of cdeust/Cortex#645 (head 9a8b606b). No wrongful deletion path was found: cleanup_operations, session_purge and codex_purge differ only on the seven intended points plus source wording, import order and an explicit check=False; the guards in remove() (symlink, owner, nested .git, lsof, transcript reader) are intact; session ids pass the UUID check before any path or glob is built.

Findings:

  1. Medium. An intake with a valid shape but a non-UUID session id was written at SessionEnd, then made the host import raise on every later hook, blocking all host cleanup. Not executed by the reviewer, reasoned from the code.
  2. Low. The README said a foreign intake is reported on stderr; it is filtered silently and left in place.
  3. Low. The ledger location and the CORTEX_CLAUDE_DIR variable changed without a migration note.
  4. Low. status fails on an invalid DISK_HYGIENE_CLEANUP value; consistent with the README, left as is.

Not verified by the reviewer: no test was run, and the real Codex tool_name values were not compared with SHELL_TOOLS.

@cdeust

cdeust commented Sep 26, 2026

Copy link
Copy Markdown
Owner Author

ZETETIC-REVIEW: APPROVE

Follow-up to the REQUEST_CHANGES verdict above, on head 4562db8. Findings 1 to 3 are fixed and finding 4 is accepted as documented.

  • Finding 1 (non-UUID session in the host intake): read_pending now reports and skips such a file for the host consumer and still returns it for the worktree consumer. test_non_uuid_session_intake_does_not_block_host_cleanup covers both consumers. The existing lifecycle test that relied on the old behavior now asserts that the file stays on disk.
  • Findings 2 and 3: the README states what happens to an intake recorded under other roots, and the README and CHANGELOG document the ledger move and the CORTEX_CLAUDE_DIR to CLAUDE_CONFIG_DIR rename.
  • Evidence: 253 tests pass locally, ruff 0.16.8 check and format are clean, and CI is green on 4562db8 (test, CodeQL, Analyze).
  • Still not verified: the real Codex tool_name values against SHELL_TOOLS, which needs a native Codex run after installation.

@cdeust
cdeust merged commit b2e007a into main Sep 26, 2026
3 checks passed
@cdeust
cdeust deleted the feat/disk-hygiene-plugin branch September 26, 2026 20:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants