Watch
1
0
Fork
You've already forked SouveraineOS
0
SouveraineOS/docs/tasks/52-atmosphere.md
Fimeg d10479710d 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.
2026-08-02 18:04:26 -04:00

7.1 KiB

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).