3.5 KiB
TASK 47 — Auto-brightness: the design is settled, none of it is built
Status: open, raised 2026-07-29. Size: one session for the Action +
hysteresis; a second for anchors and their persistence. Repo: souveraine
(sessiond), then souveraine (settings surface).
The gap
DEVICE-STATE-MACHINE.md §12 reads as finished work. It settles where light
belongs in the chain, that auto-brightness must be an Action and not an
eighth blind actor, how it interacts with Dim/Restore, that it needs
hysteresis, and — in a subsection marked "settled 2026-07-27" — that manual
correction produces anchors, not a global bias.
Measured against the code on 2026-07-29:
| §12 claim | in code |
|---|---|
lux enters through sensor_input like proximity |
yes — SensorSource::Light, fed by souveraine-sensord |
| light health is tracked | yes — live on the phone, "light": "live" |
light_changing carries evidence weight |
yes — §4 arithmetic |
auto-brightness leaves as an Action |
no |
suspended between Dim and Restore |
no |
| hysteresis / ramp on lux | no |
manual corrections stored as (lux, brightness) anchors |
no |
| anchors persisted next to other settings | no |
grep -rn "anchor" src/ returns nothing. Action is Dim | Restore | Blank | Lock — there is no brightness verb at all. The evidence half of §12 is live;
the actuation half does not exist.
This is the failure mode a settled-looking doc creates. Nothing in §12 says "unbuilt", and the section that sounds most finished — anchors, with the iOS patent reasoning worked through — is the part with zero lines behind it.
What exists to build on
sensordalready reports light with the asymmetric debounce taken from this device's own Android RRO (config_autoBrightnessBrighteningLightDebounce=2000,DarkeningLightDebounce=4000). That is the hysteresis input, already smoothed.Action::Dim/Action::Restoreare the model to copy: computed intick(), executed by the executor table, one writer, one trail.note_brightness_before_dim/take_brightness_before_dimalready establish that sessiond owns the panel value and that a second writer makes the captured value a lie. Auto-brightness must go through the same door.
Acceptance
Action::SetBrightness(u32)exists, is computed intick(), and is executed by the same table asDim. No second process writesbrightnessctl.- It proposes only while undimmed and not
Locked, per §12. BetweenDimandRestoreit is suspended, not rate-limited — andRestorere-evaluates from current lux rather than replaying the captured number. - A sustained lux delta is required before any move, and the move ramps. The
thresholds come off the trail, the way
PROXIMITY_NEAR_DEBOUNCEdid — not out of §12 and not out of this file. - A manual brightness change while auto-brightness is on writes an anchor at
the current lux. Two to four anchors, interpolated between,
0%/100%pinned. Pinned at manual maximum, further ambient rise moves nothing. - Anchors persist across a reboot and can be deleted to get the old behaviour back.
- The settings page shows the current lux, the computed target, and the anchors — TASK-19 owes the readout, and this is one of the things it reads.
Connects to
DEVICE-STATE-MACHINE.md §12 (the whole design), TASK-40 (lux must reach the
machine without widening what the raw stream exposes — that task is the gate),
TASK-19 (the readout), TASK-08 (the machine itself).