Skip to content

[codex] Add generic three-stage residual cleanup - #2

Merged
clawdbot502 merged 22 commits into
clawdbot502:mainfrom
BruceL017:codex/generic-residual-cleanup
Jul 14, 2026
Merged

[codex] Add generic three-stage residual cleanup#2
clawdbot502 merged 22 commits into
clawdbot502:mainfrom
BruceL017:codex/generic-residual-cleanup

Conversation

@BruceL017

Copy link
Copy Markdown
Contributor

Summary

  • capture application/package identity before primary removal for every existing CleanApp source
  • add a bounded direct-child residual scanner with confirmed, review-only, and unverified results
  • add a second y/N confirmation for confirmed residuals and always run a fresh verification scan #3
  • add stat-verified residual deletion that never reruns package managers or follows final symlink targets
  • report cleanup status truthfully and document the three-stage one-command workflow

Safety boundaries

  • never recursively searches the full home directory or enters unmatched browser/other-application data directories
  • excludes shared Homebrew, npm, pnpm, Cargo, Go, pip, and uv caches/stores
  • protects approved-root containers such as ~/.local and ~/Library/Preferences/ByHost
  • merges physical root aliases so XDG symlinks retain system/platform/cache policy
  • captures only the main app and directly linked embedded bundles; foreign framework metadata is ignored
  • requires exact owned-path or owned-target evidence before a local-bin match is confirmed
  • never invokes sudo automatically; permission limits remain visible and non-fatal

Verification

  • full pytest suite: 169 tests passed
  • python -m compileall -q cleanapp tests
  • uv pip check
  • uv build produced sdist and wheel
  • uvx --from . cleanapp --version, rules, and doctor
  • final task-by-task and whole-branch code reviews completed with no remaining findings
  • every commit uses 253661133+BruceL017@users.noreply.github.com for author and committer

The implementation deliberately adds no Poe-specific rule; Poe's demonstrated residuals are covered by the generic identity-linked scanner while Chrome website data remains outside the scan boundary.

@clawdbot502 clawdbot502 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking safety issue: configured XDG roots can promote protected or overly broad locations into approved residual-deletion roots.

Reproduction against this PR on macOS:

XDG_CONFIG_HOME=/Applications python - <<'PY'
from pathlib import Path
from cleanapp.residual_scanner import is_approved_residual_path
print(is_approved_residual_path(Path("/Applications/Clash Verge.app")))
PY

This returns True. I also constructed a ResidualIdentity with the matching display name and an independent bundle signal; ResidualScanner(system_roots=()).scan(identity) placed that application in confirmed with display name Clash Verge evidence. The same root-policy gap applies to values such as /Users, /Library, /tmp, or another arbitrary high-value directory because _root_specs() only rejects roots under /System and /usr. validate_deletion() protects the broad root itself but generally permits its direct children, so the second residual confirmation can reach recursive deletion for a child of a misconfigured XDG root.

Please harden the root policy before merge:

  1. Reject configured XDG roots that resolve to protected/broad roots (reuse or align with safety.PROTECTED, including /, /Applications, /Library, /Users, /opt, /private, /tmp, /var, and the home container itself).
  2. Ensure is_approved_residual_path() independently enforces the same policy at deletion time.
  3. Consider making non-home XDG roots review-only unless they satisfy a narrowly defined ownership/scope policy.
  4. Add regression tests for hostile/misconfigured XDG values such as /Applications, /Users, and /Library, covering both scan classification and the deletion boundary.

The five CI jobs are green and the overall three-stage design is thoughtful, but a cleanup tool must fail closed when environment-controlled roots widen deletion scope. I cannot approve or merge this revision until this boundary is fixed.

@clawdbot502
clawdbot502 dismissed their stale review July 14, 2026 08:18

Superseded by repository-owner direction: broad and non-home XDG roots are an intentional cleanup capability. See the follow-up review comment for the revised safety requirements.

@clawdbot502 clawdbot502 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Repository-owner clarification — this supersedes the previous change request.

The following two requirements are withdrawn:

  1. Do not reject configured XDG roots solely because they resolve to broad locations such as /Applications, /Library, /Users, /opt, /private, /tmp, /var, or outside the current home. Thorough cleanup of explicitly configured local locations is an intended product capability.
  2. Do not automatically downgrade non-home XDG-root matches to review-only solely because they are outside the home directory. They may remain confirmed when the existing strong identity rules classify them as confirmed.

The earlier review has been dismissed. The intended safety contract is now capability-preserving:

  • Never delete the configured root itself; only direct children may become candidates.
  • Keep system-critical protections for /System, /usr, and the existing protected-path deletion boundary.
  • Weak, short-name, shared-container, and platform-managed matches must remain review-only.
  • Show every confirmed path and require the separate residual y/N confirmation before deletion.
  • At deletion time, independently revalidate the approved-root relationship plus device, inode, and file type captured during preview.
  • Never invoke sudo or silently elevate privileges.
  • Preserve inaccessible-root and failure reporting so the final result does not claim a complete cleanup when locations could not be scanned.

Tests for custom roots such as /Applications, /Library, and /Users should document this intentional behavior and verify the invariants above, rather than require blanket rejection. No change is requested merely for allowing broad or non-home XDG roots.

@clawdbot502 clawdbot502 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved under the repository-owner cleanup policy clarified in review 4692216120. Broad and non-home XDG roots are intentional capabilities; the implementation retains direct-child scoping, explicit residual confirmation, deletion-time device/inode/type revalidation, no automatic sudo, and truthful incomplete-scan reporting. All CI checks pass.

@clawdbot502
clawdbot502 merged commit 0f35f10 into clawdbot502:main Jul 14, 2026
5 checks passed
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