Watch: snooze finished threads, name the files a file approval would edit, Settle on finished notifications, an instant launch from the saved feed, plain Loading states, and no more cancelled errors
Gateway / check (push) Successful in 9s
Gateway / image (push) Successful in 22s

Gateway: an approval push for a file change says which files it would edit
This commit is contained in:
gib committed 2026-11-02 14:45:34 -05:00
1 parent 4dc4e57dac
commit edc4b88990
35 files changed
+1162 -144

No files matched your search

+44 -4
View File
@@ -42,7 +42,8 @@ Allow moves a thread to working, a reply restarts a finished thread, and Settle
the feed. One card carries a subagent's request, so its Allow goes to the subagent's thread. Recent
holds 14 threads, so the feed shows its first 10 and a "4 more" row. The working cards show
activity lines, the Containerfile thread has two subagents, and "Fix hyprlock crash" has two older
pages behind Load earlier. The SwiftUI previews use it,
pages behind Load earlier. Two cards are file approvals, one with line counts and a preview and one
with the file name alone, and two finished threads are snoozed. The SwiftUI previews use it,
the pairing screen has a "Try the demo" button, and launch arguments open a screen directly:
```sh
@@ -61,8 +62,11 @@ status screens, the subagent card and thread, Recent with Settle all and the "N
Recent list, a finished thread with Settle, a running thread with Ask before acting, New thread
with its model list, the working cards' activity lines, All threads' hosts and a project's threads,
a thread's subagents collapsed and open, Load earlier with markdown, the changes line and Changed
list, search and its empty state, the complication's two modes, the Smart Stack widget, and a question
notification are rendered by `SnapshotTests` instead, which only run when given a directory:
list, search and its empty state, the complication's two modes, the Smart Stack widget, a question
notification, the Snooze until picker (`snooze-picker.png`), the Snoozed list (`snoozed.png`) and its
row under Recent (`feed-snoozed.png`), file approvals on the card (`approval-file.png`) and the thread
screen (`thread-approval-file.png`), and the feed shown from the cache (`feed-cached.png`) are rendered
by `SnapshotTests` instead, which only run when given a directory:
```sh
TEST_RUNNER_WC_SCREENSHOT_DIR=$PWD/screenshots xcodebuild -scheme WristCode \
@@ -87,7 +91,39 @@ Swipe a Recent row left, here or on the full list, or tap Settle under Reply on
row leaves at once and comes back with the error if its call fails. Settle all, on the Recent header
and the full list, is one `POST /v1/recent/settle` for every completed thread in Recent, including
those past the first 10. Failed threads stay. The completed rows leave at once, and the header says
so when the call fails or some threads did not settle.
so when the call fails or some threads did not settle. A finished notification has Settle too,
beside Reply and Open. It settles in the background without opening the app.
## Snooze
Snooze hides a finished thread from Recent until a time you pick, and the gateway brings it back on
its own. The Recent swipe has a violet Snooze beside Settle, and the thread screen has a Snooze
button beside Settle. Both open the Snooze until picker with four choices in the watch's time zone:
In 1 hour, This evening at 6 PM, Tomorrow at 9 AM, and Next week, which is next Monday at 9 AM. From
5 PM on, the picker leaves out This evening. Once `POST /v1/threads/:hostId/:threadId/snooze` succeeds, the thread leaves
Recent and the feed refreshes. When any thread is snoozed, a dim violet row under Recent counts them
and opens the Snoozed list (`GET /v1/snoozed`), where each card says when it wakes and swipes left
to Unsnooze.
## File approvals
A file-change approval names its files in place of the raw prompt, on the feed card, the thread
screen and the notification: "Wants to edit" and the file name, or "Wants to edit 3 files" with a
row for each. The line counts show on the right only when the gateway has them, and the thread
screen adds the first changed lines in red and green. Claude sends no diff before approval, so in
practice the name shows alone. Without files, the prompt shows as before.
## Loading and launch
Every screen that loads data shows a plain "Loading" until its first answer. Once a screen has
content, a refresh keeps it on screen, and a failed refresh only adds a small dim line under it.
The error and Try again replace the placeholder only when there is nothing to show. When a screen
goes away mid-request, the cancelled request shows no error.
On every refresh the app saves the last good feed as JSON in its caches folder, and it saves each
thread's detail when the thread loads. Launch shows the saved feed at once, with a dim "Updating" by the
count until the first refresh answers, and a thread opens on its saved detail while it loads.
Unpairing clears both. Demo mode never touches them.
## Activity, All threads and history
@@ -159,6 +195,7 @@ To add it: long-press the watch face, Edit, swipe to Complications, pick a slot,
| --- | --- |
| `WristCodeApp.swift` | App entry, root navigation, `WKApplicationDelegate` for APNs registration |
| `AppModel.swift` | Paired, demo or unpaired; navigation path; the feed; 401 sends you back to pairing |
| `FeedCache.swift` | The last feed and thread details on disk, for an instant launch |
| `API/GatewayClient.swift` | `GatewayAPI` protocol and the URLSession client |
| `API/Models.swift` | Codable mirror of the contract |
| `API/Route.swift` | Screens the app can open, and their `wristcode://` URLs |
@@ -167,6 +204,9 @@ To add it: long-press the watch face, Edit, swipe to Complications, pick a slot,
| `Demo/DemoGateway.swift` | In-memory gateway with fixtures |
| `Views/` | Pair, Feed, full Recent list, Thread, New thread, Status, and the mock B theme |
| `Views/BrowseView.swift` | All threads: hosts, a host's projects, a project's threads |
| `Views/SnoozeView.swift` | The Snooze until picker, the Snoozed row and the Snoozed list |
| `Views/FileEditRows.swift` | A file approval's files, counts and preview lines |
| `Views/Loading.swift` | Loading, and errors that never replace content |
| `Views/Markdown.swift` | Message text as styled text |
| `Views/StatusReport.swift` | What the status overview says: headline, issues worst first, healthy hosts |
| `Notifications/NotificationHandler.swift` | Categories `approval`, `finished`, `failed`, `input`, `host`, `test` and their actions |