[2026-09-26] eagle: personal/plans/balda-mm-pr-plan.md personal/projects/balda/balda-kraken-mm-deploy.md personal/tech/music-tags-repair-truenas.md
This commit is contained in:
1 parent
7564ae26ac
commit
7dbb3871b0
3 files changed
+218
-11
No files matched your search
@@ -7,6 +7,105 @@
|
|||||||
> Со всеми поддерживаемыми фичами и тестами. Вперёд! Без вопросов и требующих апрува команд.»
|
> Со всеми поддерживаемыми фичами и тестами. Вперёд! Без вопросов и требующих апрува команд.»
|
||||||
> Часть [[personal/projects/balda/balda-mm-delegation-plan]] (Фаза 2 → PR в апстрим).
|
> Часть [[personal/projects/balda/balda-mm-delegation-plan]] (Фаза 2 → PR в апстрим).
|
||||||
|
|
||||||
|
## ✅ БОЕВАЯ ПРИЁМКА ПРОЙДЕНА — 2026-09-26 (образ `0.1.10`, коммит `9f1e6c9c`)
|
||||||
|
|
||||||
|
**Сквозной путь работает ОТ АККАУНТА ALEX.** Это первая настоящая приёмка (прошлая была
|
||||||
|
ложной — от `testuser`).
|
||||||
|
|
||||||
|
### Доказательство — лента канала `balda-test`
|
||||||
|
|
||||||
|
```
|
||||||
|
1790413414689 | edxrgupoxiyg5gzmr79tjypbme | слово ← ОТВЕТ БОТА
|
||||||
|
1790413409055 | cbwsorzwoigbtrdnteugnx4aqo | @balda скажи одно слово ← пост ALEX
|
||||||
|
```
|
||||||
|
|
||||||
|
Запрос — `cbwsorzwoigbtrdnteugnx4aqo` (**аккаунт Alex**, `admin`), ответ — бот.
|
||||||
|
В логах: **`settlement_stage=accepted`** (НЕ `unauthorized`!), `assembled provider user content`,
|
||||||
|
`delivery settled`.
|
||||||
|
|
||||||
|
### Состояние привязки владельца — починено
|
||||||
|
|
||||||
|
```
|
||||||
|
balda_user_bindings:
|
||||||
|
channel_type = mattermost
|
||||||
|
principal = cbwsorzwoigbtrdnteugnx4aqo ← БЕЗ префикса ✅ (иначе unauthorized)
|
||||||
|
display_name = mattermost:cbwsorzwoigbtrdnteugnx4aqo ← ОДИНАРНЫЙ префикс ✅ (нет мусора)
|
||||||
|
```
|
||||||
|
|
||||||
|
Прошлый дефект двойного префикса вылечен **в коде** (идемпотентный `MattermostSubject`),
|
||||||
|
в БД мусора нет.
|
||||||
|
|
||||||
|
### WS-здоровье
|
||||||
|
|
||||||
|
| Метрика | Значение |
|
||||||
|
|---|---|
|
||||||
|
| `bad_seq` | **0** ✅ |
|
||||||
|
| `Invalid sequence` | **0** ✅ |
|
||||||
|
| `pong` | **6** (пинг раз в 30 с работает) |
|
||||||
|
| `RestartCount` | **0** ✅ |
|
||||||
|
| Контейнер | `balda-mm:0.1.10` Up стабильно |
|
||||||
|
|
||||||
|
### Старт — чистый
|
||||||
|
|
||||||
|
```
|
||||||
|
mattermost transport configured server_url=http://mattermost:8065 bot_user_id_set=true
|
||||||
|
session manager ready balda_provider=deepseek
|
||||||
|
mattermost websocket connected ws://mattermost:8065/api/v4/websocket
|
||||||
|
Balda bot started.
|
||||||
|
```
|
||||||
|
Никакого crash-loop, `advertised commands have no actor handler` **отсутствует**.
|
||||||
|
|
||||||
|
### ⚠️ Два не-блокера, которые стоит знать
|
||||||
|
|
||||||
|
1. **`warn: getMe response missing result`** при старте. Косметика: startup-лог не смог
|
||||||
|
прочитать identity бота. На работу НЕ влияет — `bot_user_id_set=true` из конфига, ответы
|
||||||
|
идут. Стоит починить отдельно (low priority, в апстриме).
|
||||||
|
2. **`transport_user_id = c6udeze8dfrdxm5jbgq55bd58r` в логах сессии** — это **`testuser`**,
|
||||||
|
id прошлого владельца, зашитый в **persisted-метаданные сессии** `mm-c-7aafea13` (создана
|
||||||
|
в прошлой сессии от testuser). Авторизация при этом прошла верно (по `principal` из
|
||||||
|
bindings), ответ ушёл Alex'у. **Но это грязь:** сессия хранит чужой `user_id`.
|
||||||
|
🔴 Если Alex хочет чистую сессию — `/reset` в канале создаст новую с его `user_id`.
|
||||||
|
На работу не влияет (проверено: ответ пришёл).
|
||||||
|
|
||||||
|
### Деплой — как сделано (воспроизводимо)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. образ из PR-коммита (на Mac)
|
||||||
|
cd ~/Developer/balda
|
||||||
|
docker buildx build --builder arm64builder --platform linux/arm64 \
|
||||||
|
-f Dockerfile.release --build-arg VERSION=v0.3.1-mm-pr8 \
|
||||||
|
--build-arg COMMIT=$(git rev-parse --short HEAD) \
|
||||||
|
--build-arg BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ) \
|
||||||
|
--provenance=false --load -t balda-mm:0.1.10 .
|
||||||
|
|
||||||
|
# 2. перенос (распаковка zstd НА MAC — на хосте zstd 1.5.4 не читает фрейм macOS)
|
||||||
|
docker save balda-mm:0.1.10 -o /tmp/balda-0110.tar
|
||||||
|
zstd -3 -T0 -o /tmp/balda-0110.tar.zst --force /tmp/balda-0110.tar
|
||||||
|
zstd -dc /tmp/balda-0110.tar.zst | ssh kraken 'docker load'
|
||||||
|
|
||||||
|
# 3. переключение с бэкапом compose (скрипт tools/mm-switch-image.sh)
|
||||||
|
ssh kraken "cat > /tmp/mm-switch-image.sh" < tools/mm-switch-image.sh
|
||||||
|
ssh kraken 'bash -n /tmp/mm-switch-image.sh' < /dev/null # SYNTAX_OK
|
||||||
|
ssh kraken 'bash /tmp/mm-switch-image.sh' < /dev/null
|
||||||
|
```
|
||||||
|
|
||||||
|
**Скрипты, созданные для этого деплоя:**
|
||||||
|
| Скрипт | Что делает |
|
||||||
|
|---|---|
|
||||||
|
| `tools/mm-switch-image.sh` | смена тега образа в compose + бэкап + `--force-recreate` |
|
||||||
|
| `tools/mm-whoami.sh` | какой MM-аккаунт у PAT (`/users/me`) — нужен для приёмки от заказчика |
|
||||||
|
|
||||||
|
⚠️ **Проверка CA в образе:** `docker save` даёт **OCI**-формат, где файлы в
|
||||||
|
`blobs/sha256/*`; `tar -tf image.tar | grep ca-certificates` даст **0** (ложный минус).
|
||||||
|
Проверять по слоям: распаковать и искать в `blobs/`, или верить `docker inspect` →
|
||||||
|
`SSL_CERT_FILE` в `Config.Env`.
|
||||||
|
|
||||||
|
⚠️ **Приёмка обязывает иметь PAT заказчика.** `/tmp/admin-tok` = PAT Alex
|
||||||
|
(`cbwsorzwoigbtrdnteugnx4aqo`, `admin`) — сверено через `mm-whoami.sh` **до** постинга,
|
||||||
|
а не на глаз. Без этого тест снова был бы от `testuser` = ложная приёмка.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## ✅ PR ОТКРЫТ — https://github.com/baldaworks/balda/pull/8 (2026-09-26)
|
## ✅ PR ОТКРЫТ — https://github.com/baldaworks/balda/pull/8 (2026-09-26)
|
||||||
|
|
||||||
**Статус: OPEN · MERGEABLE · все 8 CI-джобов PASS.**
|
**Статус: OPEN · MERGEABLE · все 8 CI-джобов PASS.**
|
||||||
|
|||||||
@@ -1,21 +1,104 @@
|
|||||||
# Фаза 3 — Балда на Kraken + Mattermost (деплой)
|
# Фаза 3 — Балда на Kraken + Mattermost (деплой)
|
||||||
|
|
||||||
> Создан 2026-09-26. Обновлён 2026-09-26 (сессия реализации: `bad_seq`, MM-хендлер,
|
> Создан 2026-09-26. Обновлён 2026-09-26 (**✅ ФАЗА ЗАКРЫТА — боевая приёмка пройдена**).
|
||||||
> привязка владельца, правки провайдера; **🔴 статус приёмки ИСПРАВЛЕН**).
|
> Статус: **✅ РАБОТАЕТ. Бот отвечает аккаунту Alex.** Образ `0.1.10` (коммит `9f1e6c9c`,
|
||||||
> Статус: **🔴 ФАЗА 3 НЕ ЗАКРЫТА. Бот отвечает `testuser`, но НЕ отвечает Alex.**
|
> он же PR baldaworks/balda#8).
|
||||||
> Причина — аккаунт Alex не привязан как владелец (`unauthorized`); в `balda_user_bindings`
|
> **Доказательство (лента `balda-test`):** `cbwsorzwoigbtrdnteugnx4aqo` (Alex) —
|
||||||
> владельцем сидит мой тестовый `testuser`. Alex: «Нихуя он мне не отвечает в ММ.
|
> `@balda скажи одно слово` → `edxrgupoxiyig5gzmr79tjypbme` (бот) — `слово`.
|
||||||
> Не готово!!» Образ `0.1.8`, все шесть технических причин устранены — осталась привязка
|
> `settlement_stage=accepted`, `bad_seq`=0, `RestartCount`=0.
|
||||||
> аккаунта Alex (причина №7). Push-уведомления — 🔴 невозможны на Team Edition.
|
> Подробный разбор приёмки — [[personal/plans/balda-mm-pr-plan]] §«БОЕВАЯ ПРИЁМКА».
|
||||||
> Подробный план и фактические изменения — [[personal/plans/balda-mm-endtoend-plan]].
|
> Pull request (Фаза 2 → апстрим): **https://github.com/baldaworks/balda/pull/8** — 8/8 CI PASS.
|
||||||
> Питфоллы и метод — [[personal/tech/balda-go-fx-pitfalls]].
|
> Питфоллы и метод — [[personal/tech/balda-go-fx-pitfalls]].
|
||||||
> Часть проекта [[personal/projects/balda/balda-mm-delegation-plan]].
|
> Часть проекта [[personal/projects/balda/balda-mm-delegation-plan]].
|
||||||
> Предыдущие фазы: [[personal/projects/balda/mattermost-kraken-deploy]] (Фаза 1, ✅),
|
> Предыдущие фазы: [[personal/projects/balda/mattermost-kraken-deploy]] (Фаза 1, ✅),
|
||||||
> [[personal/projects/balda/balda-mattermost-connector]] (Фаза 2, ✅ — код + все quality gates).
|
> [[personal/projects/balda/balda-mattermost-connector]] (Фаза 2, ✅ — код + PR #8).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🔴 СТАТУС: НЕ ГОТОВО — бот не отвечает аккаунту Alex
|
## ✅ ПРИЁМКА ПРОЙДЕНА (2026-09-26, образ `balda-mm:0.1.10`)
|
||||||
|
|
||||||
|
**Сквозной путь проверен ОТ АККАУНТА ALEX — не от тестового.** Прошлая «приёмка» от
|
||||||
|
`testuser` была ложной; эта — настоящая.
|
||||||
|
|
||||||
|
### Лента канала `balda-test` (`7bjw4g7o1jdsbmjbqd649xxgaw`)
|
||||||
|
|
||||||
|
```
|
||||||
|
1790413414689 | edxrgupoxiyig5gzmr79tjypbme | слово ← ОТВЕТ БОТА
|
||||||
|
1790413409055 | cbwsorzwoigbtrdnteugnx4aqo | @balda скажи одно слово ← пост ALEX
|
||||||
|
```
|
||||||
|
|
||||||
|
### Лог обработки — авторизация прошла
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"component":"balda.handlersfx.mattermost","session_id":"mm-c-7aafea13",
|
||||||
|
"settlement_outcome":"accepted","settlement_stage":"accepted","error_class":"none",
|
||||||
|
"message":"conversational ingress settled"}
|
||||||
|
{"message":"assembled provider user content","input_text_char_count":30}
|
||||||
|
```
|
||||||
|
|
||||||
|
**`settlement_stage=accepted`** — не `unauthorized`. Именно этого не хватало всё время.
|
||||||
|
|
||||||
|
### Привязка владельца — чистая
|
||||||
|
|
||||||
|
```
|
||||||
|
channel_type = mattermost
|
||||||
|
principal = cbwsorzwoigbtrdnteugnx4aqo ← БЕЗ префикса (требование GetUserByBinding)
|
||||||
|
display_name = mattermost:cbwsorzwoigbtrdnteugnx4aqo ← ОДИНАРНЫЙ префикс, мусора нет
|
||||||
|
```
|
||||||
|
|
||||||
|
Двойной префикс вылечен **в коде** (идемпотентный `MattermostSubject`), а не в БД — в этом
|
||||||
|
была ошибка прошлого раза.
|
||||||
|
|
||||||
|
### Метрики здоровья
|
||||||
|
|
||||||
|
| Метрика | Значение |
|
||||||
|
|---|---|
|
||||||
|
| `bad_seq` / `Invalid sequence` | **0** ✅ |
|
||||||
|
| `pong` | 6 (пинг работает) |
|
||||||
|
| `RestartCount` | **0** ✅ |
|
||||||
|
| Образ | `balda-mm:0.1.10` (коммит `9f1e6c9c`) |
|
||||||
|
| Старт | `mattermost transport configured` → `websocket connected` → `Balda bot started.` |
|
||||||
|
|
||||||
|
### Как деплоилось
|
||||||
|
|
||||||
|
Сборка на Mac из PR-коммита → `docker save` → zstd (**распаковка на Mac**) → `docker load`
|
||||||
|
на Kraken → `tools/mm-switch-image.sh` (бэкап compose + `--force-recreate`).
|
||||||
|
|
||||||
|
⚠️ Проверка CA в образе: `docker save` даёт OCI-формат, файлы в `blobs/sha256/*` —
|
||||||
|
`tar -tf image.tar | grep ca-certificates` даст **ложный 0**. Смотреть `docker inspect` →
|
||||||
|
`SSL_CERT_FILE` в `Config.Env`, либо распаковывать слои.
|
||||||
|
|
||||||
|
### ⚠️ Известные не-блокеры
|
||||||
|
|
||||||
|
1. **`warn: getMe response missing result`** при старте — косметика startup-лога, на работу
|
||||||
|
не влияет (`bot_user_id_set=true`, ответы идут).
|
||||||
|
2. **Сессия `mm-c-7aafea13` хранит `transport_user_id = c6udeze8dfrdxm5jbgq55bd58r`**
|
||||||
|
(это `testuser` — id прошлого владельца, записан при создании сессии в прошлой сессии).
|
||||||
|
Авторизация идёт по `principal` из bindings и проходит верно, ответ доставляется.
|
||||||
|
Чистая сессия — `/reset` в канале. На работу не влияет (проверено).
|
||||||
|
|
||||||
|
### Инструменты деплоя
|
||||||
|
|
||||||
|
| Скрипт (в `~/Developer/balda/tools/`, git-ignored) | Назначение |
|
||||||
|
|---|---|
|
||||||
|
| `mm-switch-image.sh` | смена тега образа в compose + бэкап + recreate (идемпотентно) |
|
||||||
|
| `mm-whoami.sh` | какой MM-аккаунт у PAT (`/users/me`) — **обязательно перед приёмкой** |
|
||||||
|
| `mm-post-as.sh`, `mm-post-user.sh` | пост от человека (единственный валидный тест ингресса) |
|
||||||
|
| `mm-get-owner-token.sh` | `owner_auth_token` из `state.db` через `strings` |
|
||||||
|
| `mm-fix-owner-principal.sh` | снятие транспортного префикса с `principal` (легаси-фикс) |
|
||||||
|
|
||||||
|
🔴 **Приёмка обязывает сверять аккаунт PAT ДО постинга** (`mm-whoami.sh /tmp/admin-tok` →
|
||||||
|
`cbwsorzwoigbtrdnteugnx4aqo | admin`). Иначе тест уходит от чужого аккаунта = ложная приёмка.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔴 ИСТОРИЧЕСКИЙ РАЗДЕЛ: как искали причину тишины (все закрыто)
|
||||||
|
|
||||||
|
> Ниже — путь диагностики. Все причины устранены, приёмка пройдена (см. выше).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔴 СТАТУС (устаревший): НЕ ГОТОВО — бот не отвечает аккаунту Alex
|
||||||
|
|
||||||
🔴 **Предыдущая запись «ИТОГ: бот работает, приёмка пройдена» была ЛОЖНОЙ.** Сквозной путь
|
🔴 **Предыдущая запись «ИТОГ: бот работает, приёмка пройдена» была ЛОЖНОЙ.** Сквозной путь
|
||||||
проверялся от `testuser` (аккаунт, созданный для тестов), и именно `testuser` оказался
|
проверялся от `testuser` (аккаунт, созданный для тестов), и именно `testuser` оказался
|
||||||
|
|||||||
@@ -151,7 +151,32 @@ Alex: **«Сам проверил весь файл на адекватност
|
|||||||
- ⚠️ **Скрипт диагностики синка** — `check_syncthing2.sh` (в `tools/music-tags/`): версия, статус папки,
|
- ⚠️ **Скрипт диагностики синка** — `check_syncthing2.sh` (в `tools/music-tags/`): версия, статус папки,
|
||||||
connections, completion для телефона. Писать в файл, а не инлайн — иначе `APIKEY=` в heredoc режется.
|
connections, completion для телефона. Писать в файл, а не инлайн — иначе `APIKEY=` в heredoc режется.
|
||||||
|
|
||||||
## 📋 ДОКУМЕНТЫ РЕВЬЮ В VAULT (2026-09-26)
|
### 🔴 ПИТФОЛЛ: права файлов в git-клоне блокируют Syncthing
|
||||||
|
|
||||||
|
После заливки нот Syncthing показал `needFiles: 1`, `needBytes: 89174` — файл **не уходил на телефон**.
|
||||||
|
|
||||||
|
**Причина:** `1-needs-decision.md` имел `noPermissions: true`. Файлы, созданные/обновлённые
|
||||||
|
из контейнера `hermes-taiga` (там **root**), получают `owner=root`, а Syncthing работает под
|
||||||
|
**uid 950** (`truenas_admin`). Каталог был `drwxr-xr-x root:truenas_admin` → Syncthing не мог войти.
|
||||||
|
|
||||||
|
**Эталон (как у всех рабочих файлов):** `truenas_admin:truenas_admin`, `drwxrwx---` (770).
|
||||||
|
|
||||||
|
**Фикс:**
|
||||||
|
```bash
|
||||||
|
docker exec hermes-taiga chown -R 950:950 /obsidian-syncthing/<path>
|
||||||
|
docker exec hermes-taiga chmod -R 770 /obsidian-syncthing/<path>
|
||||||
|
# затем форс-скан
|
||||||
|
docker exec syncthing curl -s -X POST -H "X-API-Key: $K" \
|
||||||
|
"http://localhost:8384/rest/db/scan?folder=k5vyy-gzdgj&sub=<path>"
|
||||||
|
```
|
||||||
|
|
||||||
|
> 🔴 **Проверять ПОСЛЕ каждого синка новых файлов.** `sudo` у `truenas_admin` требует пароль —
|
||||||
|
> chown делать **из контейнера** (`hermes-taiga`), где root.
|
||||||
|
|
||||||
|
**Правило приёмки синка:** `needFiles: 0` + `errors: 0`, а не «Pushed ✓». `Pushed` — это про git,
|
||||||
|
не про Syncthing.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CSV отдан не только файлом, но и **читаемыми нотами в Obsidian** — по просьбе Alex.
|
CSV отдан не только файлом, но и **читаемыми нотами в Obsidian** — по просьбе Alex.
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user