From 3f48e685cc5d0c1e7966ac2bbd28fd6c57df9db9 Mon Sep 17 00:00:00 2001 From: jochen Date: Sun, 4 Oct 2026 16:42:21 +0200 Subject: [PATCH] ADR 0212: a seat says what it receives, and the machine's hotkeys are a seat --- ...ves-and-the-machines-hotkeys-are-a-seat.md | 106 ++++++++++++++++++ 02-DECISIONS/README.md | 1 + .../42-the-machines-modules-in-order.md | 6 + 3 files changed, 113 insertions(+) create mode 100644 02-DECISIONS/0212-a-seat-says-what-it-receives-and-the-machines-hotkeys-are-a-seat.md diff --git a/02-DECISIONS/0212-a-seat-says-what-it-receives-and-the-machines-hotkeys-are-a-seat.md b/02-DECISIONS/0212-a-seat-says-what-it-receives-and-the-machines-hotkeys-are-a-seat.md new file mode 100644 index 0000000..61ad421 --- /dev/null +++ b/02-DECISIONS/0212-a-seat-says-what-it-receives-and-the-machines-hotkeys-are-a-seat.md @@ -0,0 +1,106 @@ +--- +topic: the mesh +status: accepted +date: 2026-10-04 +deciders: jochen +reconstructed: false +extends: 02-DECISIONS/0210-a-tools-configuration-is-its-seat-holders-and-every-other-module-extends-it-through-the-seat.md +--- + +# 212. A seat says what it receives, and the machine's hotkeys are a seat + +## Context + +[ADR 0210](0210-a-tools-configuration-is-its-seat-holders-and-every-other-module-extends-it-through-the-seat.md) +decided that a tool's configuration belongs to its seat's holder, and that every other module extends +it with a contribution to the seat (§2), in a grain the seat defines (§5). The controller knows only +three such grains: +- the environment ([ADR 0203](0203-the-accounts-environment-is-one-modules-and-every-module-contributes-to-it.md)); +- shell code in named slots ([ADR 0204](0204-a-module-contributes-shell-code-to-the-login-shell-in-named-slots.md)); +- the power moments ([ADR 0211](0211-a-machines-power-is-a-node-seat-its-moments-take-contributions-and-its-states-are-events.md)). + +Each was a field of its own, with a renderer of its own. Two more appeared on the first workstation: + +- **The window manager.** Four modules, the launcher, the clipboard, the wallpaper and the bar, wrote + files of their own into its include directory, and so did the laptop's model module. That is what + ADR 0210 forbids. +- **The keys the window manager never sees.** A laptop's vendor keys reach only a hotkey daemon, which + reads trigger lines (a key, a state, a command). The daemon's configuration was the laptop module's, + although the daemon is a general piece that more than one module has keys for. + +A field and a renderer per grain would make every new seat a change to the controller's schema. + +## Considered Options + +1. **A field per grain,** as before. Rejected: the manifest and the controller grow with every seat + that takes contributions. +2. **Contributions as files in the holder's drop-in directory,** each contributor writing its own. + Rejected by ADR 0210: a path in another module's territory. +3. **One general contribution: a seat, a kind the seat receives, and text in the tool's own grammar.** + The seat lists the kinds it receives. The holder places each kind with one placeholder, and the + controller concatenates the contributions in module order, each under a comment naming its module. + Chosen. + +## Decision + +**1. A module contributes with `contributions`.** Each entry names: +- a **seat**; +- a **kind**, which that seat receives; +- **content**, text in the tool's own grammar, which the controller does not read. + +**2. A seat lists the kinds it receives,** with the comment prefix of its tool's grammar. A +contribution of a kind its seat does not list is refused at registration. + +**3. The holder places a kind with `${contribution::}`** in its own files. The placeholder +is filled with every module's contribution of that kind on the node: +- in module order; +- each preceded by a comment line naming the module; +- empty when there is none. + +A placeholder in a module that does not claim the seat is refused, as ADR 0204 refuses shell slots. + +**4. A contribution depends on its seat** (ADR 0210 §3), derived and refused as +[ADR 0207](0207-a-module-depends-on-the-node-seats-that-apply-its-resources.md) says. + +**5. Two seats receive first:** + +| seat | kind | what it is | +|---|---|---| +| `node-display-session` | `config` | window-manager configuration lines: bindings, start-up commands, rules | +| `node-hotkeys` (new, node scope) | `trigger` | hotkey-daemon trigger lines: a key, a state, a command | + +`node-hotkeys` is in the mesh's own set. Its holder runs the daemon that sees the keys the window +manager does not, and owns that daemon's configuration and service. + +## Consequences + +- The window-manager fragments become `config` contributions of their modules: the launcher, the + clipboard, the wallpaper, the bar and the laptop model. The window manager's module places them + instead of including other modules' files. +- A hotkey module holds `node-hotkeys`. The laptop's model module contributes its vendor keys + instead of writing the daemon's trigger file, and keeps only what is its own: the scripts the keys + run. +- The three earlier grains stay as they are. Folding them into this form is a later change, not + required by this record. +- **What got harder:** a contribution is text the controller does not read, so a malformed line + reaches the tool. The holder checks the composed file with the tool's own check where the tool has + one (the window manager's), before it reloads. + +## How it is checked + +| Rule | Checked by | +|---|---| +| A contribution names a seat and a kind that seat receives | the catalogue check, which registration runs | +| The placeholder fills with every module's contribution, in module order, each named | the controller's contribution tests | +| A placeholder outside the seat's holder is refused | the catalogue check | +| A contribution derives a dependency on its seat | the controller's resolve tests | +| `node-hotkeys` is a node seat of the mesh's own set | the seat table's tests | + +## References + +- [ADR 0203](0203-the-accounts-environment-is-one-modules-and-every-module-contributes-to-it.md), + [ADR 0204](0204-a-module-contributes-shell-code-to-the-login-shell-in-named-slots.md), + [ADR 0208](0208-the-graphical-session-is-one-module-per-piece-on-the-meshs-seats.md), + [ADR 0210](0210-a-tools-configuration-is-its-seat-holders-and-every-other-module-extends-it-through-the-seat.md), + [ADR 0211](0211-a-machines-power-is-a-node-seat-its-moments-take-contributions-and-its-states-are-events.md) +- [To-be 42](../03-DESIGN/01-to-be/42-the-machines-modules-in-order.md) diff --git a/02-DECISIONS/README.md b/02-DECISIONS/README.md index ad4a458..4ae0e0e 100644 --- a/02-DECISIONS/README.md +++ b/02-DECISIONS/README.md @@ -193,6 +193,7 @@ python3 00-META/checks/index.py fail if stale - **0202** — [A provider declares what it derives for each consumer, and the mesh tells both ends](0202-a-provider-declares-what-it-derives-for-each-consumer.md) - **0207** — [A module depends on the node seats that apply its resources](0207-a-module-depends-on-the-node-seats-that-apply-its-resources.md) - **0210** — [A tool's configuration is its seat holder's, and every other module extends it through the seat](0210-a-tools-configuration-is-its-seat-holders-and-every-other-module-extends-it-through-the-seat.md) +- **0212** — [A seat says what it receives, and the machine's hotkeys are a seat](0212-a-seat-says-what-it-receives-and-the-machines-hotkeys-are-a-seat.md) ### Its tiers, from the bottom up diff --git a/03-DESIGN/01-to-be/42-the-machines-modules-in-order.md b/03-DESIGN/01-to-be/42-the-machines-modules-in-order.md index 3b8cb40..c9c9627 100644 --- a/03-DESIGN/01-to-be/42-the-machines-modules-in-order.md +++ b/03-DESIGN/01-to-be/42-the-machines-modules-in-order.md @@ -15,6 +15,7 @@ decisions: - 02-DECISIONS/0205-software-the-distribution-does-not-package-ships-as-a-pinned-archive-of-the-module.md - 02-DECISIONS/0207-a-module-depends-on-the-node-seats-that-apply-its-resources.md - 02-DECISIONS/0208-the-graphical-session-is-one-module-per-piece-on-the-meshs-seats.md + - 02-DECISIONS/0212-a-seat-says-what-it-receives-and-the-machines-hotkeys-are-a-seat.md - 02-DECISIONS/0211-a-machines-power-is-a-node-seat-its-moments-take-contributions-and-its-states-are-events.md - 02-DECISIONS/0210-a-tools-configuration-is-its-seat-holders-and-every-other-module-extends-it-through-the-seat.md --- @@ -111,6 +112,11 @@ not write into its include directory. Each contribution is a dependency on the s so assigning one of them without a window manager is refused. The first versions, which still write the include files themselves, move to contributions once the controller derives the dependency. +**Added 2026-10-04.** `triggerhappy` holds `node-hotkeys` on both workstations ([ADR 0212](../../02-DECISIONS/0212-a-seat-says-what-it-receives-and-the-machines-hotkeys-are-a-seat.md)). The +laptop model's vendor keys become its contribution. The window-manager fragments of the launcher, the +clipboard, the wallpaper, the bar and the laptop model become `config` contributions to +`node-display-session`. + ## Phase 3 — one machine model The laptop's hardware module (vendor daemon, GPU mode, charge limit, logind, brightness and vendor keys)