Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
1001d20
build(appstore): AppStore configuration for the Mac App Store track
Ti-03 Aug 25, 2026
73aeac9
fix(sandbox): resume the last scanned folder from a security-scoped b…
Ti-03 Aug 25, 2026
9e77373
build: check in both distribution schemes
Ti-03 Aug 25, 2026
3fcd1d4
build(appstore): match how 1.0 was actually configured
Ti-03 Aug 25, 2026
81ae915
docs(adr): record the superseded MacDirStat-appstore clone and its re…
Ti-03 Aug 25, 2026
97ef5a2
build(appstore): declare ITSAppUsesNonExemptEncryption=false
Ti-03 Aug 25, 2026
863a5ac
fix(scan): count every byte by default; collapse generated trees inst…
Ti-03 Sep 8, 2026
4b9f716
fix(scan): resolve symlinked roots, probe Full Disk Access with open(…
Ti-03 Sep 8, 2026
cd092d2
fix(ui): surface errors, keep the chart drawable and navigable, stop …
Ti-03 Sep 8, 2026
4ebf13e
fix(vm): stop stale async work from clobbering a newer scan; keep dup…
Ti-03 Sep 8, 2026
81a9ca9
fix(chart): labels never overlap, spill, or hide under the center dis…
Ti-03 Sep 8, 2026
7647f0d
fix: incremental duplicate detection, trash off-main, summarized dirs…
Ti-03 Sep 8, 2026
4a7c0d8
fix: migrate the persisted hide-hidden-files default, drop the banner…
Ti-03 Sep 8, 2026
b6f7e3b
release: 1.4 build 11, date the changelog
Ti-03 Sep 8, 2026
b55ee9f
docs(release): 1.4 build 11 App Store prep report and What's New text
Ti-03 Sep 8, 2026
bf76813
release: 1.5 build 12 (App Store Connect already holds an approved 1.4)
Ti-03 Sep 8, 2026
67f27c5
release: 1.4.1 build 12 (patch: fixes only)
Ti-03 Sep 8, 2026
3230c2c
fix(build): disambiguate the label-placement trig for older SDKs
Ti-03 Sep 16, 2026
17f800a
docs: state the real minimum, macOS 13 Ventura
Ti-03 Sep 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .agents/research/2026-09-08-appstore-whats-new-1.4.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Totals you can trust, and a long list of fixes.

• Every byte is counted. DirStat no longer skips hidden folders or dependency folders like node_modules, .git and DerivedData by default. On a real project folder the total went from 40 MB to the correct 7.5 GB; on a whole Mac it now matches what Finder reports as used.
• Dependency and cache folders collapse into a single row instead of thousands of tiny files, so scans stay fast and the chart stays readable.
• The duplicate finder no longer reports two different files as duplicates when they merely share a size and a first chunk.
• Errors are shown instead of silently ignored: failed scans, saves, exports and moves to Trash now tell you what happened.
• The chart no longer comes up empty for folders with hundreds of similar files, labels no longer overlap, and collapsed folders can't be opened into a dead end.
• Live refresh and Move to Trash no longer stall the window on large folders.
• Many smaller fixes: readable selection in light mode, unit changes apply immediately, "1000.0 KB" reads "1.0 MB", and more.
72 changes: 72 additions & 0 deletions .agents/research/2026-09-08-release-prep-v1.4.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Release Prep Report — v1.4.1 (Mac App Store)

**Date:** 2026-09-08
**Version:** 1.4.1 (Build 12)
**Release Type:** Patch (fixes only)
**Status:** Ready to upload (package built and signed; upload needs the account holder)

## Version Bump

- [x] MARKETING_VERSION: 1.4 → 1.4.1 (App Store Connect already has an approved 1.4, build 10)
- [x] CURRENT_PROJECT_VERSION: 10 → 12
- [x] CHANGELOG 1.4.1 dated 2026-09-08

## Build artefacts (gitignored, in `build/AppStore-1.4.1-12/`)

| File | Purpose |
|---|---|
| `DirStat-1.4.1-12.pkg` | App Store Connect upload package, signed "3rd Party Mac Developer Installer", app signed "Cloud Managed Apple Distribution", profile "Mac Team Store Provisioning Profile: com.macdirstat.app" |
| `DirStat-1.4.1-12.xcarchive` | The archive (Sparkle stripped: no Frameworks dir, no Sparkle load command; sandbox + user-selected read-write entitlements) |
| `exportOptions-appstore.plist` | `method=app-store-connect`, `signingStyle=automatic`, team L4UH9K7AW4 |
| `WhatsNew.txt` | Copy-paste release notes for App Store Connect |

## Code readiness

| Check | Status | Notes |
|---|---|---|
| Tests | ✓ | 156 tests, 0 failures (`swift test`) |
| Both configs build | ✓ | Release (Developer ID) and AppStore |
| Debug prints outside DEBUG | ✓ | none |
| Blocking TODOs | ✓ | one design note in AtomicDirectorySummary, not a blocker |
| Deployment target | ✓ | macOS 13.0 |
| Verified on a real disk | ✓ | Developer ID build: 881.2 GB shown vs 880 GB Finder used |
| Sandboxed build driven by hand | ✗ | not exercised this session (open panel needs a human); last verified 2026-08-25 |

## Privacy & compliance

| Check | Status | Notes |
|---|---|---|
| Privacy manifest | ✓ | `PrivacyInfo.xcprivacy`, UserDefaults reason CA92.1, no tracking, no collected data |
| Required-reason APIs | ✓ | UserDefaults declared; `volumeAvailableCapacity*` is macOS-only (no reason required on macOS) |
| Third-party SDKs in store bundle | ✓ | none (Sparkle physically stripped) |
| ATS exceptions | ✓ | none |
| Entitlements | ✓ | sandbox + files.user-selected.read-write only |
| Export compliance | ✓ | ITSAppUsesNonExemptEncryption=false |

## App Store metadata

| Check | Status | Notes |
|---|---|---|
| App icon | ✓ | 16…1024 present |
| What's New | ✓ | `WhatsNew.txt` |
| Screenshots | ? | existing listing screenshots predate the label/list changes; refresh if desired |
| Support / privacy URLs | ? | verify in App Store Connect |

## Upload

Either drop `DirStat-1.4.1-12.pkg` on Transporter, or from the repo:

```bash
xcodebuild -exportArchive \
-archivePath build/AppStore-1.4.1-12/DirStat-1.4.1-12.xcarchive \
-exportOptionsPlist build/AppStore-1.4.1-12/exportOptions-upload.plist \
-allowProvisioningUpdates
```

where `exportOptions-upload.plist` is the export plist with `destination` set to `upload`. Then in App Store Connect: create version 1.4.1, attach build 12, paste `WhatsNew.txt`, submit for review.

## Post-release

- [ ] Confirm 1.4.1 live; existing store users get the legacy-defaults migration on first launch
- [ ] Watch crash reports 48 h
- [ ] Tag `v1.4.1` once the DMG track ships the same commit
89 changes: 89 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,95 @@
All notable changes to MacDirStat are documented here. Format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## [1.4.1] - 2026-09-08

A correctness release: the scan total is now right by default, and a long
list of user-visible bugs found in an end-to-end audit are fixed.

### Fixed

- **Totals were wrong by default.** The factory settings excluded `.git`,
`node_modules`, `DerivedData` and `.Trash` and skipped every hidden entry,
so a real 7.5 GB project scanned as 40 MB. Nothing is excluded now and
hidden entries are counted; dependency and cache trees (`node_modules`,
`.git`, `Pods`, `.next`, `.venv`, ...) are collapsed into a single row
instead of dropped. Existing installs that still carry the old default
list are migrated once; a customised list is left alone. Verified
byte-for-byte against `du`.
- The duplicate finder could report two different files as duplicates when
they shared the same on-disk size and first 64 KB (sparse or compressed
files), so "Delete All Duplicates" could trash a distinct file.
- Errors from scanning, saving, opening, comparing, exporting and trashing
were recorded but never shown; they now appear as an alert.
- A flat folder with a few hundred similar-size files drew an empty chart
labelled "This folder contains no files".
- Collapsed folders (`node_modules` and friends) could be drilled into,
leaving an empty chart with the Back control hidden.
- Purgeable space (local snapshots, evictable caches) was reported as
"Hidden & Unreadable Space" on volume scans; the figure now matches what
Finder counts as used. Full Disk Access is detected by actually opening a
protected file, on either TCC database (issue #24).
- A scan that finished while a newer scan or archive load was in progress
could install its results over the newer one, keep watching the old
folder, or flip a live scan read-only.
- Live refresh did its disk walk on the main thread (UI stalls during
builds) and could resurrect a folder that had just been trashed.
- Trashing while duplicate detection was still running left "Scanning for
duplicates…" spinning until the next rescan.
- Symlinked scan roots (`/tmp`, alias folders) failed with a raw error
instead of scanning their target.
- A full scan of the boot volume now accounts for every readable byte:
854.9 GB of 8.5 million items on a 907 GB container, with the remainder
being the Preboot and Recovery volumes plus purgeable snapshot space that
no file scanner can show. That remainder is reported as one synthetic
row, renamed from "Hidden & Unreadable Space" to "System & Unreadable
Space" now that hidden files are actually scanned. Verified in the
installed app: 881.2 GB shown for a volume Finder reports at 880 GB used.
- Existing installs also had 1.3's "hide hidden files" default persisted in
their preferences; the one-time migration now resets that too (a toggle
set afterwards is respected), which was worth another 260 GB on a real
home folder (~/.cache, ~/.ollama, .git, .Trash and friends).
- The "Full Disk Access required" banner no longer appears once the grant
is held: whatever is still denied then is root-only and no setting can
open it (issue #24). Locked folders keep their icon; Settings shows the
count.
- The file list said "Scanning…" for minutes after a large scan had
finished while safety tags were computed; tagging is now an incremental
path walk (no per-node URL) and the panel says "Preparing…" meanwhile.
- Live refresh re-hashed the entire tree for duplicates on every change
batch; it now hashes only the size buckets the changed folder touches,
and duplicate results are written on the main thread instead of racing
the views.
- Move to Trash runs off the main thread, so "Delete All Duplicates" over
thousands of files no longer freezes the window.
- Comparing two scans no longer lists every file under a folder as
"removed" when that folder became a collapsed summary between the two
scans; it reports the folder's own growth instead.
- Chart labels no longer print on top of each other or spill past their
arc ("PlugInsMediaProvMotionEffect.fxp"); long names are middle-truncated
to fit, labels that would be meaningless are dropped, and inner-ring
labels slide clear of the center disc instead of being cut off by it.
- The file list panel was narrow enough that names truncated to three
letters ("Fina…"); it now keeps room for the name column.
- Smaller polish: clicking empty chart space clears the selection (and the
30 fps pulse timer that ran forever after the first click); the synthetic
hidden-space row no longer offers Reveal/Copy Path/Trash or shows up in
the legend as "(directory)"; extensionless files are "(no extension)";
the legend recolors with the color scheme and sizes refresh when the
unit style changes; "1000.0 KB" now reads "1.0 MB"; selected list rows
are readable in light mode; expansion state and duplicate-group
expansion survive deletes; the sidebar Duplicates link that stranded the
user in the detail pane is gone; Export CSV is disabled with no scan
loaded; the toolbar shows progress while comparing.

## [1.4.0] - 2026-08-25 (Mac App Store)

- Back on the Mac App Store after 1.0: a sandboxed store configuration
built from the same source as the Developer ID release, with Sparkle
removed from the store bundle and "auto-scan last folder" carried through
a security-scoped bookmark. Full Disk Access features are hidden in the
store build, since a sandboxed app cannot hold that grant.

## [1.3.0] - 2026-08-04

A performance-focused release: the scanner, the in-memory tree, and live
Expand Down
Loading
Loading