Skip to content

fix(checkpoints): never auto-delete orphans on unattended startup sweep - #1

Closed
JoaoMarcos44 wants to merge 3 commits into
Frowtek:fix/checkpoint-prune-unreachable-workdirfrom
JoaoMarcos44:checkpoint-prune-startup-safety
Closed

fix(checkpoints): never auto-delete orphans on unattended startup sweep#1
JoaoMarcos44 wants to merge 3 commits into
Frowtek:fix/checkpoint-prune-unreachable-workdirfrom
JoaoMarcos44:checkpoint-prune-startup-safety

Conversation

@JoaoMarcos44

Copy link
Copy Markdown

Follow-up on top of your fix, @Frowtek — this closes the root cause your diagnosis pointed at, not just the parent-dir mitigation.

Why

Path(workdir).exists() == False is ambiguous: deleted project vs. an unmounted external volume / network share / VPN not yet up. Your PR already makes that check less aggressive for the legacy marker path. This PR removes the ambiguity entirely from the place it's most dangerous: the unattended startup sweep.

What changed

  • cli.py / gateway/run.py: the startup auto-maintenance sweep now always calls maybe_auto_prune_checkpoints(delete_orphans=False, ...). It still prunes by retention_days, size cap, and legacy archives — none of which require guessing whether a project was deleted or is just temporarily unreachable.
  • hermes_cli/config.py: dropped the now-unused delete_orphans config default.
  • hermes_cli/checkpoints.py: the explicit, human-invoked hermes checkpoints prune command now previews the orphan project list (workdir + commit count) and asks for y/N confirmation before deleting any of them, unless -f/--force is passed. --keep-orphans still works for a stale-only sweep.
  • Docs updated (EN + zh-Hans) to match.

No changes to tools/checkpoint_manager.py or its tests — this only touches the call sites, so it merges cleanly on top of your heuristic fix there.

Full credit to @Frowtek for finding, reproducing, and diagnosing this — this PR only exists because of that report.

JoaoMarcos44 and others added 2 commits July 22, 2026 15:53
Builds on this PR's diagnosis by @Frowtek: a missing workdir is
ambiguous (deleted project vs. an unmounted external volume / network
share / VPN not yet up), so it's not safe evidence for a destructive
GC sweep — especially one that runs unattended at startup.

- cli.py / gateway/run.py: the startup auto-maintenance sweep now
  always passes delete_orphans=False to maybe_auto_prune_checkpoints().
  It still prunes by retention_days, size cap, and legacy archives —
  none of which require guessing whether a project was deleted or is
  just temporarily unreachable.
- hermes_cli/config.py: drop the now-unused delete_orphans default.
- hermes_cli/checkpoints.py: `hermes checkpoints prune` (the explicit,
  human-invoked path) now previews the orphan project list and asks
  for confirmation before deleting, unless -f/--force is passed.
- Docs updated (EN + zh-Hans) to match.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
store_status()["projects"] only ever covered v2 metadata, so the
`hermes checkpoints prune` confirmation prompt was blind to pre-v2
base/<hash>/HEAD shadow repos that prune_checkpoints() deletes
separately via shutil.rmtree — a pre-v2-only or mixed store could
lose checkpoint history without ever hitting the confirmation.

Extract the pre-v2 scan into _pre_v2_shadow_repos() and have both
store_status() (preview, new pre_v2_projects key) and
prune_checkpoints() (deletion) read from it, so the CLI prompt can
no longer diverge from what actually gets removed.

Addresses review from egilewski on NousResearch#69141.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@JoaoMarcos44
JoaoMarcos44 force-pushed the checkpoint-prune-startup-safety branch from 73319fb to 64b65dc Compare July 22, 2026 18:54
… and mixed stores

Requested by egilewski on NousResearch#69141: the orphan confirmation flow had no
test coverage at all before this. Exercises hermes_cli.checkpoints.cmd_prune
directly against pre-v2-only and mixed (v2 + pre-v2) fake stores —
decline aborts with nothing deleted, accept deletes both layouts,
--force and --keep-orphans skip the prompt as expected.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@JoaoMarcos44

Copy link
Copy Markdown
Author

Closing this one — it was an alternative direct-merge path onto your branch, offered in case that was preferred over routing through main. Since then, per your review on NousResearch#69141, we dropped a4ba9c1a1 from the checkpoint-prune-startup-safety branch (it's redundant with your fix here, which is being tracked separately at 2b50037 on NousResearch#69063) and rebased that PR to stand on its own against main. That broke the ancestry this PR needed to merge cleanly onto your branch — reopening/fixing it here would mean re-adding a4ba9c1a1, which undoes what you asked for on NousResearch#69141.

NousResearch#69141 (NousResearch/hermes-agent) is the canonical path going forward — mergeable, no conflicts, will rebase onto main once NousResearch#69063 lands as discussed there. Thanks again for the diagnosis and reproduction that started all this.

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.

1 participant