Skip to content

Commit ea19acd

Browse files
Prithvi-Webclaude
andcommitted
handoff: session 9, and the next-session prompt
v5.0.0 is built, verified inside the asar, and installed. What the handoff records that a diff cannot: the seven fixes and what each was actually saying, the five defects the adversarial pass found in code already committed, and what was verified in the INSTALLED app rather than only in tests — a real gdu-turbo scan of a 512 MB synthetic tree holding 1.8 MB, matching lstat exactly, with the receipt printing −510.45 MB against it. Six traps this round paid for, all new: asar extract-file writing to the current directory (it overwrote package.json and left eight files in the repo root), bulk-replacing a version in package-lock.json bumping six third-party packages, zsh not word-splitting an unquoted $VAR so a hash check compared the empty digest to itself, a mutant that "passed" because its anchor never matched, -0 not equalling 0 under assert/strict, and renderFleet taking no arguments while switchView re-fetches over anything you stub. The next-session prompt is rewritten for whoever comes next: what is outstanding (the push, and the release the owner publishes), the four known gaps written up honestly rather than hidden, and the standing decisions so they do not get reopened. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent 1f9f1c2 commit ea19acd

2 files changed

Lines changed: 254 additions & 253 deletions

File tree

‎HANDOFF.md‎

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,141 @@
11
# TreeMap — session handoff
22

3+
## Session 9 — the seven number fixes, a CHANGELOG, and v5.0.0 (2 September 2026)
4+
5+
Shipped as **v5.0.0**, built, verified inside the asar, and installed at
6+
`/Applications/TreeMap.app`. The previous build is parked at
7+
`release/TreeMap-4.2.0-previous.app`. Gate: **2,412 tests · 0 fail · 3
8+
skipped**, typecheck clean, `build-ui --check` matches (112 parts).
9+
10+
**v5.0.0 is not yet pushed and not yet published.** The owner pushes; the
11+
GitHub release is theirs to publish and needs a `v5.0.0` tag before the
12+
in-app updater can see it.
13+
14+
### The seven, and what each one was actually saying
15+
16+
Every one was the app stating something untrue. All seven are red-first and
17+
mutation-proven; 47 mutants, 47 caught (7 needed a second attempt because the
18+
first version of the test was not evidence).
19+
20+
1. **Fleet pairing was brute-forceable.** The doc comment claimed "a million
21+
possibilities against a three-minute window and a rate limiter"; there was
22+
no rate limiter, and an audit had measured 33,966 guesses in three seconds.
23+
Now five wrong codes per machine and fifty in total, checked BEFORE the
24+
offer is looked up so a sixth attempt is refused even when it is right.
25+
Addresses are normalised (`::ffff:` stripped) or a dual-stack socket buys a
26+
second allowance. A withdrawn offer raises a line in the Fleet panel.
27+
2. **Offload said "need 0.0 GB"** about 30 MB. Both figures go through
28+
formatBytes now. The same line had a second untruth: the check refuses at
29+
bytesTotal × 1.02 but named the raw total, so inside that window it stated
30+
its own contradiction. The headroom is said out loud.
31+
3. **The Trends dashed line and the date beside it were two different fits.**
32+
The chart ran its own unweighted linreg while the date came from the
33+
server's recency-weighted one — and with status 'ok' the server slope is
34+
guaranteed positive while linreg could still come back NEGATIVE, so the
35+
chart could draw a descending tail, clamped to zero, beside "disk full
36+
~<date>". `forecastOk` (a boolean) became `forecastRate` (bytes/day, or
37+
null); the tail rises at exactly that rate.
38+
4. **Sparse files claimed space the disk does not hold** and the gap was
39+
blamed on clones. See the two-sided note below — this one was shipped
40+
wrong first and repaired.
41+
5. **Duplicates promised bytes trashing would not free.** The clone caveat is
42+
on screen on darwin, and after a trash the MEASURED delta is reported.
43+
6. **"Used" meant two different things.** Half was already done in 9c14572;
44+
six UI/report/tray sites still derived `total − free`. They read the
45+
published `usedDisk` now, and the receipt says "Free to you" and draws the
46+
reserve as its own band.
47+
7. **Two hard-link counts wore near-identical labels.** Relabelled, not
48+
recounted. A third row now reconciles them outright.
49+
50+
### What the adversarial pass found in work already committed
51+
52+
A 16-agent recon ran plan-then-verify on all seven. The verifiers were worth
53+
more than the planners, because they audited SHIPPED code:
54+
55+
- **The sparse correction was one-sided and therefore wrong.** It subtracted
56+
only the shortfall and ignored block slack — a small file OCCUPIES more than
57+
it claims. Measured: `/usr/bin` claims 224.0 MB and holds 84.1 MB (slack
58+
0.3 MB, so it was nearly right), but 3,000 fifty-byte files claim 0.14 MB
59+
and hold 11.72 MB, where the scan UNDER-counts by 11.58 MB and the one-sided
60+
line said nothing — leaving the whole difference in Unaccounted under the
61+
clone explanation the fix exists to stop over-using. The error equalled the
62+
slack on every tree tested. Now a signed delta, and the receipt line is the
63+
NET, which is also what the allocation panel two clicks away has always
64+
reported.
65+
- **The fleet alarm hid itself.** `renderFleet` early-returns for the disabled
66+
state and the alarm was only in the enabled branch — so turning the fleet
67+
off, the natural reaction, deleted the explanation.
68+
- **The 429 named the wrong machine.** That text is read on the machine that
69+
TYPED the code.
70+
- **A comment the fix made untrue.** `verifyPairingCode` still promised a
71+
wrong code never clears the window — true of one guess, false of fifty.
72+
- **The duplicates measurement skipped the commonest roots** (`/`, `/Users`
73+
fail a one-directional `startsWith(home)`) and survived into a cloud scan.
74+
75+
### Verified in the INSTALLED app, not only in tests
76+
77+
Driven over CDP against `/Applications/TreeMap.app` (never the dev Electron
78+
binary — Gatekeeper deletes it). A synthetic tree claiming 512.27 MB while
79+
holding 1.81 MB, built in the scratchpad; the owner's real folders were never
80+
scanned.
81+
82+
- `/api/capabilities` → 5.0.0; `/api/system` publishes `usedDisk`.
83+
- A real scan on the **gdu-turbo** engine (the default) reported
84+
`sparseFiles 1 · sparseBytes 512.00 MB · slackBytes 1.55 MB` — matching
85+
`lstat` ground truth exactly, with the symlink correctly excluded.
86+
- The receipt printed `sparseFiles −510.45 MB` against a `scanned` line of
87+
512.27 MB, so the statement now says the tree holds 1.8 MB — which is what
88+
`du -sh` says. `used + free + reserved === total` held.
89+
- Dashboard: "1 file claims 512.0 MB more than it takes" (verb agreeing), and
90+
on a three-name inode "2 extra file names (8.0 MB)".
91+
- Legend: "Free to you — 280.6 GB". No reserved band on APFS, correctly.
92+
- Duplicates: the clone caveat rendered under "up to 4.0 MB reclaimable".
93+
- Fleet alarm rendered in BOTH branches, in both themes, and vanished once a
94+
fresh code was on screen.
95+
- Offload against a real 20 MB volume: "this needs 30.0 MB plus a little room
96+
to spare, and only 19.3 MB is free".
97+
- No horizontal overflow at 640 / 900 / 1440, no `will-change` at rest, no
98+
backdrop-filter on the new surfaces, no console errors.
99+
100+
### Traps this round paid for
101+
102+
- **`asar extract-file` writes to the CURRENT DIRECTORY**, not stdout. A
103+
verification script that redirects its output silently overwrote the repo's
104+
`package.json` with the asar's stripped copy (no scripts — `npm test`
105+
became "Missing script: test") and littered eight extracted `.js` files into
106+
the repo root. Read an asar by parsing its header in Node instead; there is
107+
a working reader in this session's scratchpad.
108+
- **Replacing every `"version": "4.2.0"` in package-lock.json bumps
109+
DEPENDENCIES.** Six third-party packages were moved to a version that does
110+
not exist. Only two nodes describe TreeMap: the lock root and
111+
`packages[""]`.
112+
- **`shasum -a 256 $FILES` with an unquoted zsh variable is one bogus
113+
filename.** shasum errors, and the empty-string digest is compared to
114+
itself — a restore check that always passes. This is the same trap the
115+
prompt warned about, met in a new place.
116+
- **A mutant that "passes" may not have been applied.** One gdu mutant
117+
reported green because its anchor did not match and the file was never
118+
changed. Assert the anchor count inside the mutation script.
119+
- **`-0 !== 0` under `assert/strict`** (Object.is). A measured zero produced
120+
by negation must be normalised.
121+
- **`renderFleet()` takes no arguments** — it reads `state.fleet.data`. And
122+
`switchView('fleet')` re-fetches, overwriting anything you just stubbed.
123+
124+
### Left undone, deliberately
125+
126+
- **A fast rescan under-counts the claimed-versus-held line.** Unchanged
127+
folders are read from the previous scan and not re-measured, and no
128+
per-node allocation is persisted. The line says it is a floor. Persisting
129+
allocation per node is the real fix.
130+
- **`reclaimableCaveat` / `reclaimableIsUpperBound` are still dead.** The
131+
server computes them; `/api/duplicates` and the MCP tool both drop them.
132+
The clone line on screen is the client's own darwin check, so those two
133+
fields remain unreachable. Merging them would mean two mechanisms for one
134+
sentence.
135+
- **Decimal vs binary bytes** and **Empty Folders listing `~/.Trash`** remain
136+
the owner's product decisions, per session 8.
137+
138+
3139
## Session 8 — the polish round (2 September 2026)
4140

5141
Owner: "pushed it, check the ci. and polish anything you need to. Make this

0 commit comments

Comments
 (0)