Watch
1
0
Fork
You've already forked SouveraineOS
0

tasks: 52 atmosphere, and narrow the haptics question to one a hand can answer

52 maps the fifteen-technique attention vocabulary onto what viewtop can
actually do. Two are already landed — expose IS negative space, pose IS
gravity wells — and compile_custom_pixel_shader + PixelShaderElement are
already in our smithay, so #1/#6/#9/#11/#12/#13/#14 need no new machinery.

The load-bearing note is ordering: build the attention model and one
global clock before any individual effect, or fifteen animators fight
over the same surfaces and it is §1's blind actors in the render path.
That failure already happened this week in the panel. Attention decisions
go in forensic.jsonl in the same change, so the atmosphere is
imperceptible in the moment and legible afterward — the standard every
other authority here is held to.

45: the PMIC haptics path accepts and plays an FF effect and the CS40L20
is absent from this kernel, so the five-minute check is now one question
only a hand can answer.
This commit is contained in:
Fimeg 2026-08-02 18:04:26 -04:00
commit d10479710d
3 changed files with 147 additions and 1 deletions

View file

@ -14,7 +14,20 @@ driven through feedbackd's `quiet` profile with a udev rule in the overlay.
But Google shipped a **Cirrus CS40L20** on this board as the haptic amplifier,
and both cannot be driving the same LRA. So before any port:
**Question 1: what is the motor physically wired to?** If the detents are
**Measured 2026-08-02, narrowing this considerably.** The PMIC path is live and
functional *in software*: `spmi_haptics` is `input5`/`event5` under
`qcom_spmi_haptics` bound to `ff_memless`, `feedbackd` is running, and an
`EVIOCSFF` rumble upload **succeeded (effect id 0) with the play event
accepted**. The **CS40L20 is absent from this kernel entirely** — zero dmesg
hits, no i2c node. So this is no longer "which of two drivers"; it is one live
driver and one unbuilt one.
**Question 1, now down to one thing a hand can answer: does it buzz?** If yes,
the PMIC reaches the motor and the Cirrus part is an upgrade. If no, the LRA is
wired to the CS40L20, nothing has ever vibrated, and this task is the *enabler*
for TASK-52's tactile premonition rather than an improvement to it.
**Original framing of Question 1: what is the motor physically wired to?** If the detents are
genuinely felt, the PMIC path reaches the motor and the CS40L20 is an upgrade.
If they are not — if `Haptics.tick()` has been a no-op nobody checked — then
the CS40L20 is the enabler and the current haptics are a success-shaped

132
docs/tasks/52-atmosphere.md Normal file
View file

