diff --git a/ARTICLE_LINKEDIN.md b/ARTICLE_LINKEDIN.md new file mode 100644 index 0000000..237d5b0 --- /dev/null +++ b/ARTICLE_LINKEDIN.md @@ -0,0 +1,120 @@ +# Скільки насправді часу пішло на Xsistant — трекер активності під Ubuntu + +Пару днів тому закрив невеликий проєкт — **Xsistant**, agent-трекер для Ubuntu/GNOME, який пише активність користувача (клавіатура, миша, фокус вікна) у PostgreSQL і сам же прив'язує її до проєкту. Ділюся чесною хронологією: скільки зайняло не «за календарем», а фактично. + +Репозиторій (публічний): https://github.com/overthelex/aisisstant + +--- + +## Метрика часу: за пушами в master та релізами + +Я працюю trunk-based — комічу одразу в `master`, тому **PR для таймкіпінгу немає**. Зате кожен пуш у `master` тригерить CI і викочує реліз на self-hosted runner. Релізи — найчесніший таймстемп «момент, коли шматок коду реально поїхав у прод». + +Дані з `gh release list` (час EEST): + +📦 16 Apr, 13:29 · v2026.04.16 +Python-агент, колектори, схема БД + +📦 16 Apr, 13:37 · v2026.04.16.1 +CI/CD pipeline + CalVer-версіонування + +📦 16 Apr, 13:43 · v2026.04.16.2 +switchamba fallback для window tracking + +📦 16 Apr, 13:47 · v2026.04.16.3 +AT-SPI + нормалізація заголовків + +📦 16 Apr, 14:26 · v2026.04.16.4 +нормалізація Thunderbird/LibreOffice/VLC/Telegram + +📦 16 Apr, 15:33 · v2026.04.16.5 +GTK4/Adwaita setup wizard + .deb packaging + +📦 17 Apr, 00:24 · v2026.04.17 +Xsistant rebrand, брендинг, логотип + +📦 17 Apr, 11:36 · v2026.04.17.1 +GNOME top-bar indicator + фікс Postgres-hang + +📦 17 Apr, 22:22 · v2026.04.17.2 +project attribution + stats panel + pause/quit + +--- + +## Чесний підрахунок «робочого часу» + +Якщо подивитися на інтервали між релізами і викинути «паузи на поїсти/поспати/зайнятися іншим»: + +- **16 Apr, 13:16 → 15:33** — основний ривок: від порожньої папки до робочого `.deb` з GUI-візардом. **≈ 2 год 15 хв.** +- **17 Apr, 00:24** — брендинг і rename у Xsistant. **≈ 30 хв** (логотип уже був готовий, треба було лише прошити). +- **17 Apr, 11:36** — top-bar індикатор у GNOME Shell + фікс гонки з Postgres при завантаженні системи. **≈ 45 хв.** +- **17 Apr, 22:19** — project attribution через cwd фокусного вікна + stats-панель. **≈ 1 год.** + +**Разом чистого часу: ≈ 4 год 30 хв.** +Календарний строк — півтора дня (33 години від першого коміту до останнього). + +Так, це відчувається швидко. Але все, що нижче — це не диво, а **нудьга**: звичайна декомпозиція + доступні інструменти. + +--- + +## Що увійшло в ці 4.5 години + +### 1. Сам трекер (Ubuntu Linux) + +Python-агент, асинхронний, на `asyncio`. Три колектори: + +- **Клавіатура/миша** — напряму з `/dev/input/event*` через `evdev`. Чесні натискання без прив'язки до конкретного вікна/застосунку. +- **Вікно у фокусі** — два шляхи, за пріоритетом: AT-SPI (через `pydbus`) → fallback на власну маленьку утиліту **switchamba** (теж мій deb-пакет, через `xdotool`/`wmctrl`). +- **Мікрофон** — D-Bus події PulseAudio/PipeWire. + +Агент живе як `systemd --user` service. Встановлюється одним install-скриптом або `.deb`. БД — PostgreSQL у `docker compose`, піднімається автоматично. + +### 2. GitHub Actions (self-hosted runner) + +Workflow з трьох jobs: **test → deploy → release**. + +- Тести (`pytest`) ганяються і на PR, і на push. +- `deploy` — лише на push у `master`: оновлює systemd-юніт, копіює GNOME-розширення, рестартить сервіс і робить health check. +- `release` — **автоматичний CalVer** (`YYYY.MM.DD`, з суфіксом `.N` при кількох релізах на день). На льоту підміняє версії у `pyproject.toml`, `aisisstant-setup`, `debian/changelog`, збирає `.deb` через `dpkg-buildpackage` і публікує GitHub Release з прикріпленим артефактом. + +Чому self-hosted: агенту потрібні `$DBUS_SESSION_BUS_ADDRESS` і живий user-session, щоб дотягнутися до `systemctl --user`. GitHub-hosted runner цього не дасть за визначенням. + +### 3. Коректне перемикання «активність → проєкт» + +Це був найцікавіший шматок (і саме на нього пішла остання година). + +**Проблема:** десять IDE, терміналів і браузерних вкладок у різних проєктів виглядають у заголовку вікна однаково розмито. Парсити title — крихко. + +**Рішення:** коли фокус іде на вікно, колектор знаходить PID власника вікна, читає `/proc//cwd` (і по всіх child-процесах, якщо це термінал із запущеним shell/IDE), порівнює з коренями відомих проєктів і проставляє `project_id` прямо у `activity_scores`. Якщо cwd за межами проєктних директорій — пишеться `null`, не ламаємо звіти шумом. + +Плюс невеликий «дедуп» за заголовками: різні таби одного Firefox не дроблять сесії, VS Code вікна з однаковим workspace-коренем вважаються одним контекстом. + +Підсумок — `aisisstant-report` і stats-панель у top-bar показують чесні хвилини на проєкт, без ручної розмітки. + +--- + +## Що я забираю з цього експерименту + +1. **Trunk-based + CalVer + self-hosted runner** — достатня зв'язка для pet-project під одного користувача. PR-процес тут був би бюрократією без профіту. +2. **GNOME Shell extension + D-Bus** — недооцінений спосіб інтегруватися в desktop без демона на X11-хаках. Індикатор у top-bar написаний за один присід. +3. **`.deb` через `dpkg-buildpackage`** простіше, ніж здається. `debian/` з 10 файлів + один `rules` на 3 рядки — і у тебе нативний пакет, який ставиться через `apt install ./file.deb` разом із залежностями. +4. **«cwd фокусного процесу»** — найнадійніший сигнал належності до проєкту на Linux. Набагато точніше, ніж title-парсинг, і працює для будь-якого IDE. + +--- + +## Що далі: інтеграція з Plane + +Наступний крок — **автоматична прив'язка активності до задач у Plane**. Ідея проста: розробник не має сидіти із секундоміром і згадувати в кінці дня, скільки пішло на тикет. Це одна з найдратівливіших частин тайм-трекінгу в будь-якій команді. + +Як це працюватиме: + +- Xsistant уже знає, у якому **проєкті** ти зараз працюєш (через cwd фокусного вікна). +- Наступний шар — прив'язка до **активної задачі**: або через вибір у top-bar індикаторі, або автоматично — за іменем гілки (`feature/PROJ-123-...` → тикет `PROJ-123`), або за заголовком вікна IDE з номером задачі. +- Агент агрегує хвилини активної роботи (клавіатура/миша/фокус вікна проєкту) і **сам пише worklog у Plane** через їхній API. +- Розробник нічого не заповнює вручну. У кінці спринта — чесні цифри, без «ну накину години зо три, начебто стільки було». + +Мета — прибрати психологічний тягар тайм-трекінгу. Трекер уже збирає всі потрібні сигнали; залишилося замкнути петлю на таск-трекер. + +--- + +**TL;DR:** від `git init` до робочого `.deb` з CI, GNOME-індикатором і project attribution — **~4.5 години чистого часу** за півтора дня календаря. Далі — інтеграція з Plane, щоб розробники не заповнювали worklog руками. Код: https://github.com/overthelex/aisisstant