434 lines
25 KiB
Markdown
434 lines
25 KiB
Markdown
# Balda — Mattermost connector: PR-подготовка (закрыто)
|
||
|
||
> Создан 2026-09-26. Обновлён 2026-09-26 (PR открыт).
|
||
> Статус: **✅ PR ОТКРЫТ — baldaworks/balda#8, 8/8 CI PASS, MERGEABLE.**
|
||
> https://github.com/baldaworks/balda/pull/8
|
||
> Команда Alex: «Коммит текущего стейта и продолжай пока не стыдно будет открывать PR mattermost connector.
|
||
> Со всеми поддерживаемыми фичами и тестами. Вперёд! Без вопросов и требующих апрува команд.»
|
||
> Часть [[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)
|
||
|
||
**Статус: OPEN · MERGEABLE · все 8 CI-джобов PASS.**
|
||
|
||
| | |
|
||
|---|---|
|
||
| PR | **baldaworks/balda#8** |
|
||
| База | `baldaworks/balda:main` |
|
||
| Голова | `mallexxx:feat/mattermost-channel` |
|
||
| Объём | **41 файл, +5622 / −18** |
|
||
| Коммитов | 7 |
|
||
| Mergeable | ✅ MERGEABLE |
|
||
|
||
### 🔴 Целевой репозиторий — `baldaworks/balda`, не `normahq/balda`
|
||
|
||
Проверено через API, а не по названию remote'а:
|
||
```
|
||
gh repo view mallexxx/balda --json parent
|
||
→ parent: baldaworks/balda ← форк от него
|
||
gh repo view normahq/balda --json owner
|
||
→ owner.id: O_kgDOEgAHrw (= baldaworks) ← редирект, не отдельный репо
|
||
```
|
||
`origin` = `mallexxx/balda` (форк), `upstream` = `normahq/balda` (редирект на baldaworks).
|
||
**PR создавать в `baldaworks/balda`**, head указывать как `mallexxx:<branch>`
|
||
(не полный URL форка — иначе `gh` путается).
|
||
|
||
### База ветки — идеальная
|
||
|
||
`git rev-list --left-right --count upstream/main...HEAD` → `0 7` (0 позади, 7 впереди).
|
||
`merge-base HEAD upstream/main` == `upstream/main` == `de273d8f`. Rebase не потребовался.
|
||
|
||
### CI — 8/8 PASS (прогон на чистом раннере)
|
||
|
||
```
|
||
architecture-lint pass 2m2s
|
||
ingress-e2e pass 30s
|
||
jetstream-integration pass 1m0s
|
||
lint pass 2m46s
|
||
postgres-integration pass 57s
|
||
projection-replay pass 26s
|
||
sqlite-integration pass 1m15s
|
||
test pass 6m0s ← главный: полный go test на чистом раннере
|
||
```
|
||
|
||
📌 **Это и есть настоящая приёмка сборки.** Локально `cmd/balda` падал на
|
||
`TestInitCommand_NonInteractiveAutoSelectsRootAndGeneratesDetectedAgents` — в CI он
|
||
**прошёл**, то есть падение было особенностью моей локальной среды, а не дефектом.
|
||
CI на чистом раннере закрывает ровно тот класс проблем, который локальные гейты не видят.
|
||
|
||
⚠️ **CI-пайплайн в репо ЕСТЬ** (`architecture-lint`, `lint`, `test`, `ingress-e2e`,
|
||
`jetstream-integration`, `postgres-integration`, `sqlite-integration`, `projection-replay`).
|
||
Значит локальные гейты — необходимое, но не достаточное условие; ждать CI обязательно.
|
||
|
||
### Команды (воспроизводимо)
|
||
|
||
```bash
|
||
cd ~/Developer/balda
|
||
git fetch upstream --quiet
|
||
git rev-list --left-right --count upstream/main...HEAD # 0 7
|
||
git push -u origin feat/mattermost-channel
|
||
|
||
gh pr create --repo baldaworks/balda --base main \
|
||
--head mallexxx:feat/mattermost-channel \
|
||
--title "feat(mattermost): add Mattermost channel transport" \
|
||
--body-file /tmp/mm-pr-body.md
|
||
|
||
gh pr view 8 --repo baldaworks/balda --json state,mergeable,changedFiles,additions
|
||
gh pr checks 8 --repo baldaworks/balda
|
||
```
|
||
|
||
### Что осталось
|
||
|
||
1. **Ревью апстрима** — ждать. Правки по замечаниям делать в этой же ветке (push обновит PR).
|
||
2. **Боевая проверка на Kraken** — PR-merge ≠ работает на стенде. Пересобрать образ из
|
||
`9f1e6c9c`, задеплоить, `@balda` → ответ в ленте канала (см.
|
||
[[personal/projects/balda/balda-kraken-mm-deploy]]).
|
||
3. Фаза 4 (исполнитель) — [[personal/projects/balda/balda-mm-delegation-plan]].
|
||
|
||
---
|
||
|
||
## ✅ Итог: ветка PR-clean (2026-09-26, до пуша)
|
||
|
||
**7 коммитов**, рабочее дерево **чистое**, `tools/` **исключён** из ветки.
|
||
|
||
```
|
||
9f1e6c9c chore: ignore local project-editing tooling
|
||
58f27120 docs(mattermost): document the transport setup and behavior
|
||
80d4f41d test(mattermost): cover the transport, the ingress and the handler
|
||
c7f18654 fix(mattermost): send a monotonic seq on every client frame
|
||
6dc3077a feat(mattermost): add the inbound handler and wire it into DI
|
||
fa1a2855 feat(auth): support the Mattermost channel subject
|
||
004fda2f feat(mattermost): add Mattermost transport adapter ← база прошлой сессии
|
||
```
|
||
|
||
### 🔴 Уборка `tools/` — важный урок про PR
|
||
|
||
База `004fda2f` (прошлая сессия, **не мои 5 коммитов**) затащила в ветку **16 файлов
|
||
`tools/`**: `apply-project-deltas.py`, `run-project-deltas.sh`, `deltas-mattermost*.json`,
|
||
`.deltas-state.json`. **В апстриме каталога `tools/` нет вообще** — проверено
|
||
`git ls-tree upstream/main tools/` → пусто.
|
||
|
||
**Как найдено:** `git diff --stat upstream/main...HEAD` показал `tools/` в списке файлов PR.
|
||
|
||
**Фикс (коммит `9f1e6c9c`):**
|
||
1. `/tools/` добавлен в `.gitignore`;
|
||
2. `git rm -r --cached tools/` — файлы **остались на диске** (39 файлов), ушли только из git.
|
||
|
||
⚠️ **`gitignore` НЕ отвязывает уже отслеживаемые файлы** — нужен именно `git rm --cached`.
|
||
⚠️ **Проверять состав PR через `git diff upstream/main...HEAD`, а не по своим коммитам.**
|
||
Свои 5 коммитов были чистыми (`git log upstream..HEAD -- tools/` → пусто), но ветка в
|
||
целом — нет, из-за базового коммита.
|
||
|
||
**Результат:** в PR-diff **41 файл**, все — файлы проекта, ни одного `tools/`.
|
||
|
||
### Финальные гейты — все зелёные на закоммиченном дереве
|
||
|
||
```
|
||
go build ./... → exit 0
|
||
go vet ./... → exit 0
|
||
go tool golangci-lint run → 0 issues
|
||
go tool go-arch-lint check --project-path . → OK - No warnings found
|
||
go test -race (затронутые пакеты) → все ok
|
||
тесты mattermost + handlersfx (verbose) → 126 PASS, 0 FAIL, 0 SKIP
|
||
```
|
||
|
||
**Тестов добавлено:** **103** (`grep -c '^func Test'`), по файлам:
|
||
|
||
| Файл | Тестов |
|
||
|---|---|
|
||
| `channel/mattermost/ingress_test.go` | 23 |
|
||
| `channel/mattermost/inbound_test.go` | 18 |
|
||
| `channel/mattermost/adapter_test.go` | 17 |
|
||
| `handlersfx/mattermost_ingress_test.go` | 17 |
|
||
| `channel/mattermost/locator_codec_test.go` | 15 |
|
||
| `channel/mattermost/client_test.go` | 13 |
|
||
|
||
### Предсуществующие падения — НЕ наши (проверено `git stash`)
|
||
|
||
5 пакетов: `cmd/balda`, `apps/balda`, `mcpruntime`, `session`, `state`. Те же 4 теста
|
||
падают **без** моих правок:
|
||
`TestInitCommand_NonInteractiveAutoSelectsRootAndGeneratesDetectedAgents`,
|
||
`TestCanonicalSessionMemoryRuntimeComposesPortableCapabilities`,
|
||
`TestCanonicalSessionMemoryRuntimeMigratesAndReopensGroupedStore`,
|
||
`TestResolveWorkspaceBaseBranch_ConfigPreferredWhenValid`.
|
||
|
||
### Лишнее, что я НЕ отправляю в PR
|
||
|
||
`tools/mm-*.sh` (9 ops-скриптов), `tools/deltas-*.json` (16 файлов дельта-групп),
|
||
`tools/apply-project-deltas.py`, `tools/run-project-deltas.sh`, `tools/.deltas-state.json`
|
||
— локальный инструментарий, остаётся на диске, в git не идёт.
|
||
|
||
### Осталось (по желанию Alex)
|
||
|
||
1. `git push -u origin feat/mattermost-channel` → открыть PR в `baldaworks/balda`.
|
||
2. Фаза 3/4 — [[personal/projects/balda/balda-kraken-mm-deploy]].
|
||
|
||
---
|
||
|
||
## Итог (промежуточный, до уборки tools/)
|
||
|
||
Ветка `feat/mattermost-channel`, **6 коммитов** (базовый `004fda2f` + 5 новых). Готово к `git push` и PR.
|
||
|
||
```
|
||
58f27120 docs(mattermost): document the transport setup and behavior
|
||
80d4f41d test(mattermost): cover the transport, the ingress and the handler
|
||
c7f18654 fix(mattermost): send a monotonic seq on every client frame
|
||
6dc3077a feat(mattermost): add the inbound handler and wire it into DI
|
||
fa1a2855 feat(auth): support the Mattermost channel subject
|
||
004fda2f feat(mattermost): add Mattermost transport adapter ← база
|
||
```
|
||
|
||
## Quality gates — все зелёные (проверено на закоммиченном дереве)
|
||
|
||
```
|
||
go build ./... → exit 0
|
||
go vet ./... → exit 0
|
||
go tool golangci-lint run → 0 issues
|
||
go tool go-arch-lint check --project-path . → OK - No warnings found
|
||
go test -race ./channel/mattermost/ ./handlersfx/ ./auth/ ./deliveryfmt/
|
||
./actors/command/... → все ok, включая start и auth
|
||
```
|
||
|
||
## Что сделано в этом проходе
|
||
|
||
### 1. Дефект двойного префикса — починен В КОДЕ, а не в БД (главное)
|
||
|
||
Прошлый фикс был прямым `UPDATE` в `state.db`, поэтому дефект вернулся.
|
||
Теперь источник закрыт:
|
||
|
||
- `auth.MattermostSubject()` **идемпотентен** — срезает уже имеющийся префикс
|
||
`mattermost:` перед повторной квалификацией;
|
||
- из `actors/command/start/handler.go` убран локальный `TrimPrefix`-костыль,
|
||
ветка стала как у остальных транспортов: `auth.MattermostSubject(trimmed)`.
|
||
|
||
Почему это ломало прод: `canonicalSubject` режет subject по **первому** `:`, а
|
||
`GetUserByBinding` сравнивает **точно**. Значение `mattermost:mattermost:<id>`
|
||
в `principal` не совпадает ни с чем → каждый пост Alex отбивался
|
||
`settlement_stage=unauthorized`.
|
||
**Тест-регрессия:** `TestMattermostSubjectIsIdempotent`
|
||
(`handlersfx/mattermost_ingress_test.go`) + `TestMattermostHandlerSendsChannelQualifiedPrincipalExactlyOnce`.
|
||
|
||
### 2. Исправлено противоречие `ProgressPolicy.Typing`
|
||
|
||
Command-путь ставил `Typing: true`, тогда как inbound-путь — `false`, а
|
||
`SendTyping` у MM-адаптера **осознанный no-op** (у ботов MM нет typing API).
|
||
Мёртвая ветка + warn-шум на каждом ходу. Приведено к `false`.
|
||
|
||
### 3. Тесты транспорта — 6 новых файлов (~90 тестов)
|
||
|
||
| Файл | Покрытие |
|
||
|---|---|
|
||
| `channel/mattermost/locator_codec_test.go` | локаторы, **thread↔channel изоляция**, `LocatorFromAddressKey`, scope, UserID |
|
||
| `channel/mattermost/inbound_test.go` | `NormalizeInbound`, mention-фильтр, `ParseCommand`, whitelist команд, `PostIDFromWebSocket` |
|
||
| `channel/mattermost/adapter_test.go` | все `deliverycmd.Operation`, **plain-fallback только на content-rejection**, draft-as-post, typing no-op без сети, `root_id` в треде |
|
||
| `channel/mattermost/client_test.go` | ws/wss derivation, `Bearer`, `APIError`, `isContentRejectedError`, контекст |
|
||
| `channel/mattermost/ingress_test.go` | 🔴 **`bad_seq`-регрессия**, монотонность и уникальность `seq` под 16 горутинами, фильтры, panic-recovery, семафор |
|
||
| `handlersfx/mattermost_ingress_test.go` | публикация всех команд, **одиночный** префикс principal, `/start` до авторизации, отказ чужим, nil-safety |
|
||
|
||
### 4. Доки — `README.md`, `docs/balda.md`, новый `docs/mattermost.md`
|
||
|
||
`docs/mattermost.md` — полный гайд: создание бота, минтинг токена (отдаётся
|
||
ОДИН раз), membership в команде/канале, 5 ключей конфига, поведение в
|
||
DM/канале/треде, troubleshooting (`bad_seq`, `unauthorized`, `x509`).
|
||
|
||
## Уроки метода (дополнить `balda-go-fx-pitfalls`)
|
||
|
||
1. **Тест-ассерт — это гипотеза, а не истина.** Дважды падал тест, и оба раза
|
||
неверным был ассерт, а не код: (а) «тред и корневой пост = одна сессия» —
|
||
на самом деле тред **отдельная** сессия от канала (проверено пробником:
|
||
`mm-c-a4aa02ef` vs `mm-t-89bbf64f`, два разных ответа в треде дают ОДНУ
|
||
сессию); (b) «`NewIngress` фолбэчит `botUserID` из клиента» — на самом деле
|
||
`onStart` **отказывается стартовать** без `bot_user_id`. Прежде чем править
|
||
код под падающий тест — проверить, чему код **обязан** соответствовать.
|
||
2. **`goconst` в тестах** — повторяющиеся строковые литералы (`"channel-1"` ×15)
|
||
валят линтер. Заводить константы (`testChannelID` и т.п.) сразу.
|
||
3. **`dupword`** — сообщение `"thread channel = %q, channel channel = %q"`
|
||
поймано линтером как повтор слова. Формулировать иначе.
|
||
4. **`write_file` + `***` в доке** — плейсхолдеры вида `BALDA_MATTERMOST_TOKEN=***`
|
||
в примерах конфига остаются на диске **целыми**; искажается только вывод
|
||
чтения. Проверять `awk 'NR==N'`, не глазами (см. `hermes-secret-redaction-bypass`).
|
||
5. **Артефакты деплоя — вон из PR.** `tools/mm-*.sh` (9 скриптов) и
|
||
`tools/deltas-*.json` (15 файлов) оставлены **незакоммиченными**: это
|
||
ops-инструменты и метод правок, в апстрим-репозиторий им не место.
|
||
|
||
## 🔴 Открытое решение: `tools/` закоммичены в ветку (выявлено в конце сессии)
|
||
|
||
**Найдено проверкой `git diff --stat upstream/main...HEAD`:** в диапазоне PR — 56 файлов,
|
||
и среди них **16 файлов `tools/`**, которых в апстриме **нет вообще**
|
||
(`git ls-tree upstream/main tools/` → пусто).
|
||
|
||
Кто занёс: **базовый коммит `004fda2f`** (из прошлой сессии, не из этого прохода).
|
||
Мои 5 новых коммитов чисты — проверено:
|
||
|
||
```bash
|
||
git log --oneline --name-only fa1a2855^..HEAD -- 'tools/' # → пусто
|
||
```
|
||
|
||
Что именно закоммичено в `004fda2f` (лишнее для PR):
|
||
|
||
```
|
||
tools/.deltas-state.json
|
||
tools/apply-project-deltas.py
|
||
tools/run-project-deltas.sh
|
||
tools/deltas-mattermost.json
|
||
tools/deltas-mattermost-2.json … -13.json (12 файлов)
|
||
```
|
||
|
||
**✅ РЕШЕНО (2026-09-26):** выбран вариант (a), выполнен по команде Alex «Добавь в ignored».
|
||
Коммит `9f1e6c9c chore: ignore local project-editing tooling`.
|
||
|
||
```bash
|
||
echo '/tools/' >> .gitignore # + комментарий, что это локальный инструментарий
|
||
git rm -r --cached tools/ # 16 файлов ушли из индекса, ОСТАЛИСЬ на диске
|
||
git add .gitignore && git commit # → 9f1e6c9c
|
||
```
|
||
|
||
Результат: `git diff --stat upstream/main...HEAD -- tools/` → **пусто**;
|
||
в PR-diff **41 файл**, все — файлы проекта. `tools/` на диске цел (**39 файлов**),
|
||
`git status --short` чист.
|
||
|
||
⚠️ **`git rm -r --cached tools/` уходит на апрув** (рекурсивное удаление). Первая попытка
|
||
истекла по таймауту и **не применилась** — состояние было целое. Проверять
|
||
`git diff --cached --name-only` перед повтором.
|
||
🔴 **`gitignore` НЕ отвязывает уже отслеживаемые файлы** — без `git rm --cached` они
|
||
останутся в PR навсегда. Нужны оба шага, в этом порядке.
|
||
|
||
📌 **Правило на будущее:** проверять состав PR через
|
||
`git diff --stat upstream/main...HEAD` **перед** объявлением готовности, а не только
|
||
`git status` (последний показывает рабочее дерево, не содержимое коммитов). Иначе
|
||
мусор из прошлой сессии всплывает последним.
|
||
|
||
## Что осталось
|
||
|
||
**По PR — ничего, кроме ревью.** Всё выполнено:
|
||
|
||
| Шаг | Статус |
|
||
|---|---|
|
||
| `tools/` убран из ветки, `/tools/` в `.gitignore` | ✅ коммит `9f1e6c9c` |
|
||
| `git push -u origin feat/mattermost-channel` | ✅ запушено |
|
||
| PR в `baldaworks/balda` открыт | ✅ **#8**, 41 файл, +5622/−18 |
|
||
| CI | ✅ **8/8 PASS** |
|
||
| Локальные гейты (build/vet/lint/arch-lint/no-race) | ✅ все зелёные |
|
||
|
||
**Осталось (по желанию Alex):**
|
||
|
||
1. **Ревью апстрима** — ждать. Правки по замечаниям делать **в эту же ветку**:
|
||
push обновит PR автоматически.
|
||
2. 🔴 **Боевая проверка на Kraken — НЕ сделана.** PR-merge ≠ «бот работает на стенде».
|
||
Нужно: пересобрать образ из `9f1e6c9c`, задеплоить, `@balda` → ответ в ленте канала.
|
||
См. [[personal/projects/balda/balda-kraken-mm-deploy]].
|
||
3. **Замержить PR** (после ревью) — тогда Фаза 2 закрывается официально.
|
||
|
||
⚠️ Скрипты `tools/mm-*.sh` (9 шт.), дельты `tools/deltas-mattermost-14…26` +
|
||
`deltas-goal-command-fix.json` + `deltas-mm-prefixfix.json`, `apply-project-deltas.py`,
|
||
`run-project-deltas.sh`, `.deltas-state.json` — **untracked, локальный инструментарий**,
|
||
git-ignored. Существенное продублировано в
|
||
[[personal/projects/balda/balda-kraken-mm-deploy]] и [[personal/tech/balda-go-fx-pitfalls]].
|
||
|
||
## Связанные заметки
|
||
|
||
- [[personal/projects/balda/balda-mattermost-connector]] — Фаза 2 (код коннектора)
|
||
- [[personal/projects/balda/balda-kraken-mm-deploy]] — Фаза 3 (деплой, боевые причины тишины)
|
||
- [[personal/tech/balda-go-fx-pitfalls]] — fx-питфоллы + дельта-апплаер
|
||
- [[personal/plans/balda-mm-endtoend-plan]] — сквозной путь
|
||
- [[personal/tech/hermes-secret-redaction-bypass]] — редакция секретов
|