@ -0,0 +1,132 @@
# TASK 52 — Atmosphere: attention as a compositor capability
**Status: open, and closer than it looks.** Created 2026-08-02 from Casey's
fifteen-technique design. **Repo:** `souveraine-viewtop`, plus `Pixel3Arch` for
the two hardware answers below.
The thesis: owning the compositor is not for notifications and badges. It is so
the agent can shape *the weather your attention navigates through* — thermal,
gravitational, temporal, tactile — instead of interrupting you with a banner.
## What already exists, as of today
Two of the fifteen are **landed** (`276bb3e`), because `pose` and `expose` turned
out to be the primitives underneath them:
- **#3 Negative space with intent.** `expose` is per-surface alpha, clamped by
the gate, applied in the render. Dropping every non-target surface to
`Dimmed` while the target holds `Natural` *is* this technique. What is missing
is only the **easing** — today it snaps, and the whole effect is the 1.2 s
curve.
- **#10 Gravity wells.** `pose` scales about a **pivot**, and `place` takes
arbitrary sub-pixel offsets that are honoured with no clamping (geometry is
the agent's, §13's 60). A 2 px lean is a `place` away. The gestalt — many
elements leaning coherently — is shell-side arithmetic, not compositor work.
And the pipeline for most of the rest is **already in our smithay**:
`GlesRenderer::compile_custom_pixel_shader(src, additional_uniforms)`
`GlesPixelProgram`, composited as a `PixelShaderElement` with its own `area`,
`alpha` and **custom uniforms**. That is the shader half of #1, #6, #9, #11, #12,
#13 and #14 with no fork and no new dependency. The render path already builds
an element list per frame; these are more elements.
## The hardware answers, measured 2026-08-02 rather than assumed
- **#7 Tactile premonition — the motor is real, at least in software.**
`spmi_haptics` is `input5`/`event5`, driven by `qcom_spmi_haptics` bound to
`ff_memless`, with `feedbackd` live. An `EVIOCSFF` rumble upload **succeeded
(effect id 0) and the play event was accepted.** So the path is not a
success-shaped control at the driver layer.
**Still owed, and it needs a hand:** did it actually buzz? TASK-45's Question 1
is now narrowed to exactly that — the driver works, so the only remaining
unknown is whether the LRA is wired to the PMIC or to the **CS40L20**, which is
**absent from this kernel** (zero dmesg hits, no i2c node). If the motor is on
the Cirrus part, nothing has ever vibrated and TASK-45 becomes the enabler for
this technique rather than an upgrade to it.
The 40 ms lead time is the easy half: it is a queue in the compositor's event
loop keyed to the frame clock, and `on_vblank` is already that clock.
- **#13 Bioluminescence — there is no hover, but there is something.**
The FTS controller exposes `glove_mode`, `stylus_mode`, `grip_mode`,
`gesture_mask`, `gesture_coordinates` and `touchsim` — no hover-capacitance
node. `glove_mode` raises sensitivity and is the nearest thing; whether it
yields a usable pre-touch signal is an experiment, not a port.
**Unrelated but valuable, found while looking:** `gesture_coordinates` means
the controller reports **where** a double-tap-to-wake happened. Today dt2w is
a bare `KEY_WAKEUP` and the position is thrown away — waking *to the thing you
tapped* is free information nobody is reading.
## The rest, by what they need
**Shader pipeline** (`PixelShaderElement`, no new machinery): #1 peripheral
magnetism (colour-temperature drift on a Perlin path), #6 chromatic dissonance
(RGB split on the target's damage region, offset mapped to urgency), #9
synesthetic bleed (mid-tone LUT as a final pass), #12 weather systems, #14
resonance (per-surface micro-translation with phase jitter).
**Render-loop work:** #2 depth of field (a real blur pass and a Z-map per
surface — the heaviest single item), #8 temporal dilation (per-surface frame
scheduling; `presenting` already tracks which CRTCs have a flip in flight, which
is where this hooks), #11 reflection and echo (frame-buffer feedback — sample
the previous frame's target region and decay it).
**A global time-base:** #5 breath rhythm and #15 the invitation are the same
mechanism from opposite ends — one modulates everything on a shared sinusoid,
the other **freezes** it. Both need one clock that every animated property reads,
which does not exist yet and should exist before any of the individual effects,
or each one grows its own timer and they beat against each other.
**New subsystem:** #4 condensation from noise (a particle system seeded from the
wallpaper's luminance histogram).
## Build the clock and the vocabulary first, not the effects
The tempting order is to build the effects one at a time because each is
individually small. That produces fifteen uncoordinated animators fighting over
the same surfaces — `DEVICE-STATE-MACHINE.md` §1's seven blind actors, in the
render path. It has already happened once in this project this week, in the
panel: two actors deciding about one screen produced a press that woke the phone
and put it back to sleep.
So: **one attention model, one clock, effects as strategies over it.** The
compositor holds a per-surface *attention weight*; the techniques are functions
from that weight to render parameters. The agent sets weights, not blur radii.
That also makes the vocabulary composable rather than a list — which is what
`expose` already is, and why two of these were free.
## The trail, which is what makes it legible
Every one of these is imperceptible by design at the low end — that is the
mechanism, not a side effect. This project already solved the general form of
that problem for the device state machine: **`forensic.jsonl` exists because "no
evidence" and "evidence says nothing" had to be different states** (§10), and
because a decision nobody can reconstruct is a decision nobody can audit.
Attention decisions belong in the same trail: *what* was weighted, *how much*,
*why*, and which technique carried it. Then atmosphere is imperceptible in the
moment and **legible after the fact** — the same standard every other authority
in this system is already held to, and the reason `blank-without-lock` was
eventually findable at all.
Do this in the same change as the attention model, not after. A trail added
later only ever covers what someone remembered to instrument.
## Acceptance
- One shader element composited over the real scene on the phone, driven by a
uniform the agent sets through `scene`.
- A target surface holding `Natural` while its neighbours ease to `Dimmed` over
a curve, not a snap.
- Every weight change reconstructable from `forensic.jsonl` after the fact.
- Casey reports whether the phone buzzed (TASK-45 Q1), which decides whether #7
is a queue or a driver port.
## Connects to
TASK-43 (viewtop), TASK-45 (haptics — now narrowed to one physical question),
TASK-51 (the daily-driver punch list; atmosphere is worthless on a compositor
whose windows stack), TASK-47 (auto-brightness — the *other* thing that wants to
modulate the panel, and must not become a second writer),
`DEVICE-STATE-MACHINE.md` §1 (why one model and not fifteen), §10/§11 (the
trail).

View file

@ -58,6 +58,7 @@ Four that are cheap relative to what they unblock:
| # | Task | What's left |
|---|------|-------------|
| 52 | [Atmosphere](52-atmosphere.md) | Attention as a compositor capability — the fifteen-technique vocabulary. Two are **already landed** (`expose` is negative space, `pose` is gravity wells), and `compile_custom_pixel_shader` + `PixelShaderElement` are already in our smithay, so most of the rest needs no new machinery. Build the attention model and one clock **first**; fifteen uncoordinated animators is §1's blind actors in the render path. |
| 50 | [Her hand on the glass](50-agent-hand-on-the-glass.md) | Every scene intent reaches the compositor now **except touch** — so she can move, scale, dim and close a window and cannot press anything inside one. The receiving end is built (`Origin::Agent`, the disjoint slot namespace, the evidence predicate); nothing calls it, so she still reaches touch through uinput, which is the exact conflation `input.rs` exists to prevent. Also owns the inverse mapping `pose` owes the hit test. |
| 51 | [viewtop to daily driver](51-viewtop-to-daily-driver.md) | The punch list between *runs* and *stable*, all of it found by using the phone: windows stack with nothing to tell them apart, screen capture is written and unmerged (so no UI change can be verified), volume buttons are recognised and dropped, and five named holes that are one decision each. |
| 48 | [Shell dies on any reload that owes a lock](48-lock-surface-reload-fatal.md) | Fully diagnosed 07-29, 11 crashes since 07-17. A reload re-requests ext-session-lock while the outgoing instance still holds it → `FATAL: Tried to show lockscreen surfaces without active lock`. **Sync with TASK-43 before touching the lock path.** |