behaviour-logs
Логи и замеры поведения киоска — журнал операций, лог бэкенда, временный журнал касаний, приёмы измерения в браузере и ловушки фоновой вкладки. Использовать, когда «на приборе не работает», нужно дока
SKILL.md.claude/skills/behaviour-logs/SKILL.md
GitHubЛоги поведения
Киоск стоит в зале, и жалобы приходят словами покупателя: «срабатывает со второго раза», «свайп не работает», «этикетка не печатается». Угадывать по описанию дорого — в этом проекте три подряд правильно звучавшие догадки оказались мимо. Здесь собрано, что прибор записывает сам, что можно включить на время и как получить доказательство.
Что записывается постоянно
- Журнал операций — таблица
transactions, видна в админке и черезGET /api/transactions. Одна строка на напечатанную этикетку: время (местное, чтобы совпадало с бумагой), товар, вес, цена, сумма, штрихкод, файл растра. Это единственный долгоживущий след поведения покупателя. - Чего в нём нет: касаний, выбранных и брошенных товаров, поисковых запросов, отказов печати. Если понадобится статистика «что смотрели, но не купили» — это новая сущность, а не расширение журнала операций: тот привязан к факту продажи и на него ссылается мягкое удаление товаров.
- Лог бэкенда — вывод uvicorn. Там видны все запросы и трассировки. Проверять его
стоит раньше, чем лезть в код:
POST /api/print 500сsqlite3.OperationalError: disk I/O errorоднажды выглядел как «печать сломалась во фронтенде», а на деле процесс держал битое подключение к базе после блокировки папки антивирусом.
Журнал касаний
Для разбора «срабатывает со второго раза» в киоск временно вводится журнал указателя:
слушатели pointerdown, pointerup, pointercancel, click, touchstart,
touchend, touchcancel на окне в фазе перехвата, вывод — поверх экрана, включается
?taps=1 в адресе.
Что из него удалось узнать и чего иначе не увидеть:
- клик может не родиться вовсе:
pointerdownиpointerupпо карточке в журнале есть,clickотсутствует — так проявляется подавление касания после броска; - клик может родиться и не дойти: пишите его дважды, на перехвате (
click↓) и на всплытии (click↑), и станет видно, что его гасят по дороге; touchstartс флагом «неотменяемое» означает, что жест забрал себе браузер, и дальше искать надо в его правилах, а не в нашем коде.
Журнал держат ровно до починки и убирают: он вешает семь слушателей на каждое касание
и рисует поверх всего экрана. В истории он есть — git log -S "tapsDebug".
Ловушки измерения в браузере
Проверять киоск удобно через браузерную автоматизацию, но фоновая вкладка врёт, и
врёт правдоподобно. document.visibilityState === 'hidden' — и тогда:
requestAnimationFrameне идёт: переходы Vue не доигрывают, уходящие элементы копятся в DOM. Насчитать «две ленты вместо одной» и пойти чинить утечку — потеря вечера;- таймеры зажимаются до секунды, а после пяти минут в фоне — до минуты: полуторасекундная выдержка «платформа освободилась» срабатывает с задержкой, и кажется, что не работает;
loading="lazy"не грузит ничего: пересечения с вьюпортом не вычисляются;- синтетический
left_click_dragшлётpointermoveбезpointerdown— жест не начинается, и любой свайп «не работает».
Отсюда правило: прежде чем поверить измерению, спросите document.visibilityState, а
жесты проверяйте синтетическими PointerEvent — они честнее псевдо-мыши.
Приёмы замера
- Экран прибора воспроизводится так: корню задаются 1920x1080 и
transform: scale()для обзора, а--s2l-kb-heightвыставляется значением для 1080 (340 px) — это единственная величина в вёрстке, завязанная наvh. - Живая лента среди уходящих:
[...document.querySelectorAll('.track')] .find(t => !/leave/.test(t.className)). Без этого замеры идут по уходящей копии, и клики попадают в мёртвые элементы. - Геометрию считайте в слоях:
getBoundingClientRect()подscale()делится на масштаб, аgetComputedStyleвозвращает уже честные пиксели раскладки — для долей и порогов берите второе. - Весы гоняются через
/api/sim/weight: положить груз, качнуть, снять. Симулятор качается затухающим колебанием, поэтому им проверяется и «зачекайте на стабілізацію», и конец сессии по освобождению платформы (см. скиллhardware-hal).
Правило, которое эти логи выявили
Пока касание не завершилось, на экране не двигается ничего. Между pointerdown и
click браузер решает, по какому элементу отдать клик; если раскладка успела съехать,
клик уходит соседу или растворяется в общем предке. Так ломались пейджер при открытой
клавиатуре и печать по карточке (сетка уезжала на 123 px, когда закрытие клавиатуры
возвращало шапку). Оба раза лечилось одинаково: отложить перестройку экрана до конца
касания. Ищите это первым, когда «нажимается со второго раза» или «нажал одно, получил
другое».