feat(robustness+ui): отказоустойчивость main, тесты, a11y-полировка, лицензия
Надёжность main-процесса: - глобальные uncaughtException/unhandledRejection (лог + flushNow) - safeHandle/safeOn вокруг всех IPC-хендлеров (не падаем молча, generic-ошибка наружу) - таймаут 4s на tasklist, Atomics.wait вместо busy-spin на exit-записи - единый log.error для фоновых сбоев вместо console.error/тишины Тесты (178 -> 203): meeting-detect, scheduler-gating, store (миграции/карантин/cap). UI/UX: - prefers-reduced-motion через MotionConfig + CSS media-блок - Spinner/Skeleton примитивы, loading-состояния вместо пустых заглушек - aria-live анонсы достижений и выполнения (useAnnounce) - оформленные пустые состояния, клавиатура в меню ExerciseCard Лицензия: проприетарный LICENSE + правка README/CLAUDE.md, счётчик тестов. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -64,7 +64,12 @@ export async function isMeetingActive(): Promise<boolean> {
|
||||
// CSV без заголовков (/NH), скрытое окно.
|
||||
const { stdout } = await execAsync('tasklist /FO CSV /NH', {
|
||||
windowsHide: true,
|
||||
maxBuffer: 4 * 1024 * 1024 // tasklist бывает большой
|
||||
maxBuffer: 4 * 1024 * 1024, // tasklist бывает большой
|
||||
// Если tasklist подвис (повреждённый WMI, загруженная система) — exec
|
||||
// сам прибьёт процесс и уйдёт в catch. Без таймаута зависшие child
|
||||
// накапливались бы при каждом refresh.
|
||||
timeout: 4000,
|
||||
killSignal: 'SIGKILL'
|
||||
})
|
||||
const lower = stdout.toLowerCase()
|
||||
for (const proc of MEETING_PROCESSES) {
|
||||
|
||||
Reference in New Issue
Block a user