Commit Graph
6 Commits
Author SHA1 Message Date
Gabriel Brown 07db1068f1 Review everything shipped this weekend, and fix what the reviewers caught
Claude-Session: https://claude.ai/code/session_01Ms2FbjQy31TVf3CEvQhGM8
2026-08-24 13:29:42 -04:00
Gabriel Brown 7578348db1 Merge Home & Phone into a three-tab Home that knows your house
Home is now Overview | My Home | Phone. Overview leads with quick-action
tiles (focus, Do Not Disturb, health, snapshots, storage), keeps the
findings card — updates fold in, the reclaim-space prompt is gone on
purpose — and adds glance cards, the next calendar event, and weather.

My Home groups every light by Home Assistant area: the helper gained an
`areas` command (one REST template render, no websocket), and the rooms
degrade to a flat list on setups without areas. The favorites editor and
connection card moved intact. Phone gains a vitals strip — battery and
cell signal read from KDE Connect's plugin D-Bus objects, where absence
is data, not an error — beside ring, clipboard, send-a-file, and the
BlueBubbles handoff.

The retired home-phone id resolves to my-home forever via a new alias
map in SettingsRoutes (with a hasOwnProperty guard so prototype names
cannot leak into settingsPage). Storage no longer claims 0 B free — the
old page read a field the disks helper never emitted.

Contracts updated alongside; per the new workflow, the full suite runs
once at the end of the redesign (see the test backlog note).

Claude-Session: https://claude.ai/code/session_01Ms2FbjQy31TVf3CEvQhGM8
2026-08-23 22:06:18 -04:00
Gabriel Brown 5490fd285d Fold thirty-one settings pages into fifteen categories with tabs
The sidebar was a flat scan of thirty-one rows; now it reads like a
settings app. Multi-subject categories (Input, Network & Sharing,
Applications, Users & Accounts, Privacy & Security, System) carry an
Appearance-style tab strip above the page, drawn by the shell so the
leaf pages themselves are untouched. The taxonomy lives in one new
file, services/SettingsRoutes.qml; the sidebar, the strip, route
validation, search breadcrumbs, and both generators derive from it.

ShellState.settingsPage still holds leaf ids, so every deep link, IPC
call, and search result keeps working — and now lands on the exact
tab. Dictation moves out of Sound onto its own page under Input, with
a handoff back to Sound for the microphone. The strip scrolls when
System's nine tabs outgrow a tiled window. All 161 contracts pass.

Claude-Session: https://claude.ai/code/session_01Ms2FbjQy31TVf3CEvQhGM8
2026-08-23 20:21:31 -04:00
Gabriel Brown 538c0a887c Save things where the rest of the software already saves them
Screenshots and recordings offered three folders to choose between, and three
guesses cannot include the folder somebody's other software already writes to --
which is the only folder that matters. This machine has had ~/Pictures/Screenshots
and ~/Videos/Screencasts since long before Panama, and Panama was writing
recordings to a Videos/Recordings it invented. Both are free text now, and the
recording default is the folder that was already there.

Wallpapers were swept from four directories at once, so the distribution's stock
images arrived mixed in with the user's own and there was no way to ask for just
one. Where wallpapers live is something somebody knows about their own machine.
It is a setting, not a search.

All three accept an absolute path as well as one relative to home, which meant
fixing Capture: it prefixed $HOME unconditionally, so naming /mnt/captures would
have written screenshots to ~/mnt/captures and left nobody able to find them.

The generator turned out to skip any entry whose comment sits inside the braces
rather than above them -- it looks for `key:` immediately after `{`. Three
settings were invisible in the reference because of it, one of them dockScreens,
which has never appeared there at all. The staleness contract could not see it
either: regenerating reproduced the same omission, so the copy was current and
incomplete at once. It now counts what was declared against what it could read
and refuses rather than quietly documenting less than exists.

Claude-Session: https://claude.ai/code/session_01Q84axqUE5inJhf5Jz9CFy1
2026-08-21 12:57:47 -04:00
Gabriel Brown 48f7c1e962 Name the Gaming page, and stop the docs inventing names
The settings reference is generated, and a contract already fails when the
committed copy is stale -- so it was current. It was also wrong: the Gaming page
was documented as "Found on **gaming**" while every other group named a real
page, because a routed page with no entry in PAGE_TITLES fell back to printing
its own id.

The staleness contract could not see it. Regenerating reproduced the same wrong
file, so the copy was current and wrong at the same time -- a check that compares
output against itself cannot catch a generator that is confidently mistaken.

So the fallback is gone. A routed page with no title now refuses to render and
says which page needs one, which is what makes the next page added here
impossible to miss.

Claude-Session: https://claude.ai/code/session_01Q84axqUE5inJhf5Jz9CFy1
2026-08-20 23:32:46 -04:00
Gabriel Brown 588dec4adc Generate the settings reference from the schema
Every other form of documentation here has drifted at least once today:
search routing that pointed at a page not containing the setting, a
contract that pinned the bug the same commit fixed, and a comment in
shell.qml that failed to stop me making the exact mistake it described.
Prose describing 127 settings would drift the day after it was written.

So docs/settings.md is generated, and a contract fails the moment the
committed copy stops matching the schema. The document cannot be wrong
for longer than it takes to run the suite.

It reads the schema by parsing rather than importing, since there is no
QML interpreter here and requiring a compositor to build documentation
would be worse. That parser is the risk, so it FAILS LOUDLY: if it stops
recognising the file it exits non-zero with the reason and writes
nothing, because a partial reference is worse than a stale one -- stale
is caught by --check, partial reads as complete. Verified: with the
entry pattern broken it reports "only 0 entries parsed" and leaves the
committed file untouched.

The contract also proves --check actually compares content, by appending
a line and confirming it fails, rather than trusting a command that
returns success to mean anything.

Claude-Session: https://claude.ai/code/session_01BRvzt4H8XXLPVH5MyYdk9L
2026-08-19 08:37:43 -04:00