# Product synchronization This is the synchronization entry point for **Mole CLI (macOS)**, branch `main` of `tw93/Mole`. Workflow and the four canonical product names are in [AGENTS.md](AGENTS.md#product-synchronization). Source review baseline: `3fdf4040`, with incremental review through `c5ca9f69` on 2026-10-15, Asia/Singapore. The initial source/record review did not establish runtime acceptance or release delivery; dated receipts below keep those layers separate. Record reconciliation on 2026-10-25 froze `main` at `2fb59782` and `windows` at `9c408d72`, both matching their remote refs after that initial fetch. Release candidate source heads are `main` at `8eb31131` and `windows` at `b04cb5ac`; dated earlier receipts below keep their original scope. ## Ownership - The two CLIs: the [Windows branch SYNC.md](https://github.com/tw93/Mole/blob/windows/SYNC.md) owns the shared CLI adaptation queue; the macOS entry links to it rather than duplicating rows. - Mole CLI (macOS) with Mole Mac: the app's root `SYNC.md` owns the detailed comparison. - Mole CLI (Windows) with Mole for Windows, and the two apps: Mole for Windows' root `SYNC.md` owns the detailed comparison. - App-owned records remain private. Public CLI records contain public behavior, source and tests only; never copy private catalogs, implementation details, support data or repository links here. Scoped follow-up on 2026-10-18: Mole CLI (macOS) `8f2671cd` adapts the scan-request lifecycle from Mole CLI (Windows) `b8b27771`, including macOS cache-return paths. The existing CLI-SYNC-04 entry in the Windows record owns this comparison. Local tests passed and source is pushed; [the audit record](docs/weekly-audit.md#2026-10-18-dual-cli-post-release-audit) separates source delivery from exact-head CI. This is not a new release or a review of the desktop apps. ## 2026-10-23 System-service signal identity Released (V1.63.0): `lib/optimize/tasks.sh` refreshes NotificationCenter through its current-user launchd service and mDNSResponder through the allowlisted label in its fixed system plist. Neither operation falls back to matching a process name. The two-CLI queue remains owned by the Windows branch record; its Optimize has no corresponding host restart. The private app-owned record tracks the app comparison separately. Old-source refusal/target tests fail as expected, all 141 targeted Optimize tests and the complete local check/test workflows pass. The public V1.63.0 source and isolated script update were verified on 2026-10-24; no live system-service restart was performed. Follow-up on 2026-11-05 (#1867): when macOS 27 refuses the launchd signal, Mole CLI (macOS) retries once as the `_mdnsresponder` account with `killall -u _mdnsresponder`. Mole Mac, Mole for Windows and Mole CLI (Windows) have no DNS cache refresh: Not applicable. ## 2026-10-25 Existing CLI capability follow-up Frozen sources: Mole CLI (macOS) `ba96efe8` on `main`, Mole CLI (Windows) `973c6e1d` on `windows`; both matched their tracking refs after fetch. App-owned comparisons retain their private source and test receipts. This batch changes existing cleanup, uninstall, optimization and status behavior, with no new command, flag, setting or background service. The two-CLI queue remains owned by the Windows branch record. Implementation commits are `797a484c` (uninstall) and `52c5a7fa` (cleanup/purge). `scripts/test.sh` reports all tests passed, `scripts/check.sh --no-format` passes, and the Go tests and `make build` pass. Clean uses one reclaim estimate for ordinary and bulk candidates: allocated file blocks, internal hardlinks once, and APFS private bytes for uncompressed files where available. Sparse logical lengths, external hardlinks and fully shared clone blocks no longer inflate that estimate. Symlinks are not followed; directory metadata is excluded, compressed/unsupported private-size probes fall back to allocated bytes, and separate candidates do not claim each other's hardlinks. Real file fixtures in `tests/file_ops_size.bats` cover the boundaries. This does not change Analyze's separate occupancy semantics or establish actual filesystem free-space gains after a Trash move. Named Application Support cache rows now reuse the process guard before sizing and at each sink. Purge keeps its seven-day activity threshold but requires a manifest, matching lockfile and installation record, retains dependency files newer than that record and live/unknown projects, and resolves Git without invoking an unconfigured Apple developer-tool shim. Game-library rows remain selectable in uninstall but do not start selected with `--with-data`. Analyze retains its existing explorer, live scans and safe deletion. GUI growth history, treemaps and MFT scanning are Intentional differences in this batch: the CLI cache is a bounded navigation cache, and changing hardlink/clone attribution between walks is not proof of growth. A future history feature needs a separately specified baseline and stable attribution contract. Status stays a compact read-only dashboard; no extra sensors, daemon or app control surface is added. Source changes and local regression tests are not a released package or destructive third-party app acceptance. Source follow-up verified before push on 2026-10-25: `9c33da94` repeats named/shared cache owner guards at the final removal boundary while preserving original path identity and outer exclusions, and checks purge activity before the final node-project protection probe. `fda12f48` isolates Bats and the test runner’s module-loading/install probes in runner-owned temp trees, normalizes the runner root physically and clears inherited temp memo values; it does not change production temp cleanup or remove existing temp residue. `e53abe03` stops inferring Healthy from low battery cycles when capacity is unknown, preserving known cycle warnings and separately reported system health. The complete `scripts/test.sh` finished with exit 0 and its own All tests passed summary; format/no-format checks and `make build` passed. Old-source regressions failed before the fixes. These are source/test receipts, not a released package or destructive app acceptance. The Windows owner records its parallel source follow-up (`87f26494`, `ebc7e23a`, `c0945edc`) separately. ## 2026-10-28 Simulator per-device data Implemented in source (Mole CLI (macOS), frozen at `d438a87c` on `main`): `clean_xcode_tools` now also removes, by whole directory, a shut-down simulator's MobileAsset downloads, unified-log stores, `Library/Caches` and the lock-screen poster store, matching Mole Mac's existing per-device cleanup. Before this, the CLI took only `data/tmp` inside a device, so a Mac holding 26 idle simulators kept tens of gigabytes Mole Mac would list. A leaf is listed only when non-empty, on a device whose `device.plist` reads shut down, with no link between the device folder and the leaf; the whole batch still waits while any simulator tool or booted device is active, and each leaf rereads its device before removal. Old-source runs of the two new tests fail; local check and test receipts are in the commit. Mole CLI (Windows) and Mole for Windows: Not applicable (no iOS simulators). Released in V1.66.0 (2026-10-30): the seven release assets passed checksum and attestation checks against `1a31e13c`, and a script install of V1.65.0 self-updated to 1.66.0; Homebrew core is pending upstream merge of Homebrew/homebrew-core#322217. Source-only safety follow-up on 2026-10-30 (`f8950db2`): simulator metadata is read as one complete XML snapshot, failed reads retain the device and signals cancel before later devices. The complete local macOS suite passes. This repair is not included in the V1.66.0 receipt above. ## 2026-10-29 JavaScript and Python tool caches Implemented in source (Mole CLI (macOS), `main`): `clean_dev_npm` keeps `~/.npm/_npx` in the default and custom npm caches because running npx commands load packages from it (#1870, `f954e2fd`); `~/Library/Caches/pnpm/dlx*` is hard-safety whitelisted while pnpm metadata is still cleaned by name (`c32c7274`); a failed or timed-out `bun pm cache rm` keeps the cache, and when uv or bun itself is unusable its default cache is removed directly only after a process probe confirms no `uv`/`uvx` or `bun` runs (`cf2482c5`). Old-source runs of the new tests fail; local receipts are in the commits. Released in V1.66.0 (2026-10-30): the seven release assets passed checksum and attestation checks against `1a31e13c`, and a script install of V1.65.0 self-updated to 1.66.0; Homebrew core is pending upstream merge of Homebrew/homebrew-core#322217. - Mole Mac: it already guards running npx packages at its own sink; the private app-owned record owns the detailed comparison. - Mole CLI (Windows): npx, pnpm dlx and uv are Not applicable, because `lib/clean/dev.ps1:Clear-NpmCache` only runs `npm cache clean --force` (which leaves `_npx`) and `pnpm store prune`, and there is no uv cleanup. Bun is Implemented in source (`3d2db78f`): `Clear-NpmCache` uses Bun's confirmed root and owner command, checks `bun.exe`/`bunx.exe` before mutation, and retains failed or unknown targets. Direct removal of the default cache is limited to an unavailable/unusable Bun with a confirmed idle owner. The existing [CLI-SYNC-17](https://github.com/tw93/Mole/blob/windows/SYNC.md) owns verification and delivery; no Windows package release is implied. ## 2026-11-01 Yarn Berry dependency retention Source-only repair of `21d44166` (included in V1.67.0): `clean_dev_npm` no longer automatically removes `~/.yarn/berry/cache`, whose archives Plug'n'Play projects load as installed dependencies. The existing clean-only shared protection also retains the root and descendants with default or custom whitelist files. Yarn Classic remains eligible, explicit uninstall keeps its separate reviewed-data policy, and saved Berry whitelist patterns remain custom entries after its unused menu row is removed. Producer and real-sink regressions fail on the old code; this is not a package release. Mole CLI (macOS): Implemented in source. Mole CLI (Windows): Implemented in source, owned by the [Windows branch synchronization record](https://github.com/tw93/Mole/blob/windows/SYNC.md); its platform-specific dependency roots are protected at the shared clean sink. Mole for Windows: Implemented by its existing review-only boundary. Mole Mac: Implemented by its existing review-only dependency boundary, verified against the current consumer. No private catalog or app implementation is transferred to this public record. ## Current disposition | Topic | Status | Source and next check | | --- | --- | --- | | Log-root traversal and late Git ownership | Implemented | `8811fcbd` and follow-ups `61756c27`, `f5b5a335`, `a5ba6e79`, `1c323dba`; `lib/clean/user.sh` and `lib/clean/caches.sh` recheck roots/ownership. The app-owned comparison must no longer call these unfixed. This record does not re-certify the full test suite. | | Offline and generated media | Implemented | `b364d17d`, `lib/clean/app_caches.sh`; preserve data that a user cannot regenerate from the cache alone. Windows paths retain their own policy: CLI-SYNC-01 implements Spotify preservation; CLI-SYNC-09 records explicit aged recordings as an Intentional difference and shared project-cache protection as Implemented. | | Uninstall review and configuration references | Implemented | `eb21fff1`, `lib/uninstall/config_refs.sh`; `c653d19e` now classifies personal data before sizing, reuses the bundle size within that preview and never sizes kept personal data. A fresh invocation measures again. Windows configuration references are Not applicable to its current registered-uninstaller/install-folder surface, as recorded in CLI-SYNC-06; no personal AppData review is added. | | Process CPU denominator | Intentional difference | `cmd/status/metrics_process.go` consumes macOS `ps` process CPU; both CLIs use one logical CPU as 100%. Do not divide by machine CPU count just to match a GUI. | | Unreadable whitelist | Implemented | `clean`, `purge` and `optimize` stop when the whitelist exists but cannot be opened, instead of running as if it were empty; `lib/core/base.sh`, `lib/manage/whitelist.sh`, `tests/manage_whitelist.bats`. | | APFS clone sizing in `analyze` | Released (V1.60.0) | `8aeddbbe`: file-by-file scans deduplicate fully shared clones, including files with hardlinks, by volume and clone id; edited clones count in full. Cache schema 9 invalidates earlier totals and list ordering. Folded directories and overview measurements retain bounded `du` estimates and can count shared blocks repeatedly; replacing them with per-file probes would change the fast-scan cost. The nine README copies state that boundary. | | Purge capability-probe cancellation | Released (V1.60.0) | `df2f5e06`: the dataless capability probe propagates interrupt and termination statuses before discovery can publish candidates; unsupported flags still use the ordinary find fallback. `tests/purge.bats` covers both signal statuses. | | Stable `analyze` ordering | Released (V1.60.0) | `8aeddbbe`: equal sizes tie-break by path both when a full heap selects survivors and when lists render; `cmd/analyze/live_scan.go`, `heap.go`. | | Battery temperature on macOS 27 | Implemented | `cmd/status/metrics_battery.go` falls back to `AppleSmartBatteryPack` when the top-level key is 0. | | Alibaba Cloud Security, Symantec and Broadcom | Implemented | Official-uninstaller and endpoint-security protection for `com.alibaba.security.`, never-orphan for `com.symantec.*` and `com.broadcom.*`. | | Audio plugin roots, Claude Code temp folders, SwiftPM checkouts | Pending (external ownership samples) | Retain installed plugins, authored checkouts, active state and session/history archives; existing SwiftPM cache cleanup is separate. Next check: obtain an affected user’s exact candidate root and owner, then inspect only that root with read-only `ls -ld`, a one-level `ls -la`, and `du -k -d 1`; capture each exit status and omit names/content that identify personal projects. Bound each command to 10 seconds with `/usr/bin/perl -e 'alarm 10; exec @ARGV or exit 127' -- `, and treat timeout or partial output as unknown. The missing evidence is a reproducible disposable leaf and its recovery/non-target contract, not a low capacity estimate. No magnitude cutoff is established; if size later decides inclusion, first approve a numeric reversal threshold under AGENTS.md Product Decision Filter and compare real-user samples against it. This pass adds no probe framework or automatic target, and the maintainer’s disk is not a population sample. | | Wallpaper render cache | Released (V1.60.0) | `Wallpaper agent cache` in `lib/clean/user.sh` now takes only exact `----.bmp` renders older than a week that are not a render of the newest picture of each display size or the newest overall, the same rule as Mole Mac; the rest of the agent container stays. Each run takes at most the 50 oldest renders under its own handle-probe budget, so a large backlog drains over several runs without starving the other container rows, and a folder with more than 20000 renders offers nothing. Before this the row took the whole folder: a 2026-10-15 real run removed 144.1MB including the current picture's renders. Tests in `tests/clean_user_core.bats`, observed red on the old code. | | Jupyter runtime connection files | Released (V1.65.0); Mole Mac Implemented (unreleased) | `16f5c5d7` keeps `~/.jupyter/runtime` out of the Python cleanup and protects it in `should_protect_path`; its files connect running kernels and servers. Mole Mac had offered it as a default-checked developer cache and now blocks it at both scan and deletion (2026-10-27). Tests are the two `Jupyter runtime` cases in `tests/clean_developer_state.bats`. Mole CLI (Windows): Not applicable. | | Conda install package caches (#1845) | Implemented; Mole Mac Intentional difference in scope | `clean_conda_metadata_caches` in `lib/clean/dev.sh` runs `conda clean --index-cache --tarballs --logfiles` for each install root. Mole Mac runs no third-party binary and offers only finished, day-old archives and the index cache as review rows. | | Gradle wrapper distributions of old versions | Intentional difference | Maintainer decision 2026-10-27: Mole Mac offers 30-day idle wrapper versions as unchecked review rows; the CLI has no unchecked review tier, so the same rows would become automatic removal. `clean_dev_jvm` keeps its current daemon, workers, notifications and build-cache scope. | | Mole temp leftovers in the Darwin temp root | Released (V1.65.0); Mole Mac Implemented (unreleased) | Mole Mac Clean now lists `mole.registry.` whose pid is gone and `mole.` plus six letters or digits (a one-link file or an empty folder) once a day old in the per-user Darwin temp root, where a killed CLI run leaves them and macOS never expires them (25,412 entries on the maintainer's Mac, 2026-10-27). The CLI now prunes the same two shapes under the same rules when it resolves that root, keeps any name a running registry still lists, and removes nothing when `ps` fails, in `prune_stale_mole_tmpdir_leftovers` (`lib/core/base.sh`); never `/tmp` or a TMPDIR pointed elsewhere. Tests `Darwin temp root prune takes only stale Mole registries and temp entries` and `Darwin temp root prune runs from temp root setup and keeps everything when ps fails` in `tests/user_file_ops.bats`, observed red under each removed gate. Source-only follow-up `f8950db2` also requires every live registry to be readable before pruning, locked by `Darwin temp prune retains every candidate when a live registry cannot be read`; it is not part of the V1.65.0 receipt. Mole CLI (Windows): Not applicable. | | Dead LaunchServices records | Intentional difference (maintainer decision 2026-10-27) | Mole Mac's Optimize unregisters records whose bundle is confirmed gone and recounts the registry afterwards. The CLI has no such step. Measured on macOS 27.0.1 on 2026-10-27: `lsregister -u` on an already-deleted fixture app exits 0 and its record leaves `lsregister -dump`, so the earlier note in `bin/clean.sh` that it always fails with -10814 no longer holds there; macOS 15 and 26 were not measured. The CLI does not add the step until a user reports stale records; the LaunchServices rebuild stays excluded. | | Top power process in `mo status` | Intentional difference | Mole Mac shows the process using the most power; `mo status` stays a compact read-only dashboard with top CPU only. | | AI data cleanup | Intentional difference | Maintainer decision 2026-10-15: no AI cleanup surface in the CLI. Rebuildable AI caches and old versions stay in `mo clean` (`clean_dev_ai_agents`, Claude Desktop and Codex cache rows); history, sessions, credentials, models and agent worktrees stay out. | | Intel code removal (`mo slim`) | Intentional difference | Maintainer decision 2026-10-19: CLI only. Mole Mac does not get it (small, update-restored savings that the app cannot explain safely in its UI); Mole CLI (Windows) is not applicable. `bin/slim.sh`, `.claude/rules/slim.md`, `tests/slim.bats`. The 2026-10-23 list follow-up keeps the existing shared selector, fits interactive/read-only rows to the terminal and supplies full names for search and sorting. Its shared menu now hides lower-priority hints to keep controls on one line, preserves the underlying shortcuts, and reserves the measured footer height; uninstall app and personal-data selectors inherit the same fix (`lib/ui/menu_paginated.sh`, `tests/menu_trap_restore.bats`). The slimming surface remains not applicable to the other products. The shared Bash menu fix does not introduce a slimming feature there. Released in V1.63.0. Revisit only on a new maintainer decision. | | Data volume alias paths | Released (V1.63.0); Mole Mac Intentional difference | `70d320e1` (#1814): `validate_path_for_deletion` judges a `/System/Volumes/Data/` path by the root path it reaches. Mole Mac consumer review on 2026-10-25 confirms its broader `/System` refusal retains an alias that keeps that spelling; canonicalized paths still face ordinary protection. No equivalent permissive alias normalization is needed. Mole CLI (Windows): Not applicable. | | Game and ROM libraries under `--with-data` | Released (V1.63.0) | `7b14de80` (#1806): `_uninstall_data_preselect_holdback` in `lib/uninstall/review.sh` leaves CrossOver and Whisky bottles and the OpenEmu library listed but unselected. Test `--with-data holds back CrossOver, Whisky and OpenEmu game libraries` in `tests/uninstall_review.bats`. Mole Mac already keeps these libraries out of automated removal, so this follows it. Mole CLI (Windows): its Steam library refusal already covers the Windows case; the three apps are macOS-only. | | Internal-volume refusal of `mo clean --external` | Released (V1.63.0); Mole Mac Not applicable | `f9dd8208` (#1818) introduced macOS 26 compatibility; the 2026-10-23 follow-up in `lib/clean/user.sh:validate_external_volume_target` now requires successful `diskutil info -plist`, a typed `Internal=false` and a nonempty local `BusProtocol`. Failed, timed-out, malformed or incomplete probes retain the volume; `lib/core/base.sh` also appends `/usr/sbin` and `/sbin` to PATH so `diskutil` and the other system tools are found. Tests `validate_external_volume_target refuses internal volumes and an empty answer (#1818)` in `tests/clean_user_core.bats` and `loading Mole appends /usr/sbin and /sbin to a PATH without them` in `tests/core_common.bats`. Mole Mac asks the file system for `volumeIsInternalKey` instead of parsing `diskutil` text. Mole CLI (Windows): not applicable. | | Touch ID line commented out in `sudo_local` | Released (V1.63.0); Mole Mac Not applicable | `69d2a3c7` (#1815) treats a commented `pam_tid.so` line as not configured, and `7b14de80` reads the PAM path overrides only in test mode. Tests in `tests/manage_sudo.bats` and `tests/cli.bats`. Mole Mac does not edit the sudo PAM files; Mole CLI (Windows) has no Touch ID command. | | Helium signing clones | Released (V1.62.0) | `lib/core/browser_clones.sh` admits `net.imput.helium.code_sign_clone` children with the same idle, handle and identity gates as Chrome; Mole Mac parity `BrowserClonePolicy.browsers`. Test in `tests/browser_clones.bats`, red-run on the loop list. Source `46b6d321` is in `V1.62.0`; the public script-channel source archive's `lib/core/browser_clones.sh` was downloaded and matched byte-for-byte against the tag on 2026-10-24. | | Brave signing clones | Released (V1.65.0) | `lib/core/browser_clones.sh` admits Brave Browser (`com.brave.Browser`, `.beta`, `.nightly`) and Brave Origin (`com.brave.Browser.origin`, `.origin.beta`, `.origin.nightly`) signing clones with the same idle, handle and identity gates as Chrome; ids and app names come from brave-core's `app/theme/brave*/BRANDING*` files. A Mac held 112 idle Brave clones of 19 versions, and removing them freed 12.0 GB. Test in `tests/browser_clones.bats`, observed red on the old code. Mole Mac: Implemented 2026-10-27 in `BrowserClonePolicy.browsers` with the same six ids, unreleased. Mole CLI (Windows): Not applicable. | | Edge and ego lite signing clones | Released (V1.65.0) | `lib/core/browser_clones.sh` admits `com.microsoft.edgemac` (Microsoft Edge) and `com.citrolabs.ego.lite` (ego lite) clones with the same idle, handle and identity gates as Chrome, routed from Mole Mac `BrowserClonePolicy.browsers` (2026-10-27): a user's Edge root held 2.2 GB of clones and ego lite left 1.3 GB behind a newer version. ego lite's helpers are named `ego Helper`, so the idle check also matches that name and the `ego lite.app` path. The executable names come from an installed ego lite and a recorded Edge process table. Test `browser clone cleanup reaches Edge and ego lite and retains them while either runs` in `tests/browser_clones.bats`, observed red on the old code. Mole CLI (Windows): Not applicable. | | Vesktop caches | Released (V1.66.0); Mole Mac Implemented (unreleased) | `clean_communication_apps` in `lib/clean/app_caches.sh` cleans Vesktop's `sessionData/Cache` and `sessionData/Code Cache` through `mole_safe_clean_app_cache`, which keeps both while any process runs from `Vesktop.app`. Vesktop moves Electron's session data below `~/Library/Application Support/vesktop/sessionData`, so the Discord row never reached it. `vencordFiles`, web storage, settings and themes stay. A Mac held 749 MB and 235 MB in those two folders (Vesktop 1.6.8). Test in `tests/clean_app_caches.bats`, observed red on the old code. Mole Mac: Implemented 2026-10-28 in its `communicationCaches` list (unreleased). Mole CLI (Windows): Implemented in source: `lib/clean/caches.ps1` cleans `sessionData` Cache, Code Cache and GPUCache guarded by `vesktop`. | | Futu NiuNiu update downloads | Released (V1.62.0) | `clean_futu_update_downloads` in `lib/clean/app_caches.sh` takes the children of the sandboxed `LiveUpdate/mac_qtnn` folder only, refuses a symlinked folder and re-asks `futu_running` (`FTNN` and its helpers) at every sink; no `should_protect_path` carve-out was needed. Mole Mac parity: the `Futu Update Downloads` row. Tests in `tests/clean_app_caches.bats`, red-run on the process pattern, the symlink check and the sink refusal. Source `7b2a1960` is in `V1.62.0`; the public script-channel source archive's `lib/clean/app_caches.sh` was downloaded and matched byte-for-byte against the tag on 2026-10-24. | | Live privileged helper without a bundle-id name | Released (V1.63.0) | `_plist_is_orphaned` in `lib/clean/apps.sh` asks `bundle_has_installed_app` about a still-present `/Library/PrivilegedHelperTools` helper only when its id is reverse-DNS (a `com.`, `org.`, `net.` or `io.` prefix, as the bare-helper pass); a plain name such as a cloud-print updater keeps its plist. Mole Mac parity `ee7c4ae4e` (`OrphanServiceScanner.plistIsOrphaned`). Test `clean_orphaned_system_services keeps a live helper whose name is no bundle id` in `tests/clean_apps.bats`, red on the old code. | | Live privileged helper built on this Mac | Released (V1.68.0, `58844259`); Mole Mac Implemented (unreleased); Mole CLI (Windows) Not applicable (no launchd services) | `_plist_is_orphaned` and the bare-helper pass in `lib/clean/apps.sh` count a present `/Library/PrivilegedHelperTools` binary as an app's orphan only when `_privileged_helper_is_developer_id_signed` (`codesign --verify -R` with Apple's Developer ID requirement) accepts it, so a user's clang-built, ad-hoc, self-signed or Apple Development helper stays (Mole Mac field report 2026-11-02). Mole Mac parity `OrphanServiceScanner.helperIsDeveloperIDSigned`. Tests `clean_orphaned_system_services keeps a live helper built on this Mac` and `clean_orphaned_system_services lists a bare helper only when it is Developer ID signed` in `tests/clean_apps.bats`, the second red on the old code. | | Feishu, WeChat and Codex caches from a work-Mac inventory | Released (V1.62.0); Codex in-app browser partition Intentional difference | Maintainer direction 2026-10-19. `clean_feishu_service_worker_caches` adds the `iron/users/*/profile_main` engine and the sandboxed `com.bytedance.macos.feishu` trees; `Caches/LarkShell` and the sandboxed container Caches go through `_feishu_disk_cache_delete_guard_allows` while Feishu and Lark are stopped. `clean_wechat_container_caches` takes `app_data/radium/web/profiles/*/{Cache,Service Worker/CacheStorage}`, admitted by `_is_wechat_web_profile_cache_child` in `should_protect_path`; IndexedDB, WebStorage and `radium/users` stay protected. Mole Mac takes the same paths plus Codex's `Application Support/Codex/Default/Partitions` cache leaves, which the CLI leaves out because its Codex cleanup stays out of Application Support. Tests in `tests/clean_app_caches.bats` and `tests/core_safe_functions.bats`, red-run before this change. Source `d8ad7973` is in `V1.62.0`; the public script-channel source archive's `lib/clean/app_caches.sh` was downloaded and matched byte-for-byte against the tag on 2026-10-24. | | Uninstall leftovers Mole Mac keeps but the CLI deleted | Released (V1.60.0) | Raycast `Caches/com.raycast.macos` (clipboard images) and `Caches/MullvadBrowser` (profile root) are opt-in rows like Spotify (`lib/uninstall/review.sh`); DevEco takes only `Caches/Huawei/DevEcoStudio*` and `Logs/Huawei/DevEcoStudio*`, never the shared Huawei roots; an executable named `Electron` names no app, so crash reports fall back to the app name, the running label skips it, and `force_kill_app` quits only by bundle id instead of `pkill -x Electron`; `mo clean` never offers `com.microsoft.autoupdate.helper` or management, security and VPN services (Mac's vendor tokens), checked before the binary probes so an installed helper is covered too. Tests in `tests/uninstall.bats`, `tests/uninstall_safety.bats`, `tests/clean_apps.bats`, each observed red on the old code. | | Embedded-id and vendor-nested Caches/Logs on uninstall | Intentional difference | Mac makes them review rows; the CLI keeps removing them with the confirmed uninstall. They are rebuildable caches and logs, no real collision has been found, and an extra opt-in row on many ordinary uninstalls costs more than it protects. Revisit with a real report. | | Uninstall data opt-in (`mo uninstall --with-data`, #1746) | Implemented; Mole CLI (Windows) Not applicable | CLI counterpart of Mole Mac's default-off "Remove data and settings with apps" setting. The flag only changes the starting selection of the personal-data review (`lib/uninstall/review.sh`): every row starts selected, the preview lists them under `Personal data to remove:`, `D` still deselects any of them and Enter stays the only confirmation. Browser profile roots and `~/Library/Group Containers` entries stay unselected, since the CLI cannot check App Group claimants; agent workspace roots and shared stores are never offered by the CLI, so nothing maps there. Local chat, VM and clipboard stores (WeChat, UTM, Maccy, Raycast) are preselected like Mole Mac's opt-in. Mole CLI (Windows) has no personal-data review. Tests in `tests/uninstall.bats` and `tests/uninstall_review.bats`, observed red on the old code. | | Opt-in rows Mac refuses (`~/.docker/buildx`, whole `AS/Code`, mGBA and Goose config, LM Studio cache, chat app stores) | Intentional difference | The CLI only removes them when the user selects them in the personal-data review; no automatic deletion. Revisit if a report shows a shared tool broken by a selected row. | | Leftover coverage from Mole Mac's tested-app cycle | Implemented for mechanisms; Intentional difference for broad preferences and private catalogs | The 2026-10-25 follow-up adds exact ShipIt/updater and crash SDK leaves, NativeMessaging manifests launching into the selected app, UUID containers owned by exact `MCMMetadataIdentifier`, and JetBrains Info.plist selectors with surviving-owner checks. Metadata, identity and reviewed selector evidence are rechecked before removal. `Preferences/.*.plist` remains excluded: a dot prefix alone does not establish ownership of independent products. Private per-app catalogs remain app-owned. Existing PLCrashReporter and name/version JetBrains support were already present. Source only, no new release. | | Updater staging copies in hidden folders | Implemented | Discovery and the sibling scan skip an `.app` below a dot-prefixed folder (`/Applications/.x-update/app/X.app`) so it is neither listed nor a surviving sibling; a hidden `.app` itself still counts. `bin/uninstall.sh`, `lib/uninstall/batch.sh`, `tests/uninstall_safety.bats`. | | Sandbox containers macOS refused to move | Implemented | A denied Trash move leaves the whole container, metadata plist included; only a root emptied down to that plist is a stub, so the rest is listed as `macOS denied access` and not counted as freed. `11ea4e27`, `lib/uninstall/batch.sh`, `tests/uninstall_safety.bats`. Mole Mac already kept a denied move as a failed row with no reclaimed bytes; the app-owned record holds that comparison (2026-10-15). The 2026-10-23 CLI follow-up bounds each direct/staging move and ownership handoff in `lib/core/file_ops.sh`, preserving recovery data and stopping later candidates on timeout; real-helper fixtures are in `tests/file_ops_mole_delete.bats` and `tests/uninstall_timeout.bats`. Released in V1.63.0. Mole CLI (Windows) uses `Move-MoleItemToRecycleBin` through COM rather than these shell commands; this patch does not establish a Windows recycle deadline. | | Bundle directory mtime moving while an app quits | Intentional difference | Reviewed 2026-10-25: keep the strict pre-removal identity check. No CLI reproduction establishes that a benign quit-time bundle rewrite needs an exception; an unexplained change must retain the app. Reopen only with a reproduction that distinguishes directory mtime from changed bundle contents and pins Info.plist identity. This is not an outstanding repair or authorization to weaken the guard. | | Symlinked `/Applications` entries, per-user pkg receipt payloads | Intentional difference | Both need a new sink (a pinned real bundle behind the link; `pkgutil --volume $HOME` leaves the CLI protects today) for one app each. Parked until a CLI report asks. | | Cask zap-declared home folders, signature-backed rows | Intentional difference | The CLI runs `brew uninstall` without zap and removes only exact bundle-id or app-name evidence. | | PlayCover apps, config-line leftovers, kept-reason accounting, unreadable-means-retain | Implemented | Already in the CLI (`mole_playcover_alias_target`, `lib/uninstall/config_refs.sh`, family retention causes). | | Steam library on uninstall | Released (V1.61.0) | `6c777967`: uninstall never offers `~/Library/Application Support/Steam` or anything in it, routed from Mole CLI (Windows) `3c8a6fee` (CLI-SYNC-14 on `windows`). `mo clean` keeps its exact cache leaves. | | Dry-run operation log rows | Intentional difference | `b4e27dae` records macOS dry runs as `-dry-run` sessions; Mole CLI (Windows) writes nothing in dry runs (CLI-SYNC-12 on `windows`). | | GUI-only capabilities | Intentional difference | Maintainer decision 2026-10-25: neither CLI adds third-party app updates, including a thin package-manager upgrade wrapper. A shared entry alone adds limited value, while reliable cross-source updates require ongoing identity, version, authorization and outcome handling. Prioritize existing cleanup, uninstall, optimization, analysis and status; `mo update` remains Mole self-update and `mo optimize` does not upgrade apps. Menu/tray and private leftover catalogs remain outside CLI parity. The two-CLI owner records this in CLI-SYNC-08. | Delivery checked on 2026-10-27: Mole CLI (macOS) [V1.65.0 Tidy](https://github.com/tw93/Mole/releases/tag/V1.65.0), tag source `308bf991`, is published. Check, Validation, CodeQL and Nix passed at that exact source, and [Release](https://github.com/tw93/Mole/actions/runs/40505553168) succeeded. Native macOS acceptance passed all nine steps and 23 smoke commands on macOS 27.0.1 arm64; the first attempt kept the IINA cache as a live user cache because a WebKit helper still held its `Cache.db` after the app quit, the correct refusal, and the rerun passed with no fixture remainders. All seven public assets passed provenance verification bound to the tag, source and release workflow; payload checksums, archive/raw equality, both architectures, minimum macOS 12.0 and native Analyze/Status probes passed. An isolated script installation upgraded from 1.64.0 to 1.65.0, retained the stable channel and an unknown user file, matched the tagged installed sources and public binaries, and reported current on a second update. The existing installation was preserved. Bilingual notes and six reactions were read back. [Homebrew core PR #321587](https://github.com/Homebrew/homebrew-core/pull/321587) is open and its source checksum matches the public tag archive; upstream merge and an installed Homebrew upgrade remain unverified. Previous delivery checked on 2026-10-25: Mole CLI (macOS) [V1.64.0 Steady](https://github.com/tw93/Mole/releases/tag/V1.64.0), tag source `8eb31131`, is published. Check, Validation, CodeQL and Nix passed at that exact source, and [Release](https://github.com/tw93/Mole/actions/runs/40185398618) succeeded. Native macOS acceptance passed all nine steps and 23 smoke commands, including Trash moves for the temporary IINA app, four leftovers and its installer, with no fixture remainders. All seven public assets passed provenance verification bound to the tag, source and release workflow; payload checksums, archive/raw equality, both architectures, minimum macOS 12.0 and native Analyze/Status JSON probes passed. An isolated script installation upgraded from 1.63.0 to 1.64.0, retained the stable channel and an unknown user file, matched the tagged installed sources and public binaries, and reported current on a second update. The existing installation was preserved. Bilingual notes and six reactions were read back. [Homebrew core PR #321158](https://github.com/Homebrew/homebrew-core/pull/321158) has merged; the official formula API reports 1.64.0 and its source checksum matches the public tag archive. An installed Homebrew upgrade was not tested. Mole CLI (Windows) [V1.39.0-windows Clarity](https://github.com/tw93/Mole/releases/tag/V1.39.0-windows), tag source `b04cb5ac`, is also published with `make_latest: false`; its [development record](https://github.com/tw93/Mole/blob/windows/docs/development-record.md#2026-10-25-v1390-windows-release-preparation) owns the completed CI, VM and ThinkPad acceptance, signed-package and public-download checks, successful 1.38.0 source upgrade and remaining package-manager rollout boundaries. Earlier delivery: GitHub's latest Mole CLI (macOS) stable checked on 2026-10-24 is `V1.63.0` (tag source `a7c4c84e`). Its seven public assets, attestations, archive members, minimum macOS 12.0 and an isolated script-channel update from `V1.62.0` were verified. [Homebrew core PR #320952](https://github.com/Homebrew/homebrew-core/pull/320952) merged on 2026-10-24, and the core formula points to V1.63.0 with the release workflow's source checksum. The public formula API still reported 1.62.0 at this check, so index rollout and an installed Homebrew upgrade remain unverified. The [weekly audit](docs/weekly-audit.md#2026-10-24-dual-cli-release-review-and-cancellation-repairs) owns the candidate, package and upgrade receipts. At that check, later source was not yet released. Previous delivery checks: `V1.62.0` (tag source `91a7bf44`) was verified on 2026-10-21 through its seven assets, attestations, archive members, minimum macOS 12.0 and a script-channel update from `V1.61.0`; Homebrew core PR #319945 was open at that check. The preceding stable was `V1.61.0` (tag source `122bf83c`, 2026-10-16). Consult the live release and exact commit ancestry before replying to users. Verification for the 2026-10-15 review fixes: `make build`, `go test ./...`, `./scripts/check.sh --no-format` and the full `TERM=xterm-256color MOLE_TEST_NO_AUTH=1 ./scripts/test.sh` passed. The full suite was repeated in an isolated checkout based on `81c12fd3` with the exact owned patch. These source changes shipped in V1.60.0. ## 2026-10-31 Mole CLI (macOS) clean output and temp-root listing Source: Mole CLI (macOS) `main` (this entry's commits). `prune_stale_mole_tmpdir_leftovers` now lists the Darwin temp root once, as one tagged `find` whose names never return to a command line, and leaves `mole.prune-stamp` there after a complete pass so the next listing waits a day (`mo --version` 1.89s to 0.15s on a root of 126,196 entries). The candidate rules are unchanged. The clean output changes (owner-command rows count measured bytes, 0B rows hidden, review rows link their label and state one fact, two-line summary) are CLI presentation only. Released in V1.67.0 (2026-10-31): the seven release assets passed checksum and attestation checks against `1e8b53e1`, and a script install of V1.66.0 self-updated to 1.67.0; Homebrew core is pending upstream merge of Homebrew/homebrew-core#322465. - Not applicable (checked 2026-10-31 against Mole Mac `main`): `TemporaryRootLeftoverPolicy` holds the same candidate contract (`.claude/rules/core.md`), but Mole Mac lists the root only inside a Clean scan the user started (`CacheScanner.temporaryRootLeftoverItems`, async under `metadataWalkTimeout`), not at every launch, so it never paid the per-command cost the stamp removes; a once-a-day stamp there would hide leftovers from a scan the user asked for. The stamp name matches neither candidate pattern, so the current Mole Mac policy leaves it alone. - Not applicable: the clean row wording and summary box; Mole Mac renders its own UI. ## 2026-10-31 Mole Mac safety follow-up Implemented in source (Mole CLI (macOS), `main` at `709efa56`), one commit each: `mo optimize` keeps Spotlight's own `EnabledPreferenceRules` switches and prunes only entries that look like a lowercase reverse-DNS bundle id (#1878, `ea7abfc9`); `clean_dev_ai_agents` removes a superseded Claude Code, cursor-agent or Copilot release only when the open-handle probe says no process holds it, and skips an open or unknown one by name (`fffa2ea3`); the uninstall summary in Trash mode states the size without calling it freed (`3bb0eae9`); `~/Library/Caches/llama.cpp`, where llama.cpp keeps `-hf` model downloads, is hard-safety whitelisted (`3b0f94df`); Mail attachment cleanup takes only a copy one folder deep that nobody wrote to since Mail made it, and asks again at the final sink (`709efa56`). Old-source runs of each new test fail; `scripts/check.sh --no-format` and the full `scripts/test.sh` suite pass. Released in V1.67.0 (2026-10-31): the seven release assets passed checksum and attestation checks against `1e8b53e1`, and a script install of V1.66.0 self-updated to 1.67.0; Homebrew core is pending upstream merge of Homebrew/homebrew-core#322465. - Intentional difference: Mole Mac moves Mail attachment copies to the Trash; `mo clean` removes them permanently like its other rows. The container copy under `Containers/com.apple.mail` stays protected by the CLI's blanket `com.apple.*` container rule, so on current macOS the CLI cleans only the legacy `~/Library/Mail Downloads`; opening the container is a pending maintainer decision. - Intentional difference: the CLI needs no Citro Labs vendor-folder fix, because it already cleans Chromium HTTP caches under `~/Library/Caches` while the browser runs and has no parent-folder row. - Not applicable to the CLI: Gradle wrapper usage proof (the CLI never cleans wrapper distributions), uninstall-kept data offered later (the CLI has no unticked review tier), Analyze auto-drill (the CLI has none), and the package-checkout HEAD proof (purge removes `.build` whole after its own activity and manifest checks). ## 2026-11-01 Release highlights after `mo update` Released (V1.68.0; Mole CLI (macOS), `main`): a successful stable `mo update`, through the installer or Homebrew, prints up to four changelog titles of the installed version from its GitHub release and the release link; nightly installs, non-terminal output and failed lookups print nothing, and the update's exit status is unchanged (`lib/core/common.sh` `mole_print_release_highlights`, `tests/update.bats`). Released in V1.68.0. - Mole Mac: Not applicable. Sparkle shows each version's notes before installing and the in-app What's New card lists them after. - Mole CLI (Windows): Implemented in source (`884eedc0`): after a pull that changes `VERSION`, `mo update` prints the published `V-windows` release's changelog titles and link. ## 2026-11-04 Byte sizes that round up to the next unit Released (V1.69.0; Mole CLI (macOS), `main`, `2335f055`, tw93/Mole#1914): `units.BytesSI` picked the unit before rounding to one decimal, so `mo analyze` printed 999,999 B as "1000.0 kB" where Finder shows 1 MB; a value that rounds to 1000.0 now moves up one unit (`internal/units/bytes.go`, `TestBytesSI`). Released in V1.69.0. - Mole Mac: Not applicable. Sizes go through Foundation's `ByteCountFormatter`, which picks the unit after rounding. - Mole CLI (Windows): Implemented (`f07253a7`). - Mole for Windows: Implemented (`912e4c50`). ## 2026-11-04 APFS snapshots from other backup apps Released (V1.69.0; Mole CLI (macOS), `main`, `a08c6885`, tw93/Mole#1916): Synology Active Backup, Carbon Copy Cloner and similar tools leave APFS snapshots on the data volume that pin deleted files like Time Machine ones, and Mole counted only `com.apple.TimeMachine.` names and probed only with Time Machine configured. `mo clean` now prints a read-only `APFS snapshots` row (count plus owner prefix) from `tmutil listlocalsnapshots /` whether or not Time Machine is set up, through `mole_local_snapshot_rows` in `lib/clean/snapshots.sh`; `mo analyze` counts the same names. Apple's other `com.apple.*` snapshots stay out, and nothing is sized or deleted. Released in V1.69.0. - Mole Mac: Implemented (`11ad35c68`). One read-only row names the owners, with no size and no delete; `PurgeableSpaceManager.snapshotCount` and `tmutil deletelocalsnapshots /` stay Time Machine's alone. - Mole CLI (Windows): Not applicable. Windows has no APFS snapshots; Volume Shadow Copies are a different mechanism and are not in scope. - Mole for Windows: Not applicable, for the same reason. ## 2026-11-05 Caches/Google left to its own rows Source: a 2026-10-28 support bundle from a Mac with only Mole CLI (macOS) 1.64.0: `~/Library/Caches/Google` failed on seven clean runs while Chrome and Google Drive ran. The generic "User app cache" sweep took the whole folder, Chrome's live HTTP cache included, past the Chrome row that waits for Chrome to quit. Implemented in source (Mole CLI (macOS), `main`, `d2341ba9`): the sweep skips `Caches/Google`; `clean_browsers` cleans `Caches/Google/Chrome` after Chrome quits and Android Studio keeps its own row. Locked by `clean_user_essentials leaves Caches/Google to the Chrome and Android Studio rows`, red on the old code. Next check: delivery in the next Mole CLI release. - Mole Mac: Already implemented (`coveredCachePrefixes` lists `Google`, so the generic scan never offers the folder). - Mole CLI (Windows): Not applicable (macOS path). - Mole for Windows: Not applicable (macOS path). ## 2026-11-05 Stored timestamps in the future Source: Mole Mac fixed a freshness window that read a stamp from the future (the system clock was set back) as fresh, so a stale answer lasted until the clock caught up. The rule is `0 <= age < window`: a negative age reads as expired. Released (V1.70.0; Mole CLI (macOS), `main`, `1493ee17`): the temp-root prune stamp (`prune_stale_mole_tmpdir_leftovers` used `find -mmin -N`, which matches a future mtime, so the daily pass was skipped), the Homebrew cleanup throttle (`brew_cleanup_ran_recently`), the pkgutil receipt cache (`lib/core/pkg_receipts.sh`), the uninstall metadata refresh TTL (the awk in `bin/uninstall.sh:_scan_finalize_index`) and the Analyze overview and scan caches (`cmd/analyze/cache.go`, through `stampWithin`) now treat a negative age as expired. Already guarded and unchanged: `check_for_updates` (`now >= checked`), the installed-apps cache in `lib/clean/apps.sh` (`age -ge 0`), the Status collector timers (in-process `time.Now()` values carry a monotonic reading). Age checks that decide whether to delete or list an old item keep a future-dated one, the safe direction, and are unchanged; so is the uninstall metadata lock, because stealing a live lock after a small clock step back is worse than waiting out its four-second retry. Bats cases in `tests/user_file_ops.bats`, `tests/clean_system_maintenance.bats` and `tests/uninstall_scan_bash32.bats` and Go cases in `cmd/analyze/cache_clock_test.go` fail on the previous code. Released in V1.70.0. - Mole Mac: Implemented there first (2026-11-05). - Mole CLI (Windows): Implemented in source for the installed-app inventory cache (`SYNC.md` on `windows`); its update-notice state was already guarded. - Mole for Windows: Implemented there in the same pass (2026-11-05), through one shared window helper and a source gate. ## 2026-11-06 T3 Code worktrees and preview caches Source: contributor PRs #1924 and #1925. T3 Code keeps agent checkouts in `~/.t3/worktrees` and a Chromium profile per preview browser under `~/Library/Application Support/t3code-v2` (`T3 Code (Alpha)` is the profile older builds left behind); both names match the T3 Code source (`resolveUserDataPath`, `PREVIEW_PARTITION_PREFIX`). Implemented in source (Mole CLI (macOS), `main`): `433fde60` adds `~/.t3/worktrees` to `MOLE_PURGE_DEFAULT_SEARCH_PATHS`, so `mo purge`, the `mo clean` project-cache sweep and the report-only "AI agent worktrees" row reach it; the worktrees themselves and the rest of `~/.t3` stay out. `b0dc6fef` adds `clean_t3code_desktop_caches`, which takes only `Cache` and `Code Cache` under `Partitions/t3code-preview-*` of those two profiles while no T3 Code app runs. Verified 2026-11-06 on the test Mac with T3 Code 0.1.7: running, a real-mode call removed nothing; quit, it removed the two leaves' contents, every other profile file hashed the same, and the app rebuilt them on relaunch; a real `git worktree` under `~/.t3/worktrees` lost only its ignored, week-old `target/` to `mo purge`, its tracked files stayed, and `mo clean` showed the 1.15GB report row. Next check: delivery in the next Mole CLI release. - Mole Mac: Implemented in source (2026-11-06): project artifacts inside `~/.t3/worktrees` and the same two preview cache leaves, withheld while T3 Code runs. The app-owned record owns the comparison. - Mole CLI (Windows): Implemented for the preview caches (`6088c9e3`, read in a VM on 2026-11-07). `.t3\worktrees` is not a `mo purge` root. - Mole for Windows: Implemented for the preview caches (`4f2dddb9`). It has no project artifact surface, so the worktrees are Not applicable. ## 2026-11-06 Docker on a local engine only, and running Electron caches Source: issue #1922 and a Docker Desktop 4.98 run on the test Mac. Every Docker query in Mole CLI (macOS) now reads the endpoint first (`mole_docker_endpoint_is_local`, `docker context inspect`, which never dials the engine) and skips a remote or unknown one; `mo clean` prunes BuildKit cache unused for 7 days and dangling images through Docker itself, only on a local engine that already answers; the Large files row drops types and reclaimable figures under 1MB. Separately, the generic Application Support sweep cleared Code Cache and GPUCache of running Electron apps (Docker Desktop, VS Code, T3 Code); it now skips a folder whose `SingletonLock` names a live pid. Implemented in source (Mole CLI (macOS), `main`): `4075102a` (Docker, I-38) and `8abe329d` (Application Support, I-39). Verified 2026-11-06 on the test Mac: stopped engine, no prune row and the 1.62GB Docker Desktop data row; running engine, the prune row and the shortened storage row, and Application Support down from 27.3MB to 16.2MB as Docker Desktop's caches stayed; `remote-tcp` and `remote-ssh` contexts, no engine query, the local data row, 17s instead of 25s. Next check: delivery in the next Mole CLI release. - Mole Mac: Not applicable for the endpoint gate and the daemon prune, since it never runs `docker` and a CLI owner command does not transfer by itself. Implemented in source (2026-11-06) for the running-app check: folders named `Code`, `Docker Desktop` and `t3code-v2` already answered to their running apps, and an Application Support folder that matches no running app is now held while the process its `SingletonLock` names is alive. The app-owned record owns the comparison. - Mole CLI (Windows): Not applicable. It never runs `docker`: `Clear-DockerCaches` keeps the build cache, and the running-app check is `Clear-MoleAppCache`'s named owners. - Mole for Windows: Not applicable. It never runs `docker`; its one Docker row is Docker Desktop's log folder, and every cache rule names its owner process. ## 2026-11-08 Purge configuration that cannot be read Source: PR #1947. `mo purge` stops with a cause and a next action when `purge_paths` exists but cannot be read, is a broken link or link loop, or is a directory, instead of treating it as missing and replacing the user's scope with discovered roots. Released (Mole CLI (macOS), `V1.70.0`): `ae5a6eb5` and `57f2f633`, merged in `7efe3e40`; `402ef6f5` keeps the shell error out of `mo clean`. - Mole CLI (Windows): Released in `V1.43.0-windows`, recorded in its `SYNC.md`. It never rewrote the file; it silently scanned the default paths. - Mole CLI (Linux): Implemented before this entry and Released in `V0.5.0-linux`. `lib/purge/scan.sh` already returns a refusal for an unreadable file. - Mole Mac: Not applicable. It has no purge paths file. - Mole for Windows: Not applicable. It has no purge paths file. ## 2026-11-09 Orphan data age reads the files inside Source: Mole CLI (macOS) `is_bundle_orphaned` and `orphan_cleanup_candidate_still_eligible`. Orphaned caches, logs and saved state now need every entry inside to be past the 30-day age, at discovery and at the final sink, not only the directory. The 30-day value itself did not change. - Mole Mac: Intentional difference. Its orphan rows have their own scanner and quiet period, start unchecked and go to the Trash. - Mole for Windows, Mole CLI (Windows): Not applicable. Neither has this directory-age check. ## 2026-11-09 Claude VM leftover evidence Source: Mole CLI (macOS) `is_claude_vm_bundle_orphaned` and `clean_orphaned_app_data`. The orphan check now accepts only a `*.bundle` directly under `Application Support/Claude/vm_bundles`, and its 7-day age walks every entry inside the bundle, at discovery and at the final sink, not only the directory. - Mole Mac: Not applicable. It protects `vm_bundles` and does not offer this row, on purpose. - Mole for Windows, Mole CLI (Windows): Not applicable. Neither checkout's code has this cleanup. ## 2026-11-07 Purge editor commands Source: PR #1940. `mo purge --paths` now runs an `EDITOR` that holds arguments, such as `code --wait`, and returns the editor's failure instead of reporting success. Implemented in source (Mole CLI (macOS), `main`): `4917abd1`, merged in `2cc4f227`. - Mole CLI (Windows): Not applicable. `bin/purge.ps1` opens `notepad.exe` directly and never reads `EDITOR`. - Mole Mac: Not applicable. It has no purge paths editor and never reads `EDITOR`. - Mole for Windows: Not applicable. It has no purge paths editor and never reads `EDITOR`. ## 2026-11-09 Buzz models in the user cache sweep Source: a 2026-11-09 review of model stores under `~/Library/Caches`. Buzz keeps downloaded Whisper models in platformdirs' cache folder, `~/Library/Caches/Buzz/models` on macOS (its FAQ names the folder; `BUZZ_MODEL_ROOT` overrides it), next to the plugins the user installed and their presentation CSS. The generic "User app cache" sweep removed the whole folder, the same shape as the llama.cpp store (`3b0f94df`). Implemented in source (Mole CLI (macOS), #1950): `~/Library/Caches/Buzz` joins `SAFETY_WHITELIST_PATTERNS`, so it holds under a custom whitelist too. Locked by `the user cache sweep keeps Buzz models and plugins even with a custom whitelist`, red on the old code. - Mole CLI (Windows): Not applicable. No generic `%LOCALAPPDATA%` sweep reaches Buzz's cache folder. - Mole CLI (Linux): Not applicable. Clean removes only allowlisted caches; an unknown `~/.cache` folder is listed, never selected. - Mole Mac: Implemented, `6c379a32c`: both block lists, the shape of llama.cpp. - Mole for Windows: Not applicable. Clean lists catalog rules and enumerates no `%LOCALAPPDATA%` folders; no Buzz or Puppeteer row exists. ## 2026-11-09 Puppeteer browser installs Source: the same 2026-11-09 review. Puppeteer installs the browser it launches into `~/.cache/puppeteer` and runs it from there; `clean_browsers` removed it as "Puppeteer browser cache" since `5a8d7666` (V1.23.2), the shape of ms-playwright, Camoufox and Cypress (#1400, #1941, #1945). Implemented in source (Mole CLI (macOS), `4cd5be26`): the row is gone and `should_protect_path` keeps the folder and its children. Locked by `should_protect_path applies high-risk cleanup denylist` and `clean_browsers calls expected cache paths`, both red on the old code. - Mole CLI (Linux): Same rule in `lib/clean/rules.sh` (`Puppeteer browsers`); removed by #1949 on `linux`. - Mole CLI (Windows): Not applicable. It has no Puppeteer row. - Mole Mac: Implemented. Its path guard and whitelist already keep `~/.cache/puppeteer`. - Mole for Windows: Not applicable. No Puppeteer row exists in its catalog. ## 2026-11-09 Clean write refusal and protected containers | Change | Destinations | Evidence and next check | | --- | --- | --- | | `mo clean` stops with a refusal when every folder it checks refuses a write, instead of ending on "Cleanup complete" with nothing removed; any other failure carries on, above all a full disk | Implemented (Mole CLI (macOS), `bab30aa8`); Implemented (Mole CLI (Windows), `3cd63f92`, with its previews fixed in `16eaba98`); Not applicable (Mole Mac, Mole for Windows: desktop apps with their own failure rows) | `tests/clean_core.bats`, incident I-53. | | An uninstall keeps a `Containers/` or `Group Containers/` folder holding an entry System Integrity Protection guards, so it never reaches the Trash, where it would fail every Empty Trash; asked only with Full Disk Access and only of the container's own folder | Implemented (Mole CLI (macOS), `f316ef8a`); Implemented (Mole Mac record); Not applicable (Mole for Windows, Mole CLI (Windows): no sandbox containers) | `tests/uninstall_remove_file_list.bats`, real probes of `/System/Library/Sandbox` and an ordinary tree. | ## 2026-11-09 Artifacts in use and lsof spellings Source heads read on 2026-11-09: `main` at `3feb1dd0`, `windows` at `cf28b442`, Mole Mac at `3d93c4f83`, Mole for Windows at `3c25648f`. | Change | Destinations | Evidence and next check | | --- | --- | --- | | A project artifact a running process uses is not offered or removed (#1958) | Implemented (Mole CLI (macOS), `6f2c0ce5`); Implemented (Mole CLI (Windows), `659bc206`); Implemented (Mole Mac, `32c2b1a71`); Not applicable (Mole for Windows: Clean has no project build output row) | Bats `purge_artifact_in_use`, `PurgeBoundary.Tests.ps1`, `testAProjectArtifactSomethingHoldsIsSeenAndAnIdleOneIsNot`. Mole CLI (Linux) is recorded on `linux`. | | `lsof` spellings of a non-ASCII or backslash path are read as the real name | Implemented (Mole CLI (macOS), `c73bb7c9`, `52dad8df`, `ab24a019`); Implemented (Mole Mac, `32c2b1a71`: it also decoded names for its container and AI scratch checks); Not applicable (Mole CLI (Windows), Mole for Windows: no `lsof`) | `testAHeldFolderWithANonASCIINameIsSeenInARealListingWithoutALocale` on real lsof. | | A packaged SwiftPM scratch folder is offered as its compiler output (#1955) | Implemented (Mole CLI (macOS), `1ae52ae5`); Intentional difference (Mole Mac: `.build/checkouts` is a known rebuildable layout, so the folder is already offered whole); Not applicable (Mole CLI (Windows): SwiftPM is not a purge pattern; Mole for Windows: no such row) | `clean-scanner.md`. | | A folder holding Epic games is not an uninstall leftover (#1948) | Implemented (Mole CLI (Windows), `3313adbe`); Implemented (Mole for Windows, `0b88ce85`); Not applicable (Mole CLI (macOS), Mole Mac: uninstall follows the app bundle and bundle-id leftovers, and no scan reaches `/Users/Shared/Epic Games`) | `AnEpicGameCountsAsContentAtTheGameFolderAndOneLevelInside`. | | Search matches every word (`1de902bf`), rows keep a long name's tail (`60a64902`), other apps' containers stay unmeasured without Full Disk Access (`157296a6`) | Implemented (Mole CLI (macOS)); Implemented (Mole CLI (Windows) and Mole for Windows: sources of the first two; Mole Mac: source of the third) | Pending for the third only. On the test Mac on 2026-11-10, with Terminal's app-data grant reset to undecided, a direct `du` of `~/Library/Containers/com.if.Amphetamine` blocked on the prompt, but `mo uninstall --dry-run` for Amphetamine and WeChat finished in about 9 seconds on both `157296a6` and the parent `323e2171`: discovery stops at `Shared leftovers kept (some paths unreadable)` before any container `du`, so neither sample tells the versions apart. Both prompts were then denied, which restores the earlier state. Next check: an app whose leftovers stay readable without Full Disk Access. | ## 2026-11-10 Three-CLI review Source heads read on 2026-11-10: `main` at `1baecd15`, `windows` at `075215a8`, `linux` at `cf42a724`. Fixes landed as `main` `2ed8427b`..`dfd0e583`, `linux` `210e3932`..`15e995aa` and `windows` `06b07a9d`..`46c53900`; the `main` commits shipped in V1.71.0 and the `linux` commits in V0.6.0-linux, both on 2026-11-10 (assets checked against `SHA256SUMS` and, for V1.71.0, their attestations; a script install of the previous version updated to each with `mo update`); the `windows` commits shipped in V1.44.0-windows the same day, signed and checked the same way. Mole Mac and Mole for Windows were not reviewed; the rows name what each should check. | Change | Destinations | Evidence and next check | | --- | --- | --- | | A test-only path seam cannot redirect cleanup in a real run | Implemented (Mole CLI (macOS), `2ed8427b`: `mole_test_path_override` honors seven seams only under `MOLE_TEST_MODE` / `MOLE_TEST_NO_AUTH`); Implemented (Mole CLI (Linux), `210e3932`: seven locations are globals set at load, never read from the environment); Not applicable (Mole CLI (Windows): the only environment values its product code reads are `MOLE_DRY_RUN`, `MOLE_DEBUG`, `MO_NO_OPLOG` and the `MO_ANALYZE_PATH` handoff, none a cleanup root; grep for `$env:MOLE_` and `$env:MO_` on `075215a8`) | `test-only cleanup root overrides are read only through the test-mode guard` in `tests/dev_extended.bats`. Mole Mac: check whether a launch-environment variable can move a scan or deletion root in a release build. | | Deletion validation refuses when the protection rules are not loaded | Implemented (Mole CLI (macOS), `2ed8427b`); Not applicable (Mole CLI (Windows): `Test-ProtectedPath` is defined in `base.ps1`, which every sink loads, and already fails closed); Not applicable (Mole CLI (Linux): `mole_is_protected_path` lives in the same file as the sink checks) | `validate_path_for_deletion refuses every path when protection rules are not loaded` in `tests/core_safe_functions.bats`. | | Uninstall keeps Buzz models and holds back virtual machines, bottles and local-only chat stores | Implemented (Mole CLI (macOS), `5cbe27b7`: `Caches/Buzz` is personal data, UTM and VirtualBuddy stay unselected with `--with-data`); Implemented (Mole CLI (Linux), `210e3932`: native GNOME Boxes and Bottles, Signal, Element, Session, Jami, Flatpak Viber); Pending (Mole Mac, Mole for Windows) | `tests/uninstall_safety.bats`, `tests/uninstall_review.bats`. Next check: Mole Mac's uninstall review for `Caches/Buzz`, the UTM container and `Application Support/VirtualBuddy`; Mole for Windows for Hyper-V, VMware and VirtualBox disks inside an install or data folder. | | A sandboxed app's cache folder is narrowed like the native cache | Implemented (Mole CLI (Linux), `210e3932`: Flatpak and Snap caches keep JetBrains LocalHistory, Lutris sign-in state and the names native rules never clean; GPU shader caches there need `--gpu-shaders`); Not applicable (Mole CLI (macOS), Mole CLI (Windows): no rule takes a whole per-app cache home as one root; app caches are exact leaves) | `tests/clean.bats` on `linux`. | | The sudo gate never treats typed password characters as a skip | Released earlier (Mole CLI (macOS), the Space-skip cases in `tests/clean_core.bats`); Implemented (Mole CLI (Linux), `210e3932`: an ordinary key goes to sudo's prompt, and what was typed never reaches the shell); Not applicable (Mole CLI (Windows): elevation is a UAC prompt, no password is typed into the terminal) | `tests/clean_sudo_gate_pty.py` on `linux`. | | A middle-cut name stays inside its column on wide characters | Implemented (Mole CLI (macOS), `dfd0e583`); Implemented (Mole CLI (Linux), `c80d3da5`); Implemented (Mole CLI (Windows), `cd60e200`) | `TestTruncateMiddleNeverExceedsTheColumnBudget`. Found while porting `8098ac2c` to Linux. | | Byte sizes step up at a unit boundary (#1914), names measured by grapheme width, status resize guidance (#1904) | Released (Mole CLI (macOS), V1.69.0 and earlier); Implemented (Mole CLI (Linux), `c80d3da5`); Released earlier (Mole CLI (Windows), the source of the width change) | Linux forked the Go TUIs before these fixes and had no row for them. | | `purge --dry-run` and `uninstall --dry-run` preview without a terminal | Released earlier (Mole CLI (macOS), Mole CLI (Linux)); Implemented (Mole CLI (Windows), `06b07a9d`, CLI-SYNC-18 there) | `skills/mole/references/windows.md` still tells an agent to hand these commands to the user; update the skill, its plugin copy and both versions when a tagged Windows version ships this. | | `mo history` condenses the log before parsing, `mo status` reads disk metadata from one plist | Implemented (Mole CLI (macOS), `0afbb83c`, `59c274a4`); Not applicable (Mole CLI (Windows): `history.ps1` parses with .NET strings, status has no `diskutil`); Implemented, by another route (Mole CLI (Linux): its parser was already awk and the cost was appending every record to Bash arrays, so only the newest `--limit` records are passed on; its status reads sysfs, so the disk change does not apply) | Measured on an M5 Pro: 5 MB log 4.15s to 0.80s, `status --json` 0.53s to 0.44s. Linux, on the devbox with a 5 MB log: 1.8s to 0.1s. | | Exit code for an unknown command, and `mo history --json` keys | Intentional difference: Mole CLI (macOS) and Mole CLI (Linux) exit 1, Mole CLI (Windows) exits 2; macOS has `deletions`, `trashed`, `rebuilt`, Windows `operations`, `recycled`, `uninstalled`, Linux `operations`, `trashed` | Scripts already depend on each; the skill references document each schema (CLI-SYNC-19 on `windows`). | | `mo remove --dry-run` | Released earlier (Mole CLI (macOS), Mole CLI (Linux)); Implemented (Mole CLI (Windows), `bec984bb`, CLI-SYNC-19) | The preview is a `-DryRun` switch on `Uninstall-Mole` in `install.ps1`, so it runs the removal's own path; `mo remove` there now returns its script's exit code. | | Tuning and switches are not environment variables | Released earlier (Mole CLI (macOS): AGENTS.md treats a new variable as a setting); Implemented (Mole CLI (Linux), `954da7d7`: `MO_PURGE_PROBE_TIMEOUT`, `MO_PURGE_WALK_TIMEOUT` and `MOLE_NO_UPDATE_CHECK` removed, maintainer decision 2026-11-10); Not applicable (Mole CLI (Windows): it reads none) | The purge bounds are fixed globals and the update notice has no switch. |