Известные Ловушки
Два Launcher Для Языков
Проблема: launcher_gui.cmd и launcher_gui_ru.cmd быстро создают путаницу.
Решение: один launcher_gui.cmd, язык переключается внутри UI или через конфиг.
NiceGUI Native Mode
Проблема: native=True и встроенный режим могут давать нестабильное поведение в portable/pywebview-сценариях.
Решение: запускать app.py как сервер с native=False, show=False, а окно открывать отдельным window.py.
NiceGUI ProcessPool В Закрытом Окружении
Проблема: NiceGUI может создавать multiprocessing process pool даже тогда, когда GUI использует только обычные io-bound задачи. В portable/sandbox/enterprise окружении это иногда падает на PermissionError или WinError 5.
Решение: app.py патчит NiceGUI setup и отключает process pool, если окружение его запрещает. Не используйте CPU-bound задачи NiceGUI без отдельной проверки; для обычного запуска сервисов через run.io_bound fallback безопасен.
Случайный Браузер
Проблема: пользователь запускает GUI, а открывается браузер.
Решение: app.py --no-browser внутри window.py; браузер только через явный --browser.
Страшная Консоль pywebview
Проблема: рядом с GUI висит консоль с [pywebview] Using WinForms / Chromium и служебным debug-выводом. Пользователь может закрыть её и убить приложение.
Решение: обычный launcher_gui.cmd должен предпочитать pythonw.exe, запускать GUI detached и закрываться. PYWEBVIEW_LOG по умолчанию держать на WARNING, а ошибки wrapper писать в logs/gui_window.log. Для отладки используйте отдельный dev/debug запуск через python.exe.
Всплывающие Окна pwsh На Каждый Файл
Проблема: GUI выглядит как desktop-приложение, но при конвертации или обработке каждого файла на долю секунды вспыхивает отдельное окно pwsh.exe/powershell.exe. Флаг -WindowStyle Hidden сам по себе может не помочь: окно создается раньше, чем PowerShell успевает применить стиль.
Решение: скрывать дочерний процесс на уровне Python subprocess, а -WindowStyle Hidden оставлять только как дополнительный слой. Для Windows используйте одновременно:
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
startupinfo.wShowWindow = 0
subprocess.Popen(
cmd,
startupinfo=startupinfo,
creationflags=subprocess.CREATE_NO_WINDOW,
)
В шаблоне это вынесено в system_core/core/jobs.py: для обычных CLI-вызовов используйте run_process(), для ручного Popen доступны hidden_subprocess_kwargs() и utf8_subprocess_env(). При миграции CLI-проекта, который дергает PowerShell helpers, запускайте их через эти helpers или аналогичный код. Отдельное "зеркальное" CLI-окно обычно не решает проблему, а только добавляет еще одно окно.
Невидимые Старые GUI-Серверы
Проблема: после перехода на pythonw.exe старый NiceGUI-сервер может остаться в фоне. Новый launcher подключается к старому состоянию, занимает порт или плодит процессы.
Решение: хранить PID управляемого сервера в logs/gui_server.pid, при старте launcher очищать предыдущий сервер этого же проекта, а при нормальном закрытии удалять PID-файл. Не создавать бесконечно новые порты как основной сценарий.
Занятый Порт
Проблема: [Errno 10048] на 127.0.0.1:PORT.
Решение: перед запуском проверять порт. Если сервер уже жив, не стартовать второй. Для тестов использовать отдельный порт.
Переключение Языка Рвёт Соединение
Проблема: live reload в pywebview может дать WinError 10054 или Connection lost.
Решение: считать runtime language switching вторичным. Разрешен explicit reload; для канареек допустим dark/RU default.
pywebview И proxy_tools
Проблема: pywebview может зависеть от proxy_tools, а тот приходит как sdist. При build isolation pip может упасть с Cannot import 'setuptools.build_meta'.
Решение: заранее скачать/установить setuptools, wheel, packaging, затем выполнять full install/download с --no-build-isolation.
Builder Печатает Success После Ошибки
Проблема: PowerShell скрипт запускает pip, pip падает, но wrapper продолжает шаги и показывает success.
Решение: оборачивать native commands в проверку $LASTEXITCODE и падать сразу.
Большие Кнопки Ломают Высоту
Проблема: залитые кнопки с длинным RU-текстом становятся двухстрочными и съедают экран.
Решение: compact ghost buttons, короткий label, описание справа.
Англицизмы В RU-Layout
Проблема: после портирования CLI в русском GUI остаются слова вроде embedded, render, layout, metadata, report, logs, config, workspace, хотя обычному пользователю понятнее русские аналоги. Интерфейс начинает выглядеть как смесь внутреннего CLI и пользовательского приложения.
Решение: переводить пользовательские названия, если есть нормальный русский аналог: встроенный растр, рендер страницы, раскладка, метаданные, отчёт, журнал, настройки, рабочая область, исходники, результаты. Если важно сохранить точное CLI-значение, показывать его в скобках: Встроенный растр (embedded).
Исключения не переводятся: форматы и расширения (JPG, PNG, PDF), аббревиатуры (DPI, ICC, CMYK, sRGB), CLI-флаги и значения (--mode embedded), config keys, API/model ids, бренды и реальные имена файлов/папок (input\, output\, logs\, report\, workspace\, config\ui_colors.yaml, NiceGUI, pywebview). Служебные toolbar-кнопки LOGS, CONFIG, REPORT, TOOLS могут оставаться английскими, если продуктово это задумано как технический shortcut.
Съезжающие Элементы В Header
Проблема: после добавления выбора темы или смены высоты header элементы выглядят почти правильно, но заголовок, иконка палитры, dropdown темы и переключатель языка сидят на разных вертикалях. Особенно часто это проявляется в Quasar/NiceGUI: ui.select с dense outlined визуально ниже обычного текста, а кнопка языка может казаться центрированной только относительно собственного box, но не всей шапки.
Решение: проверять реальный screenshot, а не только CSS. Для header задавайте стабильную высоту, одинаковое align-items: center, фиксированную высоту select/button и при необходимости небольшой transform: translateY(...) для группы controls или заголовка. Текущая калибровка шаблона: заголовок и .audion-header-controls подняты на 11px. Основной layout-блок .audion-shell не поднимать, иначе карточка рабочих папок/input/output прилипает к шапке. После каждой правки темы, font-size, dense, padding или высоты header делайте визуальный smoke: заголовок, theme dropdown и language switch должны сидеть на одной оси и не прилипать к верхней/нижней границе.
Кнопка Назад На Первом Экране
Проблема: disabled Назад на корневом экране всё равно выглядит как рабочая синяя кнопка из-за внутренних стилей Quasar или темы. Пользователь видит ложный путь назад.
Решение: на корневом уровне не рендерить Назад вообще. Показывать кнопку только внутри вложенного раздела или на финальном экране команды.
Внутренние Режимы Вместо Пользовательских Действий
Проблема: названия вроде SAFE, HARD, FHD, UHD, BATCH, ASK могут быть точными для CLI, но ничего не объясняют обычному пользователю.
Решение: в GUI сначала писать результат или область действия: "JPEG до 1920x1080", "Все растры", "Проверить файлы". В описании справа раскрывать внутренний смысл: какие форматы меняются, какие пропускаются, какой лимит применяется, есть ли запись на диск.
Редкий Интерактивный CLI-Режим В GUI
Проблема: CLI-команда, которая задаёт вопросы через stdin, в GUI-терминале может выглядеть как зависание и ломать сценарий "нажал и получил результат".
Решение: оставлять такие режимы в CLI/TUI как экспертные. В GUI выводить автоматические сценарии и read-only диагностику, если интерактивность не спроектирована как полноценный GUI-flow.
LF-Only CMD После Патча
Проблема: после обычного patch/edit .cmd может остаться UTF-8 без BOM, но часть строк станет LF-only. На Windows batch это может проявиться странными ошибками меню, кириллицы или переходов.
Решение: после каждой правки .cmd нормализовать файл и проверять: BOM=False, LoneLF=0. Это обязательная release-проверка, а не косметика.
В шаблоне для этого есть штатная команда:
install\Check-CmdEncoding.cmd -Fix
Она не заходит в runtime, wheelhouse, ._runtime, input, output, logs, report и workspace, чтобы внешние пользовательские файлы и scratch-артефакты не ломали release gate.
Кнопки Режут Начало Текста
Проблема: q-btn с justify-content: center и overflow: hidden у длинного label может обрезать текст с обеих сторон. Расширение окна не помогает, потому что режется внутренний flex-контент кнопки.
Решение: для строк команд использовать отдельный CSS-класс: фиксированная колонка кнопки, justify-content: flex-start, text-align: left, text-overflow: ellipsis вправо. Центрирование оставлять только для коротких toolbar-кнопок.
Верхние Кнопки Рабочих Папок Не Помещаются
Проблема: русские labels Добавить файлы... и Добавить папку... в верхнем workspace-блоке могут выглядеть тесно, особенно если пытаться держать все три кнопки одной ширины. Отдельное уменьшение шрифта только для этих кнопок нарушает общий ритм UI и потом конфликтует с INPUT/OUTPUT.
Решение: использовать шаблонный баланс ширин: Добавить файлы... и Добавить папку... - w-44, Очистить I/O - w-36, INPUT и OUTPUT - обычные w-20. Это лучше, чем заводить специальный workspace-action font-size.
Вложенное Меню Скрывает Плоские Operations
Проблема: если в config/tool_manifest.yaml появился раздел operation_groups, GUI показывает дерево команд вместо плоского списка operations. Можно решить, что старые команды пропали.
Решение: это ожидаемое поведение. При включении operation_groups перенесите важные пользовательские операции внутрь дерева. operations можно оставить для совместимости, CLI, тестов или старых интеграций, но видимый GUI-список будет строиться из дерева.
Финальный Лист Запускается Слишком Рано
Проблема: лист дерева можно случайно сделать прямой кнопкой запуска, и пользователь потеряет шанс проверить формат, DPI, ссылку или другие параметры.
Решение: лист дерева должен открывать финальный экран с Запустить и Назад. Запускать сервис сразу при клике по листу не надо.
Неуникальные Field ID
Проблема: значения fields хранятся в состоянии GUI по id. Если в разных ветках дерева использовать один и тот же id для разных смыслов, значения начнут переезжать между сценариями.
Решение: переиспользуйте один id только для одного и того же смысла, например dpi везде означает DPI. Для разных смыслов используйте разные ключи: audio_bitrate, video_bitrate, download_url, source_url.
Пустая Строка Как Авто-Режим
Проблема: для некоторых проектов пустое поле - это не отсутствие данных, а осознанный режим auto. Например, пустой target_columns может значить "выбрать колонки автоматически".
Решение: не превращайте пустые строки из GUI в None и не отбрасывайте их при сборке context.operation.parameters, если бизнес-логика различает "" и отсутствие ключа. Логируйте итоговые параметры перед запуском.
Runtime-Поля Перезаписывают YAML
Проблема: удобно взять значения из GUI и записать их обратно в project.yaml, но это опасно для неопытных пользователей и ломает воспроизводимость.
Решение: GUI fields должны быть runtime override для одного запуска. Передавайте их в сервис через context.operation.parameters; меняйте YAML только отдельной явной командой редактирования конфигурации.
Параметры Не Доходят До CLI
Проблема: GUI красиво показывает fields, но старый CLI или движок продолжает читать только YAML/глобальные константы и игнорирует runtime-параметры.
Решение: после добавления fields обязательно провести параметр через всю цепочку: tool_manifest.yaml -> Operation.parameters -> JobContext.operation.parameters -> service -> CLI/engine. В smoke-проверке отдельно убедиться, что пустые и заполненные поля меняют источник настройки.
Checkbox-Группа Ничего Не Фильтрует
Проблема: пользователь выбирает DOCX/PPTX/XLSX или другие режимы чекбоксами, но сервис запускает старый CLI без учета списка. Визуально всё выглядит правильно, а результат не меняется.
Решение: type: "checkboxes" возвращает список выбранных value в context.operation.parameters. Сервис обязан превратить этот список в аргумент CLI, временный runtime config или прямой параметр engine. Для фильтров файлов проверяйте именно этап поиска, а не только этап конвертации.
Пустая Checkbox-Группа
Проблема: пользователь снял все флажки, а движок либо обработал всё, либо упал с непонятной ошибкой.
Решение: если пустой выбор недопустим, задавайте min_selected: 1 в manifest. GUI не должен запускать leaf-команду, пока условие не выполнено. Если пустой выбор означает auto/default, зафиксируйте это в description и smoke-тесте.
Checkbox Default Случайно Обрабатывает Лишнее
Проблема: GUI по умолчанию отмечает часть или все форматы, пользователь не замечает флажки и запускает лишнюю обработку.
Решение: для новых GUI-миграций держите checkbox-группы пустыми по умолчанию: default: []. Если выбор обязателен, добавьте min_selected: 1, чтобы запуск без флажков не прошёл.
Dropdown Для Маленького Выбора
Проблема: выбор из двух-трёх фиксированных режимов спрятан в dropdown. Пользователь не видит все варианты сразу и воспринимает поле как ещё один длинный список.
Решение: используйте type: "radio" для малых fixed single-choice. Dropdown оставляйте для длинных списков, динамических provider-моделей, файлов, ключей и правил.
Дублирующие Кнопки Запуска
Проблема: GUI показывает Запустить аудит и Запустить весь процесс, хотя первая команда уже делает render при необходимости, вызывает движок и пишет итоговые отчёты. Пользователь не понимает, чем отличается "полный" путь.
Решение: оставьте один видимый запуск для одного пользовательского результата. Wrapper-режимы можно держать в CLI/TUI, разделе подготовки или экспертном меню.
Дублирующее Избранное
Проблема: рядом с dropdown есть чекбокс В избранное, а ниже кнопка Добавить ... в избранное. Непонятно, что сработает при запуске, а что меняет список сразу.
Решение: для одного списка на одном экране используйте один механизм. Если это отдельная мутация кэша, лучше явная кнопка действия. Чекбокс годится там, где он естественно относится к сохранению/импорту текущей записи.
Висячая Безымянная Команда
Проблема: на экране есть ключ, модель, инструкция и режим, а рядом стоит команда В избранное, Сохранить или Удалить. Пользователь вынужден угадывать, к какому объекту относится действие.
Решение: label команды должен назвать объект или быть визуально привязан к единственному полю. Пишите Ключ в избранное, Модель в избранное, Инструкцию в избранное, Удалить быструю инструкцию, Сохранить профиль. Если команда относится к нескольким объектам, разбейте её или назовите результат целиком.
Список Моделей Принят За Проверку Доступа
Проблема: provider model list вернул модель, но generate/smoke API для конкретного аккаунта отвечает 404, 403, not available или похожей ошибкой. Пользователь начинает искать баг в коде, хотя проблема в доступности модели.
Решение: общий список моделей и проверка выбранной модели должны быть разными действиями. Dropdown можно обновлять бесплатно/дёшево через model list, а доступность проверять отдельной кнопкой с маленьким запросом и кэшировать статус с датой.
Старый Файл Списка Моделей Живёт Рядом С Новым Движком
Проблема: после добавления live dropdown/cache/favorites/smoke в проекте остаётся ручной models.yaml, models.txt или набор provider-профилей. Через месяц он устаревает, но выглядит как официальный источник, и пользователь не понимает, чему верить.
Решение: в развитых LLM-проектах live model selector отменяет старые статические файлы списков моделей. YAML должен хранить стабильные настройки провайдера, лимиты и prompts. Model ids берите из provider list/cache/favorites/smoke. Статический список допустим только как legacy fallback для простого проекта без provider API.
Нет Визуальных Smoke-Скриншотов
Проблема: кодовые smoke-тесты проходят, но после портирования dropdown слишком узкий, форма скроллится без нужды, рамки спорят с текстом или финальный статус не виден.
Решение: после layout-правок сохраняйте smoke-скриншоты ключевых экранов в report\gui_smoke_screenshots\ или аналогичной папке. Минимум: root, большой экран команды, Дополнительно, терминал после короткого успешного запуска.
Терминал Слишком Маленький
Проблема: GUI выглядит красиво, но пользователь не видит важный вывод.
Решение: терминальная область справа должна занимать примерно 2/3 высоты окна или больше.
WUXGA И Windows Scaling
Проблема: на ноутбуке WUXGA 1920x1200 при масштабе Windows 150% доступная логическая область заметно меньше обычного desktop. Ранний breakpoint вроде 1420px ломает двухколоночный GUI: терминал уезжает вниз, а пользователь получает длинную вертикальную ленту.
Решение: стартовать pywebview в 1600x900, но держать минимальный размер около 1180x720, компактную сетку полей и перетаскиваемый разделитель. Две колонки сохранять до примерно 900px CSS-ширины. Не ставить широкие минимумы колонок вроде 820px + 560px.
Прямая Работа С Сетевыми Файлами
Проблема: Office/PDF операции на сетевых путях менее надежны и труднее диагностируются.
Решение: сначала копировать выбранные файлы/папки в локальный input, потом запускать обработку.
Русский Текст В Терминале GUI
Проблема: GUI-терминал показывает ���� вместо русских имен файлов, если дочерний CLI пишет в pipe не в UTF-8.
Решение: при запуске CLI из GUI выставлять PYTHONUTF8=1 и PYTHONIOENCODING=utf-8, а в самом CLI по возможности делать sys.stdout.reconfigure(encoding="utf-8", errors="replace") и то же для stderr.
Всплывашка Завершения Пропала
Проблема: ui.notify("Операция завершена") полезен, но если окно было неактивно, пользователь может не увидеть сообщение. После долгой операции это рождает тревогу: "оно точно закончилось?".
Решение: не считать notification источником истины. Финальный статус хранится в GUI state и постоянно отображается под терминалом: серый индикатор для ожидания, синий пульс во время работы, зеленый после успешного завершения, красный после ошибки. Он остается на экране до следующего запуска.
HiDPI В Native Picker
Проблема: системный Windows picker может выглядеть мелким или странно масштабироваться при UI scale не 100%.
Решение: запускать picker через STA PowerShell и перед созданием WinForms dialog делать best-effort DPI awareness. Если Windows всё равно игнорирует масштаб, это ограничение native common dialogs; следующий уровень надежности - собственный GUI picker.
JSON В Output
Проблема: .json-метаданные рядом с пользовательскими файлами засоряют output.
Решение: хранить machine-readable артефакты в report/run_<timestamp> и стабильные индексы в report/latest, а кнопку REPORT держать рядом с LOGS.