The (+) door stages gallery picks and camera shots as removable
chips against the daemon's own budget (eight a message, 5 MiB
decoded each, refusals surfaced, never silent drops); send reads
the files back as bare base64, the old {"text"} body unchanged
when there are none. Sent rows preview their staged files at once
and a replay fetches by attachment id like any attachment card.
Model options carry the vision badge only when the listing knows.
The diagnostics page showed the status job "waiting" while its runs
and the report-now kick died without a trace: any exception before the
first log line was invisible, indistinguishable from a job that never
starts. Every worker now wraps its run — a crash logs its type, message,
and first frame; a cancellation logs as such and rethrows. The screen
gains the report-now kick's own row (a one-time job's empty list is
"never run", not an error) and the tap lands in the log, so the next
stale-row mystery names its cause instead of hiding it.
A stale "last seen" had no client-side answer: a dead worker, a down
claw, and a claw that drops writes all looked identical from the
settings screen. The new page separates them: the WorkManager jobs'
live state (a cancelled schedule renders as "not scheduled"), the two
clocks — the phone's last landed report against the claw's last stamp
— whose disagreement names the broken end, auto-detected system checks
(battery optimization, background restriction, notifications) with
jumps into the exact settings page, a report-now kick, and a 200-line
in-memory flight recorder where every worker run logs its outcome.
A failed post returns retry(), which moves the next run onto
WorkManager's exponential backoff — 30s doubling, capped at five hours.
A couple of failures while the claw is unreachable is enough to leave
the fleet without a report for most of a day, which reads exactly like
the phone being gone.
The snapshot is only saved when every post landed, so the next
scheduled run re-derives the whole transition set and posts it again.
The fifteen-minute schedule is the retry; return success and keep it.
The fleet card reads last-seen from the claw, and only a landed report
moves it. Periodic work is deferred while the device idles — Doze
stretches the fifteen-minute floor to hours — so a phone sitting in the
human's hand could show itself as "last seen 3h ago" with nothing wrong
on the claw.
Kick a status run on resume, the same way the commands worker already
is, and reload the fleet whenever a run lands. The landed-run signal is
a new clock in StatusRepository, written in the same edit that saves the
snapshot (which only happens once every post of the run succeeded), so
the card reloads on a report that actually reached the claw.
The stored `colors` key names a palette — rhema (the default,
Jadeite), aquamarine, black-and-white, or dracula — and the
Appearance page of /settings cycles it live, like the theme and
icon toggles beside it. Each palette carries a dark and a light
appearance under the existing `theme` key; dracula's light side is
derived, the official palette ships only dark.
The appearance decision moves off token comparison: Theme now
answers is_dark() from the ground/text luminance, so palettes
beyond the original two get the right per-profile fallback tones.