v0.20.9
See CHANGELOG.md for full history.
-
Fixed — the new pointer-gesture safety check refused every GUI-driven command on every Mac. The check added just before this release asks whether anything is covering the point it is about to click or drag. It asked the question two ways and let the wrong answer win: macOS keeps invisible, click-through windows the size of the whole screen permanently in front of every application — Notification Center and the Dock on any Mac, and two more belonging to the login window — and the check counted those as something being in the way. So
area reorderand the--dangerously-drive-guirepeat verbs refused with "Notification Center owns the screen", or "Dock", having sent nothing, every time.The reliable answer, which the check was already getting and then discarding, comes from asking the window server what a click at that point would actually reach; it knows which windows pass clicks through and which do not. That answer now decides. The window list is consulted only when the window server has no answer at all, and there a window is ignored only if it both belongs to macOS itself and covers the entire display — so a notification banner, which is small and does swallow clicks, still stops the gesture and is named. Refs #676.
-
Developer-facing — the lab now runs its end-to-end suite under BOTH identities, including the one every real Mac uses. Every arm the lab had ever run executed its scripts directly, in the guest's own shell; a Mac with the helpers installed brokers the same scripts through
things-deputy, which refuses whole classes of them on purpose. Two releases shipped green in the lab and broken in the field on nothing but that difference.npm run lab:regressnow clones a new golden carrying the signed helper pair with its macOS permissions already granted, runs the write-layer suite through the helpers as well as directly, reports each arm by name, drives one real repeat-rule dialog through the broker, and requires a write attempted with the helper stopped to refuse rather than quietly run itself. Nothing about the shipped CLI changes; what changes is that the release gate can now be met inside a disposable virtual machine instead of on a real Mac. Refs #695, #696. -
Improved — on a Mac with the helpers installed, GUI-driven commands now wait for the app instead of the clock. Waiting for Things to finish something — a dialog to open, a section to rebuild — is either a matter of asking the app to say when it is done, or of guessing at a duration. Machines that drive Things directly have had the first since 0.20.7. Machines where the helpers carry the automation could not: the listener is a small watcher process, and starting one means running a command, which the helper refuses by design.
The helper now keeps the listener itself. It already has the permission the listener needs and it is already running, so there is nothing to start and nothing to refuse. Commands driven through the helpers now wait on the app's own notifications for the waits the command makes between steps — including the pause after picking a repeat frequency, which was the longest single wait a Mac could spend on
todo add-repeating.Two things this does not change. Waits that happen inside one step still count time rather than listen, because that half still has no way to reach the listener that the helper will permit — so this is a real improvement on such Macs, not the whole one. And a Mac with older helpers behaves exactly as it did: the command asks what the installed helper can do, is told it cannot host a listener, and runs the timed version. Updating is
bash scripts/build-helpers.sh, thenthings helpers install.things doctorandthings helpers statusboth name which of the two you have. Refs #695, #676. -
Fixed — a GUI-driven command that would have clicked or dragged inside another application now refuses instead, and names what was in the way. The commands that drive Things through its window —
area reorder, and the--dangerously-drive-guirepeat verbs — move the real mouse pointer to positions they read out of Things a moment earlier. If anything changed in between, those positions could belong to something else by the time the pointer arrived: another app brought to the front, a window moved over the Things sidebar, a screen lock, or the sidebar scrolled under the pointer. The gesture went where the pointer was pointing, which could be a text selection in another app, a file dragged somewhere in the Finder, or a browser tab torn off.Every synthesized click, drag and scroll now checks, in the same breath as sending it, that Things is the front application, that the point is inside Things' own window, that no other application's window covers that point, and that the thing under the pointer is still the row or control the command aimed at. If any of that does not hold, nothing is sent and the command says so — naming the application that owns the screen at that point, and the coordinates. A drag already under way re-checks before it lets go, and cancels the drag rather than dropping somewhere unintended.
It errs toward refusing: an always-on-top window over the sidebar will stop a reorder that might have worked. Re-run it with the window moved. The checks cost about 4 ms and a handful of reads per gesture, so nothing gets slower. Refs #676.
-
Fixed — clearing a reminder on a to-do that turned up in Today on its own no longer reports a failure for a change that worked.
todo update <ref> --when today --clear-reminderaimed at an item that arrived in Today by itself — a repeating series' current occurrence, or anything scheduled for today — removed the reminder and then saidverify-failed:mismatch, describing the item as being in Someday and in Today at once. Both readings were true and neither was wrong: an item Things puts in Today on its own stays marked the way it arrived until someone acknowledges it in the app, and that is the state the app leaves it in. The check now accepts it, so the command reports the success it achieved. Refs #699. -
Fixed — a reminder can be cleared while moving the item to Anytime, in one command.
todo update <ref> --when anytime --clear-reminderwas refused with instructions to saytodayoreveninginstead. Moving an item to Anytime already removes its reminder — an Anytime item has no date for a reminder to fire on — so the refusal was standing in front of the shortest way to do exactly what it recommended in two steps.--when anytimenow takes--clear-reminder. A reminder on a specific future date still cannot be cleared in place; that refusal is unchanged. Refs #699. -
Fixed —
--exceptionaimed at the wrong half of a repeating series now says which half, and what to do instead. Aimed at one of the series' occurrences it answered "this to-do is no longer a repeating series" and suggested retrying: the item was an occurrence of a live series, and an occurrence is already the exception — it can simply be edited. Aimed at the series itself, for a series that counts from each completion and so has no next date yet, it sent the caller to "one of its occurrences" without naming one, which is where the first message had just come from. Both now name the occurrence's id and the command to run on it. Refs #699.