diff --git a/.claude/settings.json b/.claude/settings.json index 6030bb6..03c712b 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -1,42 +1,44 @@ { "permissions": { "allow": [ - "Bash(omarchy:*)", - "Bash(omarchy-shell:*)", - "Bash(omarchy-battery-limit:*)", - "Bash(omarchy-als:*)", - "Bash(omarchy-aquarium-toggle:*)", - "Bash(omarchy-theme-set:*)", - "Bash(omarchy-notification-send:*)", - "Bash(omarchy-launch:*)", - "Bash(omarchy-capture-screenshot:*)", - "Bash(brightnessctl:*)", - "Bash(wpctl:*)", - "Bash(nmcli:*)", "Bash(bluetoothctl:*)", - "Bash(hyprctl:*)", - "Bash(playerctl:*)", + "Bash(brightnessctl:*)", "Bash(cat:*)", "Bash(date:*)", - "Bash(uptime:*)", - "Bash(free:*)", "Bash(df:*)", - "Bash(pgrep:*)", - "Bash(ls:*)", + "Bash(free:*)", "Bash(grep:*)", - "Bash(omarchy-jarvis note:*)", - "Edit(memory/**)", - "Write(memory/**)", - "Bash(timedatectl:*)", - "WebSearch", - "Read(~/Jarvis/**)", - "Edit(~/Jarvis/todo/**)", - "Edit(~/Jarvis/output/**)", "Bash(grim:*)", - "Bash(wl-paste:*)", + "Bash(hyprctl:*)", + "Bash(ls:*)", + "Bash(macarchy-als:*)", + "Bash(macarchy-battery-limit:*)", + "Bash(nmcli:*)", + "Bash(omarchy-aquarium-toggle:*)", + "Bash(omarchy-capture-screenshot:*)", "Bash(omarchy-jarvis lastcmd:*)", "Bash(omarchy-jarvis missed:*)", - "Read(~/.cache/jarvis/**)" + "Bash(omarchy-jarvis note:*)", + "Bash(omarchy-jarvis routine:*)", + "Bash(omarchy-jarvis routines:*)", + "Bash(omarchy-launch:*)", + "Bash(omarchy-notification-send:*)", + "Bash(omarchy-shell:*)", + "Bash(omarchy-theme-set:*)", + "Bash(omarchy:*)", + "Bash(pgrep:*)", + "Bash(playerctl:*)", + "Bash(timedatectl:*)", + "Bash(uptime:*)", + "Bash(wl-paste:*)", + "Bash(wpctl:*)", + "Edit(memory/**)", + "Edit(~/Jarvis/output/**)", + "Edit(~/Jarvis/todo/**)", + "Read(~/.cache/jarvis/**)", + "Read(~/Jarvis/**)", + "WebSearch", + "Write(memory/**)" ], "deny": [ "Bash(omarchy system:*)", @@ -47,4 +49,4 @@ "Bash(pkexec:*)" ] } -} \ No newline at end of file +} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c8cdcfa..394958a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -26,7 +26,7 @@ jobs: steps: - uses: actions/checkout@v4 - # tests/test_touchbar.py skips itself when the macarchy-dfr engine is + # tests/test_touchbar.py skips itself when the macarchy-touchbar engine is # not around — which is always, here — but it is a pytest module and # needs pytest importable to reach its own skip. This is the only # dependency the suite installs, and it buys the skip, not a run. diff --git a/CLAUDE.md b/CLAUDE.md index 2272795..d13fe4c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -54,14 +54,14 @@ Tout se pilote en ligne de commande : `omarchy-shell phmatray.notification-center open|close|toggle`, `omarchy-shell macarchy.control-center open|close|toggle`, `omarchy-shell notifications toggleDnd|dndState|clear`. -- Daemons : `omarchy-battery-limit toggle|status` (plafond 80 %), - `omarchy-als toggle|status` (auto-luminosité ; status montre paused), +- Daemons : `macarchy-battery-limit toggle|status` (plafond 80 %), + `macarchy-als toggle|status` (auto-luminosité ; status montre paused), `omarchy-aquarium-toggle [status]` (fond d'écran vivant). - Luminosité : `brightnessctl -d apple-panel-bl set N%` (écran), `brightnessctl -d kbd_backlight set N%` (clavier). - Volume : `wpctl set-volume @DEFAULT_AUDIO_SINK@ N%`, `wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle`. -- Batterie : `omarchy-battery-limit status` — la ligne contient +- Batterie : `macarchy-battery-limit status` — la ligne contient « battery now N% ». N'essaie ni upower, ni acpi, ni /sys — pas autorisés dans cette session. - Réseau : `nmcli` (Wi-Fi), `bluetoothctl` (Bluetooth). diff --git a/README.fr.md b/README.fr.md index 6caacb7..5f96e67 100644 --- a/README.fr.md +++ b/README.fr.md @@ -246,7 +246,7 @@ son propre groupe de processus, est ce qui rend l'annulation vraie — tuer le groupe est ce qui atteint les sous-processus que `claude` a lancés pour ses propres outils, ce qu'un pid nu ne fait jamais. -**Touch Bar** — avec [macarchy-dfr](https://github.com/macarchy/macarchy-dfr) +**Touch Bar** — avec [macarchy-touchbar](https://github.com/macarchy/macarchy-touchbar) installé, le plugin est aussi un `touchbar-module` : le poisson s'installe sur la barre elle-même, là où était la touche micro — un appui pour déclencher, un appui long pour ouvrir sa page du Control Center. La barre @@ -254,11 +254,11 @@ est à lui pendant qu'il travaille : elle se remplit d'un vumètre pendant qu'il écoute (nourri par le daemon de réveil), tape le transcript au fur et à mesure qu'il réfléchit, et tape sa réponse au fur et à mesure qu'elle est parlée ; une ✕ interrompt. `bin/jarvis` et `jarvis-wake.py` publient -via `macarchy-dfr macarchy.jarvis state|heard|reply|level|emote|abort` — +via `macarchy-touchbar macarchy.jarvis state|heard|reply|level|emote|abort` — rien de différent de la machine à états qui signale n'importe quel autre auditeur. `install.sh` copie [`plugin/touchbar.py`](plugin/touchbar.py) avec le reste du plugin, et le daemon le récupère au prochain -`macarchy-dfr reload`. +`macarchy-touchbar reload`. ## Le faire tien diff --git a/README.md b/README.md index af48a52..fc5ef21 100644 --- a/README.md +++ b/README.md @@ -230,17 +230,17 @@ has moved. That, plus running each external stage in its own process group, is what makes cancelling real — killing the group is what reaches the subprocesses `claude` spawned for its own tools, which a bare pid never does. -**Touch Bar** — with [macarchy-dfr](https://github.com/macarchy/macarchy-dfr) +**Touch Bar** — with [macarchy-touchbar](https://github.com/macarchy/macarchy-touchbar) installed, the plugin is also a `touchbar-module`: the fish sits on the bar itself, where the mic key used to be — tap to press, long-press to open his Control Center page. The bar is his while he works: it fills with a meter while he listens (fed by the wake daemon), types the transcript out as he thinks, and types his reply as it is spoken; a ✕ interrupts. `bin/jarvis` and `jarvis-wake.py` publish over -`macarchy-dfr macarchy.jarvis state|heard|reply|level|emote|abort` — no +`macarchy-touchbar macarchy.jarvis state|heard|reply|level|emote|abort` — no different from the FSM signalling any other listener. `install.sh` copies [`plugin/touchbar.py`](plugin/touchbar.py) with the rest of the plugin, and -the daemon picks it up on `macarchy-dfr reload`. +the daemon picks it up on `macarchy-touchbar reload`. ## Making him yours diff --git a/bin/jarvis b/bin/jarvis index 2f2a7b0..84eca14 100755 --- a/bin/jarvis +++ b/bin/jarvis @@ -199,7 +199,7 @@ log() { printf '%s %s\n' "$(date +%FT%T)" "$*" >>"$LOG"; } notify() { notify-send -a "Jarvis" -t 5000 "$1" "${2-}" 2>/dev/null || true; } # Animate the Babel fish; harmless when the shell or plugin is not running. -# The same words reach the Touch Bar (macarchy-dfr's macarchy.jarvis module). +# The same words reach the Touch Bar (macarchy-touchbar's macarchy.jarvis module). mascot() { omarchy-shell macarchy.jarvis "$@" >/dev/null 2>&1 || true touchbar "$@" @@ -208,7 +208,7 @@ mascot() { # The Touch Bar's share of the mascot channel. `setState` is the one verb # NOT forwarded here: on_state_change sends the bar the raw state, because # the bar tells followup from listening and transcribing from thinking where -# the QML aliases them. Costs one macarchy-dfr client per call (~30 ms). +# the QML aliases them. Costs one macarchy-touchbar client per call (~30 ms). touchbar() { local verb=$1 shift @@ -218,7 +218,7 @@ touchbar() { esac # A newline inside a reply breaks the one-line IPC: collapse it to a space. set -- "${@//$'\n'/ }" - macarchy-dfr macarchy.jarvis "$verb" "$@" >/dev/null 2>&1 || true + macarchy-touchbar macarchy.jarvis "$verb" "$@" >/dev/null 2>&1 || true } # Everything the body says about the CURRENT exchange goes through mascot() @@ -538,8 +538,8 @@ on_state_change() { [[ $1 == cancelling ]] || mascot setState "$sprite" # The Touch Bar wears the raw state (its module tells followup from # listening). The suite's hundreds of transitions land in a fake - # macarchy-dfr on its PATH, never on the real bar. - macarchy-dfr macarchy.jarvis state "$1" >/dev/null 2>&1 || true + # macarchy-touchbar on its PATH, never on the real bar. + macarchy-touchbar macarchy.jarvis state "$1" >/dev/null 2>&1 || true # One truth about the quiet hours, and it is this one: the mascot used to # hardcode its own 23-7 night and curled up asleep whatever the soul said. printf '%s' "$(quiet_now && echo 1 || echo 0)" >"$STATE_DIR/quiet" diff --git a/bin/jarvis-fsm.sh b/bin/jarvis-fsm.sh index b4e507c..5b07a04 100755 --- a/bin/jarvis-fsm.sh +++ b/bin/jarvis-fsm.sh @@ -13,7 +13,7 @@ # # Eight, and the one-word name of the current one lives in $RUN_DIR/state. # That file is a PUBLIC CONTRACT — bin/jarvis-wake.py reads it, and so does -# the out-of-repo macarchy-dfr Touch Bar daemon — so it stays exactly one +# the out-of-repo macarchy-touchbar Touch Bar daemon — so it stays exactly one # lowercase word and nothing else, forever. # # idle at rest, and the only state anything autonomous may diff --git a/bin/jarvis_wake_level.py b/bin/jarvis_wake_level.py index bd2a247..49544fe 100644 --- a/bin/jarvis_wake_level.py +++ b/bin/jarvis_wake_level.py @@ -2,7 +2,7 @@ jarvis-wake.py lit le micro par trames de 80 ms ; pendant que Jarvis écoute, le RMS de chaque trame devient un niveau 0–1 publié sur la prise de -macarchy-dfr, dix fois par seconde au plus, et le vumètre de la barre bouge +macarchy-touchbar, dix fois par seconde au plus, et le vumètre de la barre bouge avec la voix. Pas de daemon, pas de prise, une réponse lente : rien, en silence — c'est de la décoration, et une réponse retardée lui coûte plus qu'elle ne vaut. @@ -26,7 +26,7 @@ def level_of(rms, floor): def sock_path(): base = os.environ.get("XDG_RUNTIME_DIR") or f"/run/user/{os.getuid()}" - return os.path.join(base, "macarchy-dfr", "sock") + return os.path.join(base, "macarchy-touchbar", "sock") class LevelSender: diff --git a/memory/HEARTBEAT_PROMPT.md b/memory/HEARTBEAT_PROMPT.md index 787a444..4fab0b3 100644 --- a/memory/HEARTBEAT_PROMPT.md +++ b/memory/HEARTBEAT_PROMPT.md @@ -5,13 +5,13 @@ Une commande par appel, chacune telle qu'elle est écrite ici : une ligne `a && b` ou `a ; b` est refusée en bloc, et `cat`, `grep` ou `ls` hors de ce dépôt sont refusés aussi — n'essaie ni /sys, ni upower, ni acpi. -1. Batterie : `omarchy-battery-limit status` — une ligne de la forme +1. Batterie : `macarchy-battery-limit status` — une ligne de la forme « charge window: 75-80% (battery now N%) ». Signale : sous 15 % ; ou une fenêtre à 100 (mode voyage) — suggère de remettre la limite. 2. Disque : `df -h /` — signale au-dessus de 90 %. -3. Daemons : `omarchy-als status` (le daemon doit tourner), - `pgrep -f "macarchy-dfr daemon"` (Touch Bar — c'est un script python, - jamais `pgrep -x`), `pgrep -f omarchy-pinch`. Signale tout daemon mort. +3. Daemons : `macarchy-als status` (le daemon doit tourner), + `pgrep -f "macarchy-touchbar daemon"` (Touch Bar — c'est un script python, + jamais `pgrep -x`), `pgrep -f macarchy-pinch`. Signale tout daemon mort. 4. Mémoire : `grep -c "^- \[" memory/FAILURES.md` — seules ces lignes sont des entrées (le reste est commentaire). Au-delà de cinq, mentionne qu'un rêve serait bienvenu. diff --git a/plugin/touchbar.py b/plugin/touchbar.py index 0b5a6d5..d7679bb 100644 --- a/plugin/touchbar.py +++ b/plugin/touchbar.py @@ -1,6 +1,6 @@ -"""Jarvis sur la Touch Bar. Chargé en mémoire par macarchy-dfr (kind +"""Jarvis sur la Touch Bar. Chargé en mémoire par macarchy-touchbar (kind `touchbar-module`), nourri par bin/jarvis et le wake daemon à travers -`macarchy-dfr macarchy.jarvis `. +`macarchy-touchbar macarchy.jarvis `. Au repos, le poisson est un bouton (tap = press, appui long = sa page du Control Center) qui porte l'état et les émotions comme le service QML. Le @@ -14,8 +14,8 @@ import os import weakref -from macarchy_dfr.layout import Layout, Row -from macarchy_dfr.widgets import Button, Label, Meter, Sprite +from macarchy_touchbar.layout import Layout, Row +from macarchy_touchbar.widgets import Button, Label, Meter, Sprite SPRITES_DIR = os.environ.get("JARVIS_SPRITES") or os.path.expanduser("~/.local/share/jarvis/sprites") RUN_DIR = os.environ.get("JARVIS_RUN") or os.path.join(os.environ.get("XDG_RUNTIME_DIR", "/tmp"), "jarvis") diff --git a/tests/bin/macarchy-dfr b/tests/bin/macarchy-dfr deleted file mode 100755 index 4ffb530..0000000 --- a/tests/bin/macarchy-dfr +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -# The Touch Bar channel, recorded instead of dropped: every state, heard, -# reply, emote and abort the FSM sends lands in $FAKE_DFR_LOG. -printf '%s\n' "$*" >>"${FAKE_DFR_LOG:-/dev/null}" -exit 0 diff --git a/tests/bin/macarchy-touchbar b/tests/bin/macarchy-touchbar new file mode 100755 index 0000000..ce447a0 --- /dev/null +++ b/tests/bin/macarchy-touchbar @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# The Touch Bar channel, recorded instead of dropped: every state, heard, +# reply, emote and abort the FSM sends lands in $FAKE_TOUCHBAR_LOG. +printf '%s\n' "$*" >>"${FAKE_TOUCHBAR_LOG:-/dev/null}" +exit 0 diff --git a/tests/run b/tests/run index 03a1aa7..0a7083e 100755 --- a/tests/run +++ b/tests/run @@ -48,7 +48,7 @@ sandbox() { JARVIS_WAKE=0 \ FAKE_CLAUDE_LOG="$SB/claude.log" FAKE_PIPER_LOG="$SB/piper.log" \ FAKE_PLAY_LOG="$SB/play.log" FAKE_SHELL_LOG="$SB/shell.log" \ - FAKE_DFR_LOG="$SB/dfr.log" \ + FAKE_TOUCHBAR_LOG="$SB/touchbar.log" \ FAKE_VOXTYPE_LOG="$SB/voxtype.log" FAKE_NOTIFY_LOG="$SB/notify.log" \ FAKE_PACTL_LOG="$SB/pactl.log" # The soul lives in the repository, not in the sandbox — so a test that @@ -374,7 +374,7 @@ assert "groupe enregistré" waitfor test -s "$JARVIS_RUN/pids/record" rec=$(cat "$JARVIS_RUN/pids/record" 2>/dev/null) assert "enregistreur vivant" alive "$rec" assert "le poisson suit" grep -q 'macarchy.jarvis setState listening' "$FAKE_SHELL_LOG" -assert "la Touch Bar suit" grep -q '^macarchy.jarvis state listening$' "$FAKE_DFR_LOG" +assert "la Touch Bar suit" grep -q '^macarchy.jarvis state listening$' "$FAKE_TOUCHBAR_LOG" "$JARVIS" cancel assert "état idle" state_is idle assert "enregistreur arrêté" waitfor dead "$rec" @@ -680,7 +680,7 @@ assert "la précédente reste" journal_has "Quelle heure est-il" assert "le panneau ne montre plus rien" test ! -e "$JARVIS_RUN/last-ask" -a ! -e "$JARVIS_RUN/last-reply" assert "tracé" grep -q 'oublié : « Et la météo ? »' "$JARVIS_MEMORY/trace/$(today).log" assert "la bulle est vidée" grep -q 'macarchy.jarvis heard $' "$FAKE_SHELL_LOG" -assert "la Touch Bar aussi" grep -q '^macarchy.jarvis heard $' "$FAKE_DFR_LOG" +assert "la Touch Bar aussi" grep -q '^macarchy.jarvis heard $' "$FAKE_TOUCHBAR_LOG" assert "sans voix en --quiet" test ! -s "$FAKE_PIPER_LOG" assert "oublié encore" "$JARVIS" undo --quiet assert "et plus rien à oublier" not "$JARVIS" undo --quiet @@ -885,7 +885,7 @@ assert "la réponse est garée" grep -q 'disque' "$JARVIS_STATE/reply-pending" assert "l'émotion est garée" test "$(cat "$JARVIS_STATE/emote-pending")" = worried "$JARVIS" cancel assert "l'aparté est arrivé" grep -q 'macarchy.jarvis reply.*disque' "$FAKE_SHELL_LOG" -assert "l'aparté est sur la Touch Bar" grep -q 'macarchy.jarvis reply.*disque' "$FAKE_DFR_LOG" +assert "l'aparté est sur la Touch Bar" grep -q 'macarchy.jarvis reply.*disque' "$FAKE_TOUCHBAR_LOG" assert "l'émotion aussi" grep -q 'macarchy.jarvis emote worried' "$FAKE_SHELL_LOG" assert "plus rien en attente" test ! -e "$JARVIS_STATE/reply-pending" @@ -903,7 +903,7 @@ t "un saut de ligne dans la réponse n'écrase pas l'IPC vers la Touch Bar" printf 'idle' >"$JARVIS_RUN/state" FAKE_CLAUDE_REPLY=$'Deux\nlignes' "$JARVIS" ask --quiet "et alors" assert "la Touch Bar reçoit une seule ligne aplatie" \ - grep -q '^macarchy.jarvis reply Deux lignes$' "$FAKE_DFR_LOG" + grep -q '^macarchy.jarvis reply Deux lignes$' "$FAKE_TOUCHBAR_LOG" # ---- the gesture of aborting: chantier 3 t "presser pendant la réflexion : trop tôt ne fait rien, à temps annule" @@ -1007,15 +1007,15 @@ assert "aucun cas raté" python3 "$TESTS_DIR/test_wake_fsm.py" assert "aucun cas raté sur le niveau" python3 "$TESTS_DIR/test_wake_level.py" # ---- la Touch Bar -t "touch bar: le module, chargé par le moteur de macarchy-dfr" -# test_touchbar.py skips itself when the macarchy-dfr engine is absent, but it +t "touch bar: le module, chargé par le moteur de macarchy-touchbar" +# test_touchbar.py skips itself when the macarchy-touchbar engine is absent, but it # needs pytest to be importable to reach that skip. A bare runner — or a # contributor who has not installed pytest — has neither, and failing there # says nothing about their change. if python3 -c 'import pytest' 2>/dev/null; then # Exit 5 is "no tests collected", which is exactly what test_touchbar.py's # module-level skip produces when the engine is absent — a runner always, - # a laptop with a sibling macarchy-dfr never. Both 0 and 5 are the test + # a laptop with a sibling macarchy-touchbar never. Both 0 and 5 are the test # doing its job; anything else is a real failure. assert "les tests du module passent (ou sont sautés sans moteur)" \ bash -c 'python3 -m pytest -q "$1"; rc=$?; ((rc == 0 || rc == 5))' \ diff --git a/tests/test_touchbar.py b/tests/test_touchbar.py index 5584469..2c66cf7 100644 --- a/tests/test_touchbar.py +++ b/tests/test_touchbar.py @@ -1,9 +1,9 @@ #!/usr/bin/env python3 """Le poisson sur la Touch Bar, sans Touch Bar : le module plugin/touchbar.py -chargé par le moteur de macarchy-dfr en mémoire, avec une horloge factice. +chargé par le moteur de macarchy-touchbar en mémoire, avec une horloge factice. Le moteur n'est pas une dépendance de Jarvis : sans lui (pas de -`macarchy-dfr` sur le PATH, pas de dépôt voisin), ces tests sont sautés.""" +`macarchy-touchbar` sur le PATH, pas de dépôt voisin), ces tests sont sautés.""" import importlib.util import os import shutil @@ -17,28 +17,28 @@ def _engine_root(): """The first candidate that actually holds the engine: the real - `macarchy-dfr` on PATH (not a test's own fake, which has no - `macarchy_dfr/modules.py`), else the sibling checkout.""" - exe = shutil.which("macarchy-dfr") + `macarchy-touchbar` on PATH (not a test's own fake, which has no + `macarchy_touchbar/modules.py`), else the sibling checkout.""" + exe = shutil.which("macarchy-touchbar") candidates = [] if exe: candidates.append(os.path.dirname(os.path.dirname(os.path.realpath(exe)))) - candidates.append(os.path.join(os.path.dirname(os.path.dirname(HERE)), "macarchy-dfr")) + candidates.append(os.path.join(os.path.dirname(os.path.dirname(HERE)), "macarchy-touchbar")) for root in candidates: - if os.path.exists(os.path.join(root, "macarchy_dfr", "modules.py")): + if os.path.exists(os.path.join(root, "macarchy_touchbar", "modules.py")): return root return None ROOT = _engine_root() if ROOT is None: - pytest.skip("macarchy-dfr introuvable", allow_module_level=True) + pytest.skip("macarchy-touchbar introuvable", allow_module_level=True) sys.path.insert(0, ROOT) import cairo # noqa: E402 -from macarchy_dfr.loop import EventLoop # noqa: E402 -from macarchy_dfr.modules import ModuleHost, ModuleSpec, Registry # noqa: E402 -from macarchy_dfr.widgets import Button, Label, Meter, Sprite # noqa: E402 +from macarchy_touchbar.loop import EventLoop # noqa: E402 +from macarchy_touchbar.modules import ModuleHost, ModuleSpec, Registry # noqa: E402 +from macarchy_touchbar.widgets import Button, Label, Meter, Sprite # noqa: E402 SHEETS = {"idle": 6, "listening": 2, "thinking": 3, "speaking": 4, "cancel": 4, "sleeping": 4, "tired": 2, "dnd": 2, "worried": 2, "proud": 2, "curious": 2, "celebrate": 3} @@ -313,7 +313,7 @@ def test_speaking_types_the_reply_and_shows_the_tail_when_it_overflows(sprites): rig.ipc("reply", "Il est dix heures.") lay = rig.scene() text = _text(lay) - from macarchy_dfr.geometry import Rect + from macarchy_touchbar.geometry import Rect text.rect = Rect(0, 0, 200, 60) # narrow on purpose (fake measure = 8 px/char) rig.advance(0.5) assert text.text == "Il est dix heures." diff --git a/tests/test_wake_level.py b/tests/test_wake_level.py index 5a41dc0..434430c 100755 --- a/tests/test_wake_level.py +++ b/tests/test_wake_level.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 """Le niveau de l'oreille vers la Touch Bar : l'échelle et l'envoi, sans -micro ni barre — une prise Unix éphémère joue macarchy-dfr.""" +micro ni barre — une prise Unix éphémère joue macarchy-touchbar.""" import os import socket import sys