[2026-09-28] eagle: personal/plans/balda-runtime-rebuild-mm-validation.md personal/plans/runtime-pr5-toolset-dedup-review-fixes.md personal/projects/balda/balda-kraken-mm-deploy.md
This commit is contained in:
1 parent
1480fa8d95
commit
bf7787bcbd
3 files changed
+187
-28
No files matched your search
@@ -1,10 +1,25 @@
|
||||
> Создан 2026-09-28. Статус: **✅ ЧАСТЬ A (runtime) И ЧАСТЬ C/D (сборка+деплой+валидация) ВЫПОЛНЕНЫ.**
|
||||
> Создан 2026-09-28. Статус: **✅ ЧАСТЬ A (runtime) · C/D (сборка+деплой+валидация) · E (sync с апстримом) ВЫПОЛНЕНЫ.**
|
||||
> Часть B (3 блокера PR #8) — **НЕ НАЧАТА**.
|
||||
> Цель: собрать локально runtime (PR4+PR5 влиты) + balda (ревью PR #8), задеплоить на Kraken,
|
||||
> прогнать проверку тулинга и Mattermost.
|
||||
> Связано: [[personal/projects/balda/balda-kraken-mm-deploy]], [[personal/plans/balda-mm-pr8-review-fixes]],
|
||||
> [[personal/plans/runtime-pr5-toolset-dedup-review-fixes]].
|
||||
|
||||
### 🔴 Состояние git на конец сессии (читать первым)
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| HEAD | **`6f5695c7`** — `Merge remote-tracking branch 'upstream/main' into feat/mattermost-channel` |
|
||||
| Ветка | `feat/mattermost-channel` |
|
||||
| behind `upstream/main` | **0** (впереди на 18) |
|
||||
| `upstream` | `https://github.com/baldaworks/balda.git` (заменён с `normahq/balda`) |
|
||||
| runtime pin | **`v2.1.0`**, директивы `replace` нет |
|
||||
| Незакоммичено | **5 файлов** (см. §7.1) + `?? personal/` (мусор) |
|
||||
|
||||
⚠️ **ВАЖНО:** задеплоенный на Kraken образ **`0.1.14` собран из дерева ДО merge `6f5695c7`**.
|
||||
Merge добавил апстримные коммиты (backoffice-фичи), т.е. **текущее дерево ≠ собранному образу**.
|
||||
Перед следующим релизом — пересобрать.
|
||||
|
||||
---
|
||||
|
||||
## 0а. ✅ РЕЗУЛЬТАТ — что сделано в этой сессии
|
||||
@@ -103,7 +118,7 @@ rejected by transport: sending "tools/call": Internal Server Error
|
||||
## 0б. ✅ Замена `upstream` на baldaworks
|
||||
|
||||
`git remote set-url upstream https://github.com/baldaworks/balda.git`.
|
||||
Было `https://github.com/normahq/balda.git`.
|
||||
Было `https://github.com/normahq/balda.git`. Fetch прошёл: `upstream/main` = `c1fde3c4`.
|
||||
|
||||
📌 **Разъяснение путаницы (проверено фактами):**
|
||||
- `normahq/balda` и `baldaworks/balda` отдают **идентичный** `main` = `c1fde3c4` → это один
|
||||
@@ -113,13 +128,16 @@ rejected by transport: sending "tools/call": Internal Server Error
|
||||
PR идёт из форка.
|
||||
- PR #8: head `mallexxx/balda:feat/mattermost-channel` @ `e0162009` → base `baldaworks/balda:main`.
|
||||
- 🔴 **PR создаётся через gh API, git-ремоут на базовый репо для этого НЕ нужен.**
|
||||
Отсюда и путаница «как открыт PR, если ремоута нет».
|
||||
Отсюда и путаница «как открыт PR, если ремоута нет». Аккаунт `mallexxx` (тот же, под которым
|
||||
работает `gh auth`) имеет доступ к `baldaworks/balda`; `gh pr create --repo baldaworks/balda
|
||||
--head mallexxx:feat/mattermost-channel` сравнивает ветку форка с базой апстрима **по API**.
|
||||
Ремоут `upstream` нужен только для `fetch`/синхронизации, а не для открытия PR.
|
||||
|
||||
⚠️ После fetch: `upstream/main` продвинулся `de273d8f..c1fde3c4` (плюс forced update
|
||||
служебной ветки `__dolt_remote_info__`). База PR #8 = `de273d8f` **отстаёт** от текущего main —
|
||||
**PR #8 нужно синхронизировать перед мержем.**
|
||||
служебной ветки `__dolt_remote_info__`). База PR #8 = `de273d8f` **отставала** от текущего main —
|
||||
✅ **устранено** merge'ом `6f5695c7` (§1б), осталось запушить.
|
||||
|
||||
Бэкап конфига: `/tmp/balda-git-config.bak-20260928` (md5 `69fdc0de503640002dba06ac49741c24`).
|
||||
Конфиг-бэкап: `/tmp/balda-git-config.bak-20260928` (md5 `69fdc0de503640002dba06ac49741c24`).
|
||||
|
||||
---
|
||||
|
||||
@@ -156,7 +174,9 @@ jq -r '.posts as $p | .order[] | $p[.] | "\(.create_at) | \(.user_id[0:10]) | \(
|
||||
| runtime tag **`v2.1.0`** | = `c41939f` = `upstream/main`; содержит `DedupKey` (**6**) и `openAIToolsFromConfig` (**2**) |
|
||||
| maint-фиксы в `v2.1.0` | `hydrateMCPServerConfig` несёт `DedupKey`/`DedupPreferred` (без этого дедуп был бы мёртв в проде) |
|
||||
| `baldaworks/balda` PR #8 | **OPEN**, head `e0162009`, review **CHANGES_REQUESTED** (2026-09-28T13:54Z) |
|
||||
| Локальный `~/Developer/balda` | **`e0162009`** — совпадает с головой PR #8 (был `06b2b8d0`, отстал на 4) |
|
||||
| Локальный `~/Developer/balda` | **`6f5695c7`** (merge upstream/main); before merge был `e0162009` |
|
||||
| `upstream/main` (balda) | **`c1fde3c4`** — содержит backoffice-фичи (`docs(backoffice): document UI review workflow`) |
|
||||
| `upstream/main` (balda) runtime pin | ⚠️ всё ещё **`v2.0.11`**, тег `2.1.0` НЕ заменён (см. §1б) |
|
||||
|
||||
---
|
||||
|
||||
@@ -174,6 +194,46 @@ session-memory **fail closed**. Лексикографически меньши
|
||||
|
||||
---
|
||||
|
||||
## 1б. Часть E: подтягивание локала к апстриму ✅ ВЫПОЛНЕНО
|
||||
|
||||
Задача Alex: *«подтяни локал к апстриму. вероятно там уже заменен тег 2.1.0»*.
|
||||
|
||||
**Гипотеза про тег НЕ подтвердилась — проверено фактом:**
|
||||
`git show upstream/main:go.mod` → `github.com/normahq/runtime/v2 v2.0.11`.
|
||||
Тег `2.1.0` в апстриме **не заменён**, директивы `replace` там нет.
|
||||
📌 Вывод: наш bump до `v2.1.0` — **наше локальное опережение**, а не подтягивание за апстримом.
|
||||
Его надо будет протолкнуть в апстрим отдельно (иначе при следующем sync go.mod снова откатится
|
||||
на `v2.0.11` — merge его сохранит только потому, что правка неконфликтная).
|
||||
|
||||
**Merge:** `git merge upstream/main` → `de273d8f..c1fde3c4`.
|
||||
**Один конфликт:** `cmd/balda/init_test.go`.
|
||||
- **наша ветка (HEAD)** добавила `filepath.EvalSymlinks` для пути к `.env`
|
||||
(устойчивость к symlink-нутой working dir);
|
||||
- **upstream/main** добавил ассерты bootstrap администратора
|
||||
(`Backoffice password: …`, `NewSQLiteProvider`, `ListUsers`, `GetCredentialSecret` + `userpassword.Verify`)
|
||||
и вернул путь **без** symlink-разрешения.
|
||||
|
||||
**Разрешено объединением:** все upstream-ассерты + наш `tokenPath` через `EvalSymlinks`,
|
||||
финальная проверка `strings.Contains(out, "telegram token stored in: "+tokenPath)`.
|
||||
Коммит **`6f5695c7`** (merge). Целевой тест проходит:
|
||||
`TestInitCommand_NonInteractiveAutoSelectsRootAndGeneratesDetectedAgents` → **PASS**.
|
||||
|
||||
📌 **Урок merge-конфликта с апстримом:** апстрим переписал тот же участок, что и мы, но по другой
|
||||
причине. Нельзя брать «их вариант целиком» — потеряем свою правку; нельзя «наш целиком» —
|
||||
потеряем новую функциональность апстрима. Читать оба блока и **объединять по смыслу**.
|
||||
|
||||
**Гейты на смерженном дереве (HEAD `6f5695c7`):**
|
||||
```
|
||||
go build ./... → OK
|
||||
go vet ./... → OK
|
||||
go test -race ./... → 107 пакетов ok, 0 фейлов
|
||||
go tool golangci-lint run → 0 issues
|
||||
go tool go-arch-lint check --project-path . → OK - No warnings found
|
||||
```
|
||||
`go mod tidy` сохранил `v2.1.0` (апстрим не переопределил).
|
||||
|
||||
---
|
||||
|
||||
## 2. План — Часть B: 3 блокера PR #8 ⏳ НЕ НАЧАТО
|
||||
|
||||
Последнее ревью (13:54) подтверждает: canonical chat ingress, command registry, scope
|
||||
@@ -325,14 +385,29 @@ reboot**. Источники в `~/Developer/balda/tools/` (созданы за
|
||||
|
||||
## 7. ⏭️ Что делать дальше (приоритет)
|
||||
|
||||
1. 🔴 **Закоммитить незакоммиченные правки** в `~/Developer/balda` — образ `0.1.14` собран из них.
|
||||
Файлы: `go.mod`, `go.sum`, `Dockerfile.release`, `internalmcp/manager.go`,
|
||||
`sessionapp/module.go`, `sessionmemorymcp/broker.go`.
|
||||
1. 🔴 **Закоммитить 5 незакоммиченных файлов** в `~/Developer/balda` — образ `0.1.14` собран из них:
|
||||
```
|
||||
M go.mod ← runtime v2.0.11 → v2.1.0, убран replace на ./runtime-local
|
||||
M go.sum ← следствие go mod tidy; gorilla/websocket стал прямым
|
||||
M internal/apps/balda/internalmcp/manager.go ← DedupKey у bundled-записи
|
||||
M internal/apps/balda/sessionapp/module.go ← DedupKey + DedupPreferred
|
||||
M internal/apps/balda/sessionmemorymcp/broker.go ← константа BundledDedupKey
|
||||
```
|
||||
⚠️ `Dockerfile.release` **уже НЕ в списке** — правка (удаление `COPY runtime-local/`) совпала
|
||||
с HEAD после merge; ссылок на `runtime-local` нет и в HEAD.
|
||||
2. **Часть B** — 3 блокера PR #8 (`ingress.go:389`, `:483`, `:164`).
|
||||
3. **Синхронизировать PR #8** с `upstream/main` (`c1fde3c4`): база PR = `de273d8f`, отстала.
|
||||
4. **Починить bridge `balda-executor-mcp`** — HTTP 000 + JSONDecodeError (отдельная инфра).
|
||||
5. Прогнать сценарии D2-b / D2-c (после части B) — они и есть приёмка надёжности WS.
|
||||
6. ⚠️ Убрать мусор `~/Developer/balda/personal/` (создан ошибочным `write_file`).
|
||||
3. **Протолкнуть bump `v2.1.0` в апстрим** — сейчас в `upstream/main` всё ещё `v2.0.11`
|
||||
(см. §1б). Иначе при следующем sync go.mod откатится.
|
||||
4. **Синхронизировать PR #8** с `upstream/main` (`c1fde3c4`) — сделано merge `6f5695c7`
|
||||
локально; **запушить в `origin`** (`mallexxx/balda`), чтобы PR подхватил.
|
||||
⚠️ База PR = `de273d8f`, отставала от main.
|
||||
5. **Пересобрать образ** после merge — `0.1.14` собран из pre-merge дерева; следующий `0.1.15`.
|
||||
6. **Починить bridge `balda-executor-mcp`** — HTTP 000 + JSONDecodeError (отдельная инфра).
|
||||
7. Прогнать сценарии D2-b / D2-c (после части B) — они и есть приёмка надёжности WS.
|
||||
8. ⚠️ Убрать мусор `~/Developer/balda/personal/` (создан ошибочным `write_file`).
|
||||
9. ⚠️ Временное в `/tmp` (не переживёт reboot): `runtime-local-removed-20260928`,
|
||||
`runtime-local-bak-20260928`, `balda-git-config.bak-20260928`, `mergemsg.txt`,
|
||||
`balda-test.log`, `/tmp/mm-*.sh` на Kraken.
|
||||
|
||||
## Связанные заметки
|
||||
|
||||
|
||||
@@ -1,8 +1,40 @@
|
||||
> Создан 2026-09-28. Статус: **✅ ВЛИТО В АПСТРИМ (2026-09-28T13:22:13Z).**
|
||||
> Мой коммит: **`d4ab923`** (4 файла, +411/−1), ветка `fix/hosted-toolsets-duplicate-endpoint`.
|
||||
> **PR normahq/runtime#5** — **MERGED** (merge-коммит `6775d71`).
|
||||
> Ответ ревьюеру: https://github.com/normahq/runtime/pull/5#issuecomment-5867224210
|
||||
> Репо: `~/Developer/runtime-local`. Связано: [[personal/plans/runtime-pr4-openai-toolcalls-fixes]].
|
||||
> Создан 2026-09-28. Статус: **✅ MERGED В АПСТРИМ 2026-09-28T13:22:13Z (head `facb0d0`).**
|
||||
> Финальная голова PR: **`facb0d0`**. Мейнтейнер добавил **3 фикса поверх** моего `d4ab923` —
|
||||
> см. §0г. Образ Балды переведён на тег **`v2.1.0`** (= `c41939f`, содержит PR #4 + #5).
|
||||
> **PR normahq/runtime#5** — MERGED. Репо: `~/Developer/runtime-local`.
|
||||
> Связано: [[personal/plans/runtime-pr4-openai-toolcalls-fixes]],
|
||||
> [[personal/plans/balda-runtime-rebuild-mm-validation]].
|
||||
|
||||
---
|
||||
|
||||
## 0г. 🔴 Мейнтейнер нашёл 2 реальных дефекта в моём фиксе (`d4ab923` → `facb0d0`)
|
||||
|
||||
Перед мержем в ветку PR #5 добавлены 3 коммита:
|
||||
`f8011c1` fix(agentfactory): preserve MCP dedup metadata ·
|
||||
`e888d5e` fix(agentconfig): validate preferred MCP dedup ·
|
||||
`facb0d0` fix(agentfactory): keep MCP dedup silent.
|
||||
Diff: 5 файлов, +160/−10.
|
||||
|
||||
| # | Дефект в моём фиксе | Фикс мейнтейнера |
|
||||
|---|---|---|
|
||||
| **1** | 🔴 **`hydrateMCPServerConfig` не переносил `DedupKey`/`DedupPreferred`** — собирал новый `MCPServerConfig` поле за полем и **забыл новые поля**. Фикс был бы **мёртв в проде** на пути `Build()` | добавлены `DedupKey: cfg.DedupKey`, `DedupPreferred: cfg.DedupPreferred`. Покрыто тестом `TestFactoryBuildKeepsPreferredDedupEndpoint` (сквозной путь registry → hydration → `hostedToolsets`) |
|
||||
| **2** | `strings.TrimSpace(key)` **нормализовал** ключ → независимо настроенные namespace'ы с пробелами схлопывались (ровно тот cross-tenant риск, который API и предотвращает) | сравнение по **сырому** ключу; проверка пустоты отдельно: `key := resolvedMCP[id].DedupKey; if strings.TrimSpace(key) == ""`. Тест `TestDedupKeyIsOpaque` |
|
||||
| **3** | Две записи с `DedupPreferred: true` в одной группе — **молча** выбиралась одна (зависит от порядка id) | явная ошибка: `mcp dedup key %q has multiple preferred configs`. Тест `TestHostedToolsetsRejectsMultipleDedupPreferredConfigs` |
|
||||
| **4** | `fmt.Printf("[mcp] skipping …")` в **библиотеке** — печать в stdout потребителя | вывод убран (коммит «keep MCP dedup silent») |
|
||||
| **5** | `DedupPreferred: true` без `DedupKey` не валидировался | `ValidateMCPServerConfig`: `dedup_preferred requires dedup_key`. Тест `TestValidateMCPServerConfig_DedupPreferredRequiresDedupKey` |
|
||||
|
||||
📌 **Уроки (durable):**
|
||||
1. 🔴 **Добавляя поле в конфиг — грепнуть ВСЕ места ручного копирования структуры.**
|
||||
`hydrateMCPServerConfig` собирает `MCPServerConfig` поле за полем; компилятор такое **не ловит**
|
||||
(пропущенное поле = zero value, валидный код). Искать `grep -n "MCPServerConfig{"` во всём репо.
|
||||
Это ровно тот класс дефекта, что и «терпимый ассерт» / «копия логики в тесте»: **выглядит
|
||||
рабочим, молчит в проде**.
|
||||
2. ⚠️ **Opaque = opaque.** Назвал ключ «непрозрачным» у вызывающего — не нормализуй его сам.
|
||||
`TrimSpace` выглядел гигиеной, а был дырой безопасности.
|
||||
3. ⚠️ **Библиотека не печатает в stdout.** Логирование — дело потребителя.
|
||||
4. 📌 **Тест сквозного пути ловит то, что юнит-тест уровня функции пропускает.**
|
||||
Мой тест дёргал `hostedToolsets` напрямую и не проходил через hydration — дефект №1 был невидим.
|
||||
Правильный тест — через `f.Build()`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in new issue
Block a user