diff --git a/personal/tech/karabiner-keyboard-config.md b/personal/tech/karabiner-keyboard-config.md index 7fb8653f..1021dbbb 100644 --- a/personal/tech/karabiner-keyboard-config.md +++ b/personal/tech/karabiner-keyboard-config.md @@ -9,8 +9,9 @@ tags: - russian-layout - caps-lock - devices-remap + - automatic-backups created: 2026-09-15T00:00:00.000Z -updated: 2026-09-15T13:10:00.000Z +updated: 2026-09-15T13:55:00.000Z --- # Karabiner-Elements — конфиг, раскладки, символы @@ -21,10 +22,12 @@ updated: 2026-09-15T13:10:00.000Z | Путь | Назначение | |---|---| -| `~/Documents/karabiner.json` | **Рабочая копия** (канон, редактируется) | -| `~/.config/karabiner/karabiner.json` | **Живой** конфиг — его читает Karabiner | +| `~/Documents/karabiner.json` | **Рабочая копия** (канон, редактируется) — ⚠️ на 2026-09-15 **отстал от живого**, см. «Файловое состояние» | +| `~/.config/karabiner/karabiner.json` | **Живой** конфиг — его читает Karabiner. **Самый актуальный файл** | +| `~/.config/karabiner/automatic_backups/karabiner_YYYYMMDD.json` | **Автобэкапы Karabiner по датам** — лучший источник для diff «что изменилось» | | `~/Documents/karabiner.json.bak` | Бэкап рабочей копии | -| `~/Documents/karabiner.json.bak.20260915` | Бэкап перед первой правкой Caps-фикса (md5 `2ad1f7e1c8c8807739b636cc0650a527`) | +| `~/Documents/karabiner.json.bak.20260915` | Бэкап перед правками Caps-фикса (md5 `2ad1f7e1c8c8807739b636cc0650a527`) | +| `~/Documents/karabiner.json.new` | Снимок рабочей версии от 2026-09-15 (md5 `4f643933…`) | | `~/.config/karabiner/assets/complex_modifications/*.json` | Импортированные наборы правил (не редактируются вручную) | ### ⚠️ Расхождение канона и живого файла (обнаружено 2026-09-15) @@ -46,46 +49,46 @@ updated: 2026-09-15T13:10:00.000Z ⚠️ **Это состояние УСТАРЕЛО.** Во второй сессии Alex приказал вернуть `.new` — актуальный статус см. в разделе «Файловое состояние (актуально, после возврата `.new` в 13:06)» ниже по документу. -## 🔴🔴 ГЛАВНАЯ НАХОДКА: `right_control` ремапнут в `devices[].simple_modifications` +## 🔴🔴 Проблема с app-комбо `right_control+…` (симптом `≈`) — ДИАГНОЗ НЕ ЗАКРЫТ -**Дата:** 2026-09-15 (вторая сессия). **Запрос Alex:** «почему сломались комбинации переключения аппов (`right_control+…`)?» +**Дата:** 2026-09-15 (вторая и третья сессии). **Запрос Alex:** «почему сломались комбинации переключения аппов (`right_control+…`)?» ### Симптом -`right_control+x` вместо запуска Xcode печатает **`≈`**. Аналогично ломаются все остальные app-комбо. +`right_control+x` вместо запуска Xcode печатает **`≈`**. Аналогично ломаются остальные app-комбо. -### ✅ ДИАГНОЗ (подтверждён фактом из конфига) +### ❌ ОПРОВЕРГНУТАЯ ГИПОТЕЗА (была записана как «подтверждённый диагноз» — НЕВЕРНО) -**Физическая правая Control НЕ приходит в систему как `right_control`.** Она ремапится на уровне устройства. В `profiles[0].devices[].simple_modifications` живого конфига (версия 155 937 байт) прописано: +Ранее в этом документе утверждалось: «ремап `right_control → right_option` в `devices[].simple_modifications` есть только в откаченном `.bak.20260915`, а в рабочем `.new` его нет — поэтому откат убил комбо». -```json -{ "from": { "key_code": "right_control" }, "to": [{ "key_code": "right_option" }] }, -{ "from": { "key_code": "right_option" }, "to": [{ "key_code": "right_command" }] } -``` +**Это опровергнуто прямым сравнением.** Факт: ремап `right_control → right_option` присутствует в **обоих** файлах, и в живом конфиге, и в `karabiner_20260902.json`, у встроенной клавиатуры (`vid 1204 pid 257`): -Присутствует у **всех трёх** клавиатур в `devices[]` (vid 1204/pid 257, vid 1133/pid 49948, vid 1267/pid 259). - -**Следствие:** Karabiner видит нажатие как `right_option`. Все **43** манипулятора группы `#0 Launch Apps HotKeys` ждут в `from.modifiers.mandatory` ровно `right_control`. Такого нажатия не приходит **никогда** → правило не матчится → нажатие уходит в систему напрямую → RussianWin отдаёт свой стандартный символ на `opt+x`, а это `≈`. - -**Механизм идентичен случаю с `Ї`** (см. раздел про Caps Lock): «сырой» символ раскладки = признак того, что Karabiner пропустил нажатие. Не вывод `to`, а провал матча `from`. - -### Почему это вылезло именно после отката - -| Версия конфига | Размер | Секция `devices[]` | Комбо `right_control+…` | +| Файл | `right_control→right_option` у vid 1204 | `devices[]` | Размер | |---|---|---|---| -| `karabiner.json.new` (текущая рабочая, md5 `4f643933…`) | 96 877 | **ремапа `right_control→right_option` НЕТ** | **работают** | -| `karabiner.json.bak.20260915` (откат, md5 `2ad1f7e1…`) | 155 937 | ремап есть | **мертвы** | +| `karabiner.json.new` (рабочая, 96 877) | **есть** | 3 | 96 877 | +| `.bak.20260915` (откат, 155 937) | **есть** | 3 | 155 937 | +| `automatic_backups/karabiner_20260902.json` | **есть** | 4 | 110 898 | -Разница в 59 KB — это в основном старая обвязка в `devices[].simple_modifications` (включая `application→right_control`, `left_command↔left_option`, consumer-keys на F7–F12). +Клавиатурные ремапы между этими тремя версиями **идентичны**. Разница в `devices[]` между `.new` и `.bak.20260915` — **нулевая** (3 устройства, 21 `simple_modifications`, одинаковый набор ремапов включая `right_control→right_option`, `application→right_control`, `left_command↔left_option`). + +**Единственное реальное расхождение `devices[]` с 02.09:** в `karabiner_20260902.json` есть **4-е устройство — мышь** `vid 11720 pid 20998` (`is_pointing_device: true`, `mouse_flip_vertical_wheel: true`, ремапов нет). В живом его нет. + +**Следствие для диагностики:** ремап `right_control→right_option` **не объясняет** симптом, потому что он был и в тот период, когда комбо работали. Причина `≈` по-прежнему **не найдена**. Не использовать опровергнутую гипотезу как объяснение. + +**Что это значит про разницу размеров 96 KB vs 155 KB:** это **не** `devices[]` (там всё одинаково). Разница — в текстовых полях `complex_modifications` (длина `description`). Проверялось несколько раз, функциональной разницы в правилах нет: 13 групп, 43 app-манипулятора, 39 с `right_control` — в обоих файлах одинаково. ### Ошибки агента в этой сессии — НЕ повторять | Что было сделано | Вывод | |---|---| -| Откат на `.bak.20260915` **без предварительного diff** `devices[]` | Снёс рабочую обвязку и убил 43 app-комбо. Откат «на бэкап» ≠ откат к рабочему состоянию: бэкап может быть старше по структуре, а не только по правкам | -| Поиск причины в `complex_modifications` (правила `r0 m7`/`m8`, `device_if`) | Правила были целы и идентичны. Причина лежала в **другой секции** конфига — `devices[].simple_modifications`. При «правило не срабатывает» проверять **обе** секции | -| Гипотеза «Karabiner потерял Input Monitoring» / «не та клавиатура» | Мимо. Процессы Karabiner живы, конфиг валиден. Причина — ремап внутри самого конфига | -| Просьба к Alex самому нажать комбо для проверки | **Алекс это отверг** — задачу решать агенту, не перекладывать проверку на пользователя. Скрейпить факты из файлов, а не спрашивать | +| Откат на `.bak.20260915` **без предварительного diff** | Нарушение собственной процедуры. Откат «на бэкап» ≠ откат к рабочему состоянию | +| Гипотеза «в бэкапе нет обвязки app-комбо» | **Опровергнута:** в бэкапе те же 43 манипулятора и 39 с `right_control` | +| Гипотеза «в `.new` нет `devices`-ремапа» | **Опровергнута:** ремап есть в обоих | +| Гипотеза «Karabiner потерял Input Monitoring / Accessibility» | **Опровергнута Alex:** модификаторные правила работают → Karabiner нажатия видит | +| Гипотеза «`shell_command` не выполняется из-за прав» | **Опровергнута:** `shell_command` выполняется, `open -b com.apple.dt.xcode` → exit 0, Xcode запускается. В логе есть чужие `shell_command stderr` (Photoshop) — значит механизм рабочий | +| Три подряд взаимоисключающие версии, каждая опровергалась следующим `jq`-запросом | Прежде чем объявлять причину — проверять её **двумя независимыми фактами сразу** | +| Просьба к Alex самому нажать комбо для проверки | **Алекс это отверг** — задачу решать агенту, не перекладывать проверку на пользователя | +| Разбор истории бэкапов и diff, когда Alex просил «фактический diff» | Alex требовал буквальный `diff -u` двух JSON, а не пересказ «что изменилось». Давать машинный вывод, не интерпретацию | ### 🔎 Ключевая диагностическая процедура: «правило есть, но не срабатывает» @@ -93,15 +96,19 @@ updated: 2026-09-15T13:10:00.000Z ```bash /usr/bin/jq -r '.profiles[0].devices[].simple_modifications[] | "\(.from.key_code) -> \(.to[0].key_code)"' ~/.config/karabiner/karabiner.json ``` - **Если нужный модификатор там переназначен — все правила на него мертвы.** Это первое, что надо смотреть, а не содержимое `complex_modifications`. + ⚠️ **Важно:** наличие ремапа «целевого» модификатора само по себе **не доказывает** поломку. В этой системе `right_control→right_option` есть всегда, в том числе в периоды, когда комбо работали. Ремап — гипотеза, требующая независимого подтверждения, а не улика. 2. Сверить число правил на целевой модификатор: `/usr/bin/jq '[.profiles[0].complex_modifications.rules[].manipulators[] | select((.from.modifiers.mandatory // []) | index("right_control"))] | length'` -3. Только после этого смотреть `device_if`-условия и `to`. +3. **Сравнивать не только с бэкапами, но и с `automatic_backups/`** — там лежат автоматические снимки Karabiner по датам (см. раздел ниже). +4. Смотреть `device_if`-условия: манипулятор с условием `device_if` срабатывает **только** на этой клавиатуре. +5. **Читать живой лог сразу после нажатия.** Если правило сработало, но `shell_command` упала — в `console_user_server.log` будет `shell_command stderr:`. Если правило не сработало — записи не будет вообще. Это единственный способ различить «правило не матчится» от «команда падает». ### ⚠️ Что НЕ является причиной - **Права Input Monitoring / Accessibility у Karabiner.** Проверялось и **опровергнуто фактом**: модификаторные правила работают, значит Karabiner нажатия видит. `core_service.log` содержит перемежающиеся `core_service_daemon_client connect_failed: Permission denied`, но каждая такая запись завершается `is connected` — это штатный ре-коннект сокета после sleep/wake, **не** отозванные права. Не путать с поломкой. - **`shell_command` не может печатать символы** — верно технически, но это следствие, не причина. `shell_command` просто не даёт вывода в раскладку; `≈` приходит из системы, потому что матч провалился. Сам факт `shell_command` запуск приложения не ломает. - **Несуществующий бандл приложения.** Проверено: `open -b com.apple.dt.xcode` → exit 0, Xcode запускается. Команда из правила валидна. Ошибка в логе `shell_command stderr: ... Photoshop CC 2018.app does not exist` относится к другому, действительно удалённому приложению. +- **Разница размеров `.new` (96 KB) vs `.bak.20260915` (155 KB) — НЕ в `devices[]`.** Проверено: оба содержат 3 устройства, 21 `simple_modifications`, идентичный набор ремапов. Разница — в длине текстовых полей `description`. Функциональной разницы в правилах нет (13 групп, 43 app-манипулятора, 39 с `right_control` — в обоих файлах). +- **Ремап `right_control → right_option`** — присутствует **исторически всегда**, в т.ч. в `karabiner_20260902.json` и в рабочем `.new`. Гипотеза «откат убил комбо через ремап» **опровергнута**. - **Проверка бандлов через `osascript -e "id of app \"$b\""`** — **недостоверна** в этой системе: вернула «НЕ НАЙДЕН» для всех бандлов, включая рабочие. Не использовать этот способ как доказательство отсутствия приложения; применять `open -b ` + проверку `pgrep`. - Отсутствие `optional: caps_lock` — к `right_control`-комбо отношения не имеет. - Права 644 / md5 канона и живого — были в порядке, конфиг не сбрасывался. @@ -130,21 +137,36 @@ chmod 644 ~/.config/karabiner/karabiner.json **Статус: НЕ применено. Ждёт команды Alex.** -### Файловое состояние (актуально, после возврата `.new` в 13:06) +### Файловое состояние (обновлено 2026-09-15 13:53 — конец третьей сессии) -Alex приказал вернуть `.new` на место — канон и живой снова = рабочая версия. +⚠️ **Живой конфиг менялся минимум 4 раза за час** — Karabiner UI / Alex правят его активно. Перед любой работой заново снимать md5, не опираться на таблицу: + +| md5 | Размер | Время | Примечание | +|---|---|---|---| +| `4f643933f9565330fd2111973c865563` | 96 877 | 13:06 | залит агентом как `.new` | +| `50e3bdd5…` | 156 088 | ~13:10 | перезаписан извне, 3 устройства | +| `ffb65c53…` | 111 191 | 13:53:07 | **текущий**. 4 устройства (мышь вернулась), права **600**, группа #0 = **45** | + +**🔴 Текущая проблема: права `600`.** `-rw-------` вместо `644` → прямой риск молчаливого сброса конфига. Лечение: +```bash +chmod 644 ~/.config/karabiner/karabiner.json +``` + +**Раскладка по путям (актуально на конец сессии):** | Файл | md5 | Размер | Роль | |---|---|---|---| -| `~/Documents/karabiner.json` | `4f643933f9565330fd2111973c865563` | 96 877 | **канон — рабочая версия** | -| `~/.config/karabiner/karabiner.json` | `4f643933f9565330fd2111973c865563` | 96 877, права **644** | живой = канон, подхвачен в 13:06:21 (`core_configuration is updated`) | -| `~/Documents/karabiner.json.new` | `4f643933f9565330fd2111973c865563` | 96 877 | источник возврата (теперь дубль канона) | -| `~/Documents/karabiner.json.rolledback.20260915` | `2ad1f7e1c8c8807739b636cc0650a527` | 155 937 | **страховка: откаченное состояние** (ремап `right_control→right_option` внутри) | -| `~/Documents/karabiner.json.bak.20260915` | `2ad1f7e1c8c8807739b636cc0650a527` | 155 937 | бэкап, на который откатывались | -| `~/Documents/karabiner.json.bak.20260915.keep` | `2ad1f7e1c8c8807739b636cc0650a527` | 155 937 | страховочная копия бэкапа | +| `~/Documents/karabiner.json` | `4f643933…` | 96 877 | канон (отстал от живого!) | +| `~/.config/karabiner/karabiner.json` | `ffb65c53…` | 111 191, права **600** ⚠️ | **живой — свежее канона** | +| `~/Documents/karabiner.json.new` | `4f643933…` | 96 877 | источник возврата `.new` (13:06) | +| `~/Documents/karabiner.json.rolledback.20260915` | `2ad1f7e1…` | 155 937 | страховка: откаченное состояние | +| `~/Documents/karabiner.json.bak.20260915` | `2ad1f7e1…` | 155 937 | бэкап, на который откатывались | +| `~/Documents/karabiner.json.bak.20260915.keep` | `2ad1f7e1…` | 155 937 | страховочная копия бэкапа | | `~/Documents/karabiner.json.bak` | `44ca420798be5ab38ff3c1d54c1c6fb9` | 153 847, Jun 15 | старый бэкап | -**Процедура возврата `.new` (выполнена):** +**Вывод: канон `~/Documents/karabiner.json` отстал от живого.** Живой содержит правки (45-й манипулятор, честные клавиши `o`/`i`/`k`, возвращённая мышь), которых в каноне нет. При следующей правке редактировать **живой**, а не заливать канон поверх. + +**Процедура возврата `.new` (выполнена в 13:06):** ```bash cp -p ~/Documents/karabiner.json ~/Documents/karabiner.json.rolledback.20260915 # страховка текущего cp -p ~/Documents/karabiner.json.new ~/Documents/karabiner.json @@ -152,23 +174,114 @@ cp -p ~/Documents/karabiner.json ~/.config/karabiner/karabiner.json chmod 644 ~/.config/karabiner/karabiner.json ``` -**Статус задачи app-комбо на конец сессии:** конфиг возвращён на рабочую версию, но Alex **не подтвердил**, что комбо ожили. Если `≈` остаётся и на `4f643933…` — гипотеза о ремапе `devices[]` неполна, и следующий шаг: смотреть живой лог `console_user_server.log` **сразу после нажатия** `right_control+x` (там пишутся `shell_command stderr`), плюс EventViewer. +**Статус задачи app-комбо:** конфиг возвращён на рабочую версию, но **Alex не подтвердил, что комбо ожили**. Причина `≈` **не найдена** — все выдвинутые версии опровергнуты. Следующий шаг: читать `console_user_server.log` немедленно после нажатия `right_control+x` (там появятся либо `shell_command stderr`, либо ничего), плюс EventViewer. -## Структура профиля (на 2026-09-15) +## 🔴 Группа #0 `Launch Apps HotKeys` — фактическая карта клавиш (2026-09-15, живой конфиг `ffb65c53…`, 45 манипуляторов) -Один профиль: `Default profile`, `selected=true`. `simple_modifications` — пустой (0). Все правила — в `complex_modifications.rules[]`. +**Главная ловушка раздела:** в группе #0 **описание манипулятора ≠ физическая клавиша**. Многие app-комбо висят на «служебных» клавишах (`scroll_lock`, `pause`, `print_screen`, `home`), потому что на них заведён правый Control в некоторых клавиатурах. Проверять всегда по `from.key_code`, не по `description`. + +### Расхождения «описание обещает → реально нажато» + +| Описание | Реальная клавиша | Найдено в сессии | +|---|---|---| +| `Fn+Opt+O` → Outlook | `scroll_lock` (стр. 33) + **`o` (стр. 34)** | обе версии, `o` добавлен позже | +| `Fn+Opt+P` → Photoshop | `pause` — **правило УДАЛЕНО** | ⚠️ Photoshop больше не запускается | +| `Fn+Opt+Shift+P` → Preview | `pause` (16) + **`p` (17)** | дубль по смыслу | +| `Fn+Opt+I` → Safari | `print_screen` (27) + **`i` (28)** | обе | +| `Fn+Opt+K` → Calendar | `home` (41) + **`k` (42)** | обе | +| `Fn+Opt+Shift+K` → Console | `home` (43) | | +| `Fn+Opt+left` → Mission Control Left | `home` (39) → `open_bracket`, без модификаторов | | +| `Fn+Opt+right` → Mission Control Right | `end` (40) → `close_bracket`, без модификаторов | | +| `Ctrl+Shift+Esc` → Activity Monitor | `escape` (2) / `grave_accent_and_tilde` (1, External kb) | | + +### Дубли, требующие внимания + +- **стр. 16 и 17** — оба `Ctrl+Opt+Shift+P → Preview`, описания идентичны, клавиши разные (`pause` / `p`). Оставить одну. +- **стр. 8** — `x`+`right_control` → Xcode. Второй дубль `x` с условием `device_if Logitech (vid 1133 pid 49948)` **удалён** в версии 13:53 (был в `50e3bdd5…`). +- **стр. 21** — `Solves.app` на `c+right_control+right_shift+right_command`; существование бандла не проверено. +- **стр. 25** — `Cmd+Alt+,` → System Settings, но модификаторы **правые** (`right_command+right_option`) — на встроенной клавиатуре может не срабатывать из-за ремапов `devices[]`. + +### Правила на честных буквах (совпадают с описанием) + +`a`→Asana, `w`→Warp, `e`→Excel, `r`→RDP, `x`→Xcode, `z`→Zoom, `d`→DuckDuckGo, `m`→Mattermost, `v`→VOX/VirtualBuddy, `s`→Sublime/Spotify, `g`→Chrome/GitHub/GIMP, `c`→Cursor/Calculator, `h`→Hopper, `y`→Yandex Music, `t`→ToDo/Translate/Telegram, `n`→Google Keep, `u`→uTorrent, `j`→Console, `b`→Bitwarden, `f`→Finder, `o`→Outlook, `i`→Safari, `k`→Calendar. + +**Проверка существования приложения из правила** (не через `osascript` — он ложноотрицателен): +```bash +open -b && pgrep -x # или open "/path/to/App.app" +``` + +## `automatic_backups/` — автобэкапы Karabiner (впервые описано) + +Karabiner сам делает снимки конфига в `~/.config/karabiner/automatic_backups/`. **Это самый полезный источник для сравнения «что изменилось»** — глубже, чем ручные `.bak` файлы в `~/Documents/`. + +Список на 2026-09-15 (14 файлов): + +| Файл | Размер | Дата | +|---|---|---| +| `karabiner_20210603.json` | 5 661 | 2021-06-03 | +| `karabiner_20211227.json` | 84 162 | 2021-12-27 | +| `karabiner_20220419.json` | 84 157 | 2022-04-19 | +| `karabiner_20221121.json` | 101 816 | 2022-11-21 | +| `karabiner_20230912.json` | 110 038 | 2023-09-12 | +| `karabiner_20231102.json` | 110 028 | 2023-11-02 | +| `karabiner_20231111.json` | 122 059 | 2023-11-11 | +| `karabiner_20241105.json` | 143 731 | 2024-11-05 | +| `karabiner_20250314.json` | 142 755 | 2025-03-14 | +| `karabiner_20250519.json` | 153 847 | 2025-05-19 | +| `karabiner_20260615.json` | 46 972 | 2026-06-15 | +| `karabiner_20260706.json` | 155 934 | 2026-07-06 | +| `karabiner_20260831.json` | 155 871, права 600 | 2026-08-31 | +| `karabiner_20260902.json` | 110 898, права 600 | 2026-09-02 | + +### Команда фактического diff (то, что просил Alex) + +```bash +cd /tmp +/usr/bin/jq -S . ~/.config/karabiner/karabiner.json > kb_A.json +/usr/bin/jq -S . ~/.config/karabiner/automatic_backups/karabiner_20260902.json > kb_B.json +diff -u kb_B.json kb_A.json +``` +`jq -S` (sort keys) обязателен — без него diff утонет в перестановках ключей. Через `diff -u` вывод машинный и точный; **не заменять пересказом «что изменилось»** — Alex требует буквальный diff. + +### Найденные расхождения с `karabiner_20260902.json` (diff -u, 5 ханков) + +| Что | В 02.09 | Сейчас (на момент diff) | +|---|---|---| +| `Fn+Opt+X` → Xcode | один манипулятор | **два** (второй с `device_if` Logitech) — позже снова один | +| `Preview (Logitech)` на `pause`, `p` | **есть (2 шт.)** | удалены | +| `Fn+Opt+O` → Outlook | на `o`+`right_control` | был `scroll_lock`, описание врало; сейчас `o` возвращён | +| `Hopper Disassembler.app` | `.app` без `v4` | `v4.app` | +| `cmd+alt+c to ç` (`EN/ABC symbol keys`) | нет | **добавлен** (condition `input_source_if language: en`) | +| `alt+shift+slash` → `?` | без `caps_lock` | **`optional: ["caps_lock"]` добавлен** (правка агента, осталась) | +| Устройство-мышь `vid 11720 pid 20998` | **есть** (`mouse_flip_vertical_wheel: true`) | отсутствовало, **возвращено** в версии 13:53 | +| `vid 1204 pid 257`: `from.key_code` | `right_command` → `right_option` | в живом — `right_control` → `right_option` (⚠️ в 02.09 тоже есть `right_control`; раннее утверждение об этом расхождении было ошибкой) | + +### Мышь `vid 11720 pid 20998` + +Существует **только** в `automatic_backups/karabiner_20260902.json` — её нет ни в одном `~/Documents/karabiner*.json*`, ни в остальных 13 автобэкапах. Конфигурация: `is_pointing_device: true`, `ignore: false`, `mouse_flip_vertical_wheel: true` (инверсия вертикального скролла), `simple_modifications` пуст. Если инверсия скролла пропала — эта запись должна быть возвращена в `devices[]`. + +## Устройства (`devices[]`) на 2026-09-15 + +| vid | pid | Тип | Ремапы | `simple_mods` | +|---|---|---|---|---| +| 1204 | 257 | встроенная клавиатура | `application→right_control`, `right_control→right_option`, `right_option→right_command`, `left_command↔left_option`, `backslash→vk_none`, `insert→backslash`, F7–F12→consumer keys | 13 | +| 1133 | 49948 | Logitech | `right_control→right_option`, `right_command→right_option`, `right_option→right_command`, `left_command↔left_option` | 4 | +| 1267 | 259 | внешняя | `right_option→right_command`, `left_command↔left_option` | 3 | +| 11720 | 20998 | **мышь** | нет | 0 (`mouse_flip_vertical_wheel: true`) | + +**`simple_modifications` на верхнем уровне профиля пуст (0)** — все device-ремапы живут в `devices[].simple_modifications`. Правила — в `complex_modifications.rules[]`. Группы правил (индекс → название → число манипуляторов): | # | Правило | Манипуляторов | |---|---|---| -| 0 | Launch Apps HotKeys | 43 | +| 0 | Launch Apps HotKeys | **45** (было 43; растёт по мере правок Alex) | | 1 | Russian @ from opt+cmd+2 | 1 | | 2 | Xcode Keyboard helpers | 7 | | 3 | F Keys | 8 | | 4 | Media Keys, F Keys | 11 | | 5 | Smart Quotes | 8 | -| 6 | EN/ABC symbol keys | 4 | +| 6 | EN/ABC symbol keys | 4 (в 02.09 — 3; добавлен `cmd+alt+c to ç`) | | 7 | **Russian symbol keys** | **27** | | 8 | Cmd+Space to switch language in RDP | 1 | | 9 | Remap Keys in Microsoft Remote Desktop | 1 | @@ -339,10 +452,17 @@ Alex в изначальном запросе назвал комбинацию ## Pitfalls -- **🔴 ПЕРВЫМ ДЕЛОМ ПРОВЕРЯТЬ `devices[].simple_modifications`.** Если нужный `from`-модификатор там переназначен (в этой системе `right_control → right_option`), то **все** правила на него в `complex_modifications` мертвы, сколько бы их ни было. Симптом: вместо действия печатается «сырой» символ раскладки (`opt+x` → `≈`). Правило «не срабатывает» ≠ ошибка в правиле; проверять **обе** секции конфига, а не только `complex_modifications`. -- **Откат «на бэкап» ≠ откат к рабочему состоянию.** Перед откатом делать `diff` по структуре (`devices[]`, число правил, размер), а не только по целевой правке. `.bak.20260915` (155 937) структурно старше и содержит ремап, которого нет в рабочей версии (96 877) — откат на него убил 43 app-комбо. Хранить рабочие снимки как `.new` до подтверждения, что откат вернул работоспособность. +- **🔴 `description` манипулятора ≠ физическая клавиша.** В группе #0 многие правила подписаны буквой (`Fn+Opt+O to launch Outlook`), а фактически висят на служебной клавише (`scroll_lock`, `pause`, `print_screen`, `home`). **Всегда проверять по `from.key_code`**, не по `description`: + ```bash + /usr/bin/jq -r '.profiles[0].complex_modifications.rules[0].manipulators[] | "\(.from.key_code) + \((.from.modifiers.mandatory // [])|join("+")) | \(.to[0].shell_command // .to[0].key_code) | \(.description)"' ~/.config/karabiner/karabiner.json + ``` +- **🔴 `devices[].simple_modifications` — сначала смотреть, но НЕ считать уликой.** Если нужный `from`-модификатор там переназначен, это **кандидат** в причины, а не доказательство: в этой системе `right_control→right_option` присутствует **всегда**, в том числе в периоды, когда комбо работали. Гипотеза подлежит независимой проверке. +- **🔴 Не объявлять причину, пока она не подтверждена двумя независимыми фактами.** В этой сессии трижды подряд версия («нет обвязки в бэкапе» → «нет `devices` в `.new`» → «права отозваны») **опровергалась следующим же `jq`-запросом**. Цена: Alex раздражён, время потеряно. Сначала собрать 2 факта из разных секций конфига, потом говорить. +- **🔴 «Фактический diff» = машинный `diff -u`, а не пересказ.** Когда Alex просит сравнить два конфига, давать буквальный вывод `jq -S` + `diff -u`, а не таблицу «что изменилось». Пересказ был воспринят как «пиздоболия». +- **Откат «на бэкап» ≠ откат к рабочему состоянию.** Перед откатом делать `diff` по структуре (`devices[]`, число правил, размер), а не только по целевой правке. Хранить рабочие снимки как `.new` до подтверждения, что откат вернул работоспособность. - **Не перекладывать проверку на Alex.** Просьба «нажми комбо и скажи, что произошло» была отвергнута. Задачу решает агент: факты вытаскивать из файлов конфига, логов и процессов, а не спрашивать пользователя. -- **Права 600 → молчаливый сброс конфига.** `cp` сохраняет режим ИСТОЧНИКА, а не целевого файла. После каждого `cp` в `~/.config/karabiner/karabiner.json` → `chmod 644`. Симптомы сброса: Karabiner спрашивает про тип виртуальной клавиатуры, все complex_modifications исчезли. +- **Права 600 → молчаливый сброс конфига.** `cp` сохраняет режим ИСТОЧНИКА, а не целевого файла. После каждого `cp` в `~/.config/karabiner/karabiner.json` → `chmod 644`. Симптомы сброса: Karabiner спрашивает про тип виртуальной клавиатуры, все complex_modifications исчезли. ⚠️ **Права 600 возвращаются сами** — в этой сессии живой файл снова оказался `-rw-------` после серии внешних перезаписей. Проверять права при каждом обращении к конфигу, не только после своего `cp`. +- **Живой конфиг перезаписывается извне (Karabiner UI / синк).** За час наблюдения md5 сменился 4 раза (`4f643933` → `50e3bdd5` → `ffb65c53`). **Никогда не опираться на сохранённую таблицу md5** — снимать заново перед каждой операцией. Канон `~/Documents/karabiner.json` при этом отстаёт: свежие правки живут только в живом. - **Правила без явного условия Caps Lock.** Каждый манипулятор, чей `from` содержит `shift`, при активном Caps Lock **может перестать матчиться вообще** — нажатие уходит в систему и раскладка отдаёт свой стандартный символ (для `opt+shift+/` в RussianWin это `Ї`). Лечится добавлением `"optional": ["caps_lock"]` в `from.modifiers`, не трогая `mandatory`. - **Не переводить `shift` из `mandatory` в `optional`.** Если shift — часть combo (как в `opt+shift+/`), это расширит правило на более короткое сочетание (`opt+/`) и сломает соседнее правило. - **Не менять модификатор в `to` вслепую.** RussianWin **не является** аналогом US-раскладки: `opt+7` там = `&`, а не `?`. Замена `right_shift` → `right_option` в `to` даёт мусорный символ. Сначала проверить, что реально лежит на позиции в раскладке. @@ -369,7 +489,12 @@ Alex в изначальном запросе назвал комбинацию ## Связанные правила по флагам Caps (для справки) -Проверено на 2026-09-15: ссылок на `caps_lock` ни в `key_code`, ни в `from`/`to` в конфиге **нет** (0 совпадений). Ни один манипулятор не декларирует Caps в `optional` — именно поэтому Caps-состояние ломает матчинг у правил, где `shift` обязателен. +Проверено на 2026-09-15 (первый осмотр): ссылок на `caps_lock` ни в `key_code`, ни в `from`/`to` тогда **не было** (0 совпадений) — именно поэтому Caps-состояние ломало матчинг у правил, где `shift` обязателен. + +⚠️ **Обновлено:** в живом конфиге на конец сессии правка **присутствует** — у манипулятора группы #7 `alt+shift+slash -> ?` в `from.modifiers` добавлено `"optional": ["caps_lock"]` при `mandatory: ["option","shift"]`. Alex это подтверждения не давал; правка попала в конфиг и осталась (вероятно, при одной из внешних перезаписей). Проверить актуальное состояние: +```bash +/usr/bin/jq '.profiles[0].complex_modifications.rules[7].manipulators[13].from.modifiers' ~/.config/karabiner/karabiner.json +``` ## References