Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .images-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v9
v11
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,24 @@ All notable changes to LitClock are documented here. Format loosely follows [Kee

## [Unreleased]

### Changed

- Two more quotes are classified as mature, so they now appear only on a clock with mature content switched on.

### Fixed

- Rebooting while the startup screen is still on the panel now paints the restart farewell. Before, the panel could stay frozen on the startup screen through the power-off, or show the shutdown farewell for a restart.
- After a settings reset, the reboot it asks you to perform paints the farewell screen again instead of leaving the previous quote on the panel.
- A quote refresh that lands while the clock is still starting up no longer fails outright — it waits for the startup screen to release the display.
- A blank or invalid nightly display-cleaning hour no longer freezes the panel; the clock falls back to the default hour and keeps painting.
- A clock with a location you typed in yourself no longer shows a permanent stale-location warning in Diagnostics.
- On the setup page, the box for typing a hidden network's name stays out of the way until you pick "My network isn't listed", so the form can no longer show two conflicting answers at once, and a name typed on an earlier attempt can no longer come back already filled in.
- Preparing an SD card for cloning now stops before it erases anything if your settings could not be wiped, so a refused run leaves the card untouched and the clock still working.
- Preparing an SD card for cloning now really clears the shell history, instead of having it written back when you close the terminal you ran it from.
- An update that fails its safety check is now remembered, so the clock stops downloading, failing and rolling back the same broken release every week.
- A weekly update check that could not reach the internet is no longer reported as a failed update needing manual recovery, and no longer moves the "Last update" date for an update that never happened.
- A rolled-back update no longer leaves the clock a minute behind, showing the previous minute's quote on every tick until the next update succeeded.

## [v0.227.0] - 2026-09-13

### Changed
Expand Down
273 changes: 254 additions & 19 deletions CLAUDE.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion TODOS.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

### LKG auto-revert (bootcheck.service) — follow-up to litclock-dev#209 — SHIPPED

**Filed as litclock-dev#493; merged to master 2026-07-10 (bundles into v0.217.0); hardware-QA-validated on the test Pi.** `litclock-bootcheck.service` consumes the litclock-dev#209 `lkg-sha` writer: per-boot "did the clock paint a frame since boot?" via the tmpfs render heartbeat (network-independent). Fail 1-2 auto-reboot to retry; fail 3 pins the last-known-good SHA and routes recovery back through `update.sh` rollback mode (full install — git + submodules + venv + units + sudoers + smoke — not a code-only `git reset`), then a terminal `bootcheck-gave-up` marker + re-flash splash bounds the sequence to ~4 reboots. Runs as `pi` on the existing `020_litclock-control` grants, so it works after litclock-dev#387 drops `010`. The end-to-end auto-reboot self-heal was proven unattended on real hardware (2 reboots → rollback → quotes returned). Closes the litclock-dev#82 brick-recovery prerequisite. See https://github.com/kapoorankush/litclock/issues/209.
**Filed as litclock-dev#493; merged to master 2026-07-10 (bundles into v0.217.0); hardware-QA-validated on the test Pi.** `litclock-bootcheck.service` consumes the litclock-dev#209 `lkg-sha` writer: per-boot "did the clock paint a frame since boot?" via the tmpfs render heartbeat (network-independent). Fail 1-2 auto-reboot to retry; fail 3 pins the last-known-good SHA and routes recovery back through `update.sh` rollback mode (full install — git + submodules + venv + units + sudoers + smoke — not a code-only `git reset`), then a terminal `bootcheck-gave-up` marker + re-flash splash bounds the sequence to ~4 reboots. Runs as `pi` on the existing `020_litclock-control` grants, so it works after litclock-dev#387 drops `010`. (Written when litclock-dev#387 planned that drop; it was **reversed 2026-07-12** and `010` is kept. Note the original claim was always narrower than it reads: bootcheck's own `sudo mkdir -p "$STATE_DIR"` is not in `020` and degrades via a fallback, and the `update.sh` rollback it routes into copies unit files on the blanket grant.) The end-to-end auto-reboot self-heal was proven unattended on real hardware (2 reboots → rollback → quotes returned). Closes the litclock-dev#82 brick-recovery prerequisite. See https://github.com/kapoorankush/litclock/issues/209.

### Text-fit row triage (P3 under litclock-dev#211) — shipped

Expand Down
2 changes: 1 addition & 1 deletion docs/plans/lkg-bootcheck-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Per the TODO wording ("reverts … after 3 consecutive failed boots, then reboot
- When it arms a fresh `lkg-sha` (all gates pass, write succeeds): also clear `rollback-sha` (new code is now the known-good; old rollback target retired).

### Reboot authorization
`020_litclock-control` already authorizes `/usr/bin/systemctl reboot`. bootcheck runs as pi and uses the same scoped grant — no new sudoers entry, works after litclock-dev#387 drops `010`. Verify the exact authorized form (`reboot` vs `reboot --no-block`).
`020_litclock-control` already authorizes `/usr/bin/systemctl reboot`. bootcheck runs as pi and uses the same scoped grant — no new sudoers entry, and no dependence on the blanket `010` grant. (As planned, litclock-dev#387 was going to drop `010`; that was reversed 2026-07-12 and `010` is kept. The scoped-grant property is what matters and is unaffected.) Verify the exact authorized form (`reboot` vs `reboot --no-block`).

## Reboot-loop bound (safety)
Worst case: bad update → 3 natural power-cycles → revert + 1 reboot → reverted code also bad → 3 more cycles → give-up splash, no further reboots. Bounded. The give-up splash tells the user to reflash (last resort).
Expand Down
21 changes: 20 additions & 1 deletion docs/sd-card-cloning.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,20 @@ Complete the full installation on one Pi by flashing the released image (see [Fl

## 2. Prepare for Cloning

Run this as the **only open session** on the Pi: log out of every other shell
first (SSH sessions, tmux panes, a `sudo -i` root shell). The script clears the
bash history, but any interactive shell still holding history when the Pi
powers off writes it back to disk on exit, and that is what gets imaged onto
every card.

That rule cannot cover **the shell you run it from** — it is alive for the
whole run and writes its own history as it exits. The script covers that one
itself, by locking both history files against write-back until the clone's
first boot, and it now stops rather than continue if it cannot apply the lock.

Running over SSH is otherwise supported; only the WiFi question below requires
a local console.

```bash
sudo ./scripts/prepare-for-cloning.sh
```
Expand All @@ -21,12 +35,17 @@ This script will (and then power the Pi off):
- Optionally clear WiFi credentials
- Re-enable the first-boot setup service
- Clear logs and caches
- Clear the bash history, and lock both history files so no shell still open at power-off — including the one you are typing in — can write it back (the clone's first boot unlocks them). The run stops if either path cannot be cleared or locked.
- Clear the SSL certificates
- Delete the persisted setup-hotspot password, so no clone carries your key
- Disable SSH, so clones ship in the same posture as a fresh flash (to get back into a clone: put a blank file named `ssh` in the SD card's boot partition)

If any of those steps cannot finish, the script says so in red and stops rather
than reporting success. Do not clone a card it refused. The one refusal you may
than reporting success. Do not clone a card it refused. If the API-key and
location wipe itself fails, it stops right there, before asking about WiFi, and
nothing on the card has been changed at all — the clock still works and still
boots normally. Fix the cause (usually the control PWA still holding
`env.sh.lock`) and run it again; the PWA comes back on the next boot. The one refusal you may
not SEE is the final SSH-disable check when running over the network (output is
cut before it, deliberately) — its tell is a Pi that has not powered itself off
within a minute of your session dropping; do not image that card either, and
Expand Down
8 changes: 4 additions & 4 deletions image-gen/litclock_annotated.csv
Original file line number Diff line number Diff line change
Expand Up @@ -1573,7 +1573,7 @@
08:29|8:29|Mr. Trent himself followed a rigid routine. Each day, he arose at 7 a.m., breakfasted at 7:30, and departed for work at 8:10, arriving at 8:29.|The Great Train Robbery|Michael Crichton|NO
08:30|half-past eight|"""What nonsense!"" thought Vronsky, and glanced at his watch. It was half-past eight already."|Anna Karenina|Leo Tolstoy|NO
08:30|8:30 A.M.|At 8:30 A.M. Filomina walked into the Ale House white, round, and heaving from the extra hundred and forty-six pounds she carried on her small frame.|Pomegranate Soup|Marsha Mehran|NO
08:30|eight thirty|"At eight thirty, I called and said, ""I've been thinking I might get a boob job, just take them clean off. What do you think? Could I pull off the flat-chested look?"""|My Year of Rest and Relaxation|Ottessa Moshfegh|NO
08:30|eight thirty|"At eight thirty, I called and said, ""I've been thinking I might get a boob job, just take them clean off. What do you think? Could I pull off the flat-chested look?"""|My Year of Rest and Relaxation|Ottessa Moshfegh|YES
08:30|half past eight|At half past eight Millicent Hammitt barged in, without a preliminary knock, to say goodbye.|The Black Tower|P.D. James|NO
08:30|half past eight|At half past eight, Mr. Dursley picked up his briefcase, pecked Mrs. Dursley on the cheek, and tried to kiss Dudley good-bye but missed, because Dudley was now having a tantrum and throwing his cereal at the walls.|Harry Potter and the Philosopher's Stone|JK Rowling|NO
08:30|Eight-thirty|Eight-thirty the ward door opens and two technicians trot in, smelling like grape wine; technicians always move at a fast walk or a trot because they're always leaning so far forward they have to move fast to keep standing.|One Flew Over the Cuckoo's Nest|Ken Kesey|NO
Expand Down Expand Up @@ -1980,7 +1980,7 @@
10:00|Ten|. . .the clock ticked louder and louder until there was a terrific explosion right in her ear. Orlando leapt as if she had been violently struck on the head. Ten times she was struck|Orlando|Virginia Woolf|NO
10:00|ten o'clock|A new life opening up for me at the Villa Borghese. Only ten o'clock and we have already had breakfast and been out for a walk.|Tropic of Cancer|Henry Miller|NO
10:00|10 am|According to military records no US bombers or any other kind of aircraft were flying over that region at the time, that is around 10 am on November 7,1944.|Kafka on the shore|Haruki Murakami|NO
10:00|ten o'clock|Anyway, when he looked at his watch again it was ten o'clock. At ten o'clock she was lying on the divan with her boobies in her hands. That's the way he gives it to me-in driblets.|Tropic of Cancer|Henry Miller|NO
10:00|ten o'clock|Anyway, when he looked at his watch again it was ten o'clock. At ten o'clock she was lying on the divan with her boobies in her hands. That's the way he gives it to me-in driblets.|Tropic of Cancer|Henry Miller|YES
10:00|ten o'clock|At about ten o'clock in the morning the sun threw a bright dust-laden bar through one of the side windows, and in and out of the beam flies shot like rushing stars.|Of Mice And Men|John Steinbeck|NO
10:00|ten o'clock|At about ten o'clock the first tiny snowflakes came loitering down and settled on Jill's arm. Ten minutes later they were falling quite thickly. In twenty minutes the ground was noticeably white.|The Silver Chair|C.S. Lewis|NO
10:00|ten|At around ten every morning, my wife and I would take a cooler down to the beach. We'd lather up with sunblock, then sprawl out on mats on the sand. I'd listen to the Stones or Marvin Gaye on a Walkman, while my wife plowed through a paperback of Gone With the Wind. She claimed that she'd learned a lot about life from that book. I'd never read it, so I had no idea what she meant.|Blind Willow, Sleeping Woman|Haruki Murakami|NO
Expand Down Expand Up @@ -4127,7 +4127,7 @@
20:30|half-past eight|"""What nonsense!"" thought Vronsky, and glanced at his watch. It was half-past eight already."|Anna Karenina|Leo Tolstoy|NO
20:30|half-past eight|... she said, 'at exactly half-past eight you may be watching the middle upper window of the top floor. If I decide to forgive I will hang out of that window a white silk scarf. You will know by that that all is as was before, and you may come to me...|The Four Million|O. Henry|NO
20:30|half-past eight|"Alix took up a piece of needlework and began to stitch. Gerald read a few pages of his book. Then he glanced up at the clock and tossed the book away. ""Half-past eight. Time to go down to the cellar and start work."""|The Listerdale Mystery|Agatha Christie|NO
20:30|eight thirty|"At eight thirty, I called and said, ""I've been thinking I might get a boob job, just take them clean off. What do you think? Could I pull off the flat-chested look?"""|My Year of Rest and Relaxation|Ottessa Moshfegh|NO
20:30|eight thirty|"At eight thirty, I called and said, ""I've been thinking I might get a boob job, just take them clean off. What do you think? Could I pull off the flat-chested look?"""|My Year of Rest and Relaxation|Ottessa Moshfegh|YES
20:30|half past eight|At half past eight Millicent Hammitt barged in, without a preliminary knock, to say goodbye.|The Black Tower|P.D. James|NO
20:30|eight-thirty|By eight-thirty, with dusk growing too thick to be much different from night, the five searchers had grown to a dozen.|The Tommyknockers|Stephen King|NO
20:30|Eight-thirty|Eight-thirty the ward door opens and two technicians trot in, smelling like grape wine; technicians always move at a fast walk or a trot because they're always leaning so far forward they have to move fast to keep standing.|One Flew Over the Cuckoo's Nest|Ken Kesey|NO
Expand Down Expand Up @@ -4404,7 +4404,7 @@
22:00|ten|"""A considerable crime is in contemplation. I have every reason to believe that we shall be in time to stop it. But to-day being Saturday rather complicates matters. I shall want your help to-night."" ""At what time?"" ""Ten will be early enough."" ""I shall be at Baker Street at ten."""|The Adventures of Sherlock Holmes|Sir Arthur Conan Doyle|NO
22:00|ten o'clock|Alone at the too-small child's desk in her room, Eva finished the last line of the most pointless assignment ever, and though she wanted to start on the evening's true mission immediately, she kept the box of churro bites closed under her bed. Her parents went to sleep at ten o'clock on weeknights. Only three and a half more hours to wait out.|Kitchens of the Great Midwest|J. Ryan Stradal|NO
22:00|ten o'clock in the evening|And now sometimes, in the very midst of things, sometimes when I feel that I am absolutely free of it all, suddenly, in rounding a corner perhaps, there will bob up a little square, a few trees and a bench, a deserted spot where we stood and had it out, where we drove each other crazy with bitter, jealous scenes. Always some deserted spot, like the Place de l'Estrapade, for example, or those dingy, mournful streets off the Mosque or along that open tomb of an Avenue de Breteuil which at ten o'clock in the evening is so silent, so dead, that it makes one think of murder or suicide, anything that might create a vestige of human drama.|Tropic of Cancer|Henry Miller|NO
22:00|ten o'clock|Anyway, when he looked at his watch again it was ten o'clock. At ten o'clock she was lying on the divan with her boobies in her hands. That's the way he gives it to me-in driblets.|Tropic of Cancer|Henry Miller|NO
22:00|ten o'clock|Anyway, when he looked at his watch again it was ten o'clock. At ten o'clock she was lying on the divan with her boobies in her hands. That's the way he gives it to me-in driblets.|Tropic of Cancer|Henry Miller|YES
22:00|ten o'clock|At night, a quiet so vast it seemed it seemed almost to reverberate. Few cars passed on Route 114, and after ten o'clock or so there were none at all. After ten, the part of the world where I had come to rest belonged only to the loons and the wind in the fir trees.|11/22/63|Stephen King|NO
22:00|ten o'clock|At ten o'clock at night I hadn't returned yet, and then I went to bed; at about one o'clock in the morning they woke my steps in the room|The Seven Madmen|Roberto Arlt|NO
22:00|ten o'clock|At ten o'clock she went into her double cell, where the woman she shared with was already asleep, and there was the reassuring clang of the door and click of the lock. It felt safe to be caged in, now that she knew she had this other person inside her who was capable of escapades and contortions she'd never known about before.|The Heart Goes Last|Margaret Atwood|NO
Expand Down
Loading
Loading