feat(doctor|cli): aelf doctor --prune-dormant interactive deletion (#594) - #628
Conversation
Add a pure-detection function that returns per-project DBs idle for at least N days (default 30). Unlike #589's legacy-schema scan this flags both legacy and modern DBs — the criterion is dormancy, not schema. Empty DBs and unreadable schemas still surface; an idle empty DB is the cleanest prune target. Read-only DB connection per-DB, OSError-tolerant stat. The scanner is the only piece commit-1 ships; the actuation surface (--prune-dormant) and tests follow.
Wire the dormant-DB scanner from #594 commit-1 into the doctor CLI. The default action is dry-run (scan + list); --apply triggers y/N per DB before delete, with no --yes shortcut (issue body's 'never silent delete' constraint). Surface choices, with rationale on which the operator can push back during review: - '--prune-dormant' on the existing 'aelf doctor' parser, mirroring --gc-orphan-feedback and --classify-orphans. Avoids a new top-level 'aelf prune' subcommand that would conflict with future general-purpose pruning verbs. - '--apply' is reused (already gates --gc-orphan-feedback delete); same dry-run-by-default mental model. - '--idle-days N' for threshold override (default 30 from DORMANT_IDLE_DAYS_DEFAULT). Conservative: a project touched monthly stays out of the prune list. - '--projects-dir PATH' override for tests. Detection criterion: idle-threshold only. Filesystem-orphan check (project root no longer exists at recorded path) was the second option in the issue body but project_warm.py hashes the git-common- dir into a 12-char slug and stores no reverse mapping; rebuilding that mapping is a separate piece of work and is left as a follow-up under #594.
15 tests covering the two pieces from commits 1-2: Scanner (_check_dormant_dbs): - empty list when projects dir is missing - recent DBs are skipped - dormant DBs surface with row_count + size_bytes - legacy and modern schemas are both flagged (dormancy is schema-agnostic) - threshold boundary: idle_days=30 excludes 29d, includes 31d - empty DBs are pruneable (row_count=0) - DBs with no beliefs table are still flagged (row_count=0) CLI (_cmd_doctor_prune_dormant): - dry-run lists without deleting - --apply with 'y' deletes - --apply with 'n' preserves - --apply with empty answer preserves (locks 'never silent delete') - mixed y/n answers in one run - empty result reports cleanly - negative --idle-days returns exit 2 - EOFError on input preserves the DB
Add a 'Pruning dormant per-project DBs' subsection right after the legacy-schema migration block, since both surfaces operate on the same per-project DB layout. Documents: - the default 30d idle threshold and --idle-days override - the dry-run-by-default + --apply mental model - per-DB y/N confirmation with no --yes shortcut - schema-agnosticism (legacy + modern both pruneable) - relationship to 'aelf migrate' (migrate first, then prune)
New 'Added' bullet documenting aelf doctor --prune-dormant and the design choices (idle-threshold detection, dry-run by default, per-DB y/N with no shortcut, schema-agnostic, filesystem-orphan mode deferred).
There was a problem hiding this comment.
Sorry @robotrocketscience, you have reached your weekly rate limit of 2500000 diff characters.
Please try again later or upgrade to continue using Sourcery
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (4)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
PR-size soft capThis PR is over the advisory size threshold:
Bigger PRs collide with more open work, which under the parallel-session workflow tends to produce repeated This is advisory only — nothing is blocked. If the size is intentional (large refactor, module removal, generated code), apply the |
|
[claim:review:noether:2026-05-11T05:08:29Z] |
|
Approve. Verified:
Filesystem-orphan detection is correctly out of scope — the deferral is justified (project_warm hashes the abs path with no reverse mapping) and the follow-up shape is sketched in the PR body. Merging FF. |
|
[release:review:noether:2026-05-11T05:10:30Z] |
Closes #594.
Adds
aelf doctor --prune-dormantto identify and (with--apply) interactively delete per-project DBs under~/.aelfrice/projects/*/memory.dbthat have been idle for at least N days. Companion to the #589 legacy-schema scanner.Acceptance criteria
--idle-days N). The filesystem-orphan check listed in the issue body — "project root no longer exists at the recorded path" — was deferred:project_warm.pyhashes the git-common-dir absolute path into a 12-char slug and stores no reverse mapping, so rebuildingid → original-pathis a separate piece of work outside this PR's scope. Documented in the changelog and INSTALL.md.aelf doctor --prune-dormant. Lives next to--gc-orphan-feedbackand--classify-orphans(other doctor action flags). Avoids a new top-levelaelf prunesubcommand that would conflict with future general-purpose pruning verbs, and leavesaelf doctor --auto-fix(the third option) free for the auto-migrate follow-up that feat(doctor|cli): auto-migrate (or prompt-to-migrate) on detected legacy schema #593 is currently working.y/Nconfirmation per DB before deletion. Per-DB prompt; onlyy/yesdeletes. Empty answer (bare Enter) andEOFError(piped/dev/null) both preserve the file. There is no--yesshortcut — every deletion is per-DB and explicit, locking the issue body's "never silent delete" constraint.tests/test_doctor_prune_dormant.py. DB matching detection criteria → flagged; non-matching → not flagged;--noanswer → DB preserved; plus the threshold boundary, schema-agnosticism, empty-DB and missing-beliefs-table cases, mixed y/n answers in one run, and the EOF guard.docs/INSTALL.md— new "Pruning dormant per-project DBs" subsection right after the legacy-schema migration block.Verification
git log --format='%G?' github/main..HEAD→ allG(5 atomic SSH-signed commits).git merge-base --is-ancestor github/main HEAD && echo FF→ FF.uv run pytest -q→ 3318 passed, 52 skipped.github/main...HEAD→ clean.uv run aelf doctor --prune-dormant --idle-days 0 --projects-dir /tmp/nonexistent→ "no per-project DBs idle for >= 0 days." (rc=0).uv run aelf doctor --prune-dormant --idle-days -1→ "must be >= 0 (got -1)" (rc=2).Atomic commits
feat(doctor): _check_dormant_dbs scanner + DormantDB dataclass (#594)feat(cli): aelf doctor --prune-dormant interactive prune (#594)test(doctor): dormant detection + prune-flow tests (#594)docs(install): document aelf doctor --prune-dormant (#594)docs(changelog): unreleased entry for #594 prune-dormantOpen question for review
The idle-threshold-only choice means a project root that was deleted from disk yesterday wouldn't surface here until its DB had also gone 30 days untouched. If that's a meaningful gap, the follow-up shape is: persist the originating absolute path in a sidecar (e.g.
~/.aelfrice/projects/<id>/.origin) when_warm_storefirst writes the directory, then_check_dormant_dbscan OR anot Path(origin).exists()flag in. Filing a follow-up issue if you want that — wanted to keep this PR scoped to the no-new-state-file path.Out of scope
aelf doctor --auto-fixumbrella surface.