[2026-09-28] eagle: personal/plans/balda-runtime-rebuild-mm-validation.md personal/plans/runtime-pr4-openai-toolcalls-fixes.md personal/plans/runtime-pr5-toolset-dedup-review-fixes.md personal/tech/adk-hostedagent-openai-mcp.md

This commit is contained in:
Alexey Martemyanov committed 2026-09-28 20:13:45 +06:00
1 parent 73518c5e43
commit 7501feea25
4 files changed
+299 -23

No files matched your search

@@ -1,11 +1,42 @@
> Создан 2026-09-28. Статус: **✅ РЕАЛИЗОВАНО, ЗАПУШЕНО. Ре-ревью ожидается.**
> Голова PR: **`d4ab923`** (4 файла, +411/−1), ветка `fix/hosted-toolsets-duplicate-endpoint`.
> **PR normahq/runtime#5** — OPEN. Ответ ревьюеру опубликован:
> https://github.com/normahq/runtime/pull/5#issuecomment-5867224210
> Создан 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]].
---
## 0а. 🔴 ПОСТ-МЕРЖ: мейнтейнер нашёл 2 дефекта в МОЁМ фиксе
После моего `d4ab923` и **до** мержа в ветку прилетели 3 коммита мейнтейнера
(`f8011c1`, `e888d5e`, `facb0d0` — head PR стал `facb0d0`). Это **code review моего кода**,
и два замечания — настоящие дефекты:
| Коммит | Что нашёл | Почему это мой дефект |
|---|---|---|
| `f8011c1` `fix(agentfactory): preserve MCP dedup metadata` | **`hydrateMCPServerConfig` не переносил `DedupKey`/`DedupPreferred`** в гидратированную копию | 🔴 **Фикс был бы мёртвым в продовом пути `Build()`.** `hostedToolsets` читает гидратированные конфиги → ключ всегда пуст → дедуп никогда не срабатывает. Мой юнит-тест звал `hostedToolsets` **напрямую**, минуя гидратацию, поэтому дефект не поймал |
| `e888d5e` `fix(agentconfig): validate preferred MCP dedup` | `DedupPreferred: true` без `DedupKey` не отвергался | Бессмысленная конфигурация проходила молча |
| `facb0d0` `fix(agentfactory): keep MCP dedup silent` | Убрал мой `fmt.Printf` из библиотеки; добавил ошибку при **нескольких** `DedupPreferred` в одной группе | Библиотека не должна писать в stdout; молчаливый выбор победителя делал активную авторизацию зависимой от порядка id |
| — | **`strings.TrimSpace(key)` — нормализация ключа** | 🔴 Ключ обязан быть **opaque**: `"tenant-a"` и `" tenant-a "` — разные namespace'ы. Нормализация склеила бы независимо сконфигурированные namespace'ы и воссоздала бы cross-tenant merge, который этот API и должен предотвращать |
**Заменённые строки в моём коде:**
```go
// было (мой вариант) // стало (upstream/main)
key := strings.TrimSpace(cfg.DedupKey) key := cfg.DedupKey
if strings.TrimSpace(key) == "" { continue }
skip[id] = true skip[id] = true // без fmt.Printf
```
+ `hydrateMCPServerConfig` теперь копирует `DedupKey`/`DedupPreferred`.
📌 **ГЛАВНЫЙ УРОК (durable):** юнит-тест, вызывающий внутреннюю функцию **напрямую**,
не покрывает продовый путь, где конфиг проходит через **гидратацию/нормализацию**.
Мейнтейнер добавил `TestFactoryBuildKeepsPreferredDedupEndpoint` — он идёт через
`f.Build()` (registry lookup → hydration → hostedToolsets). **Правило: тестировать сквозь
композиционный путь, а не только целевую функцию.** Этот дефект дал бы «зелёные гейты
и неработающий фикс» — ровно тот класс ошибки, против которого был весь PR.
---
## 0. ИТОГ — что сделано
Коммит **`d4ab923`** `fix(agentfactory): dedup MCP toolsets by explicit key`.
@@ -116,15 +147,24 @@ go tool golangci-lint run ./... → 0 issues
## 5. Осталось сделать
1. ⏳ **Ре-ревью metalagman** — ждать.
2. ⛔ **Синхронизация копии рантайма в Balda** (`~/Developer/balda/runtime-local`, HEAD `05342c5a`,
`grep -c DedupKey agentconfig/config.go` → **0**). Правки Balda-слоя (§0) **сейчас не компилируются**
против этой копии — ошибки `unknown field DedupKey in struct literal of type agentconfig.MCPServerConfig`.
Это **отдельная задача**, как и в PR #4 (решать после мержа, чтобы копия не разъехалась снова).
🔴 Пока не синхронизировано — боевой стенд Балды фикс **не получил**.
1. ✅ **Ре-ревью пройдено, PR влит** (`6775d71`).
2. 🔴 **Синхронизация копии рантайма в Balda — ОТКРЫТО, блокирует боевой стенд.**
`~/Developer/balda/runtime-local` — **не клон runtime**, а **снапшот кода эпохи PR #4**
(3 файла отличаются от `upstream/main`, все три — в пользу апстрима; `DedupKey` — **0 вхождений**).
Каталог **git-ignored** в balda и подключён через
`replace github.com/normahq/runtime/v2 => ./runtime-local`.
Правки Balda-слоя из §0 **не компилируются** против него
(`unknown field DedupKey in struct literal of type agentconfig.MCPServerConfig`).
✅ **Потери при замене НЕТ** — проверено `diff -rq`:
отличаются только `agentfactory/agentfactory.go`, `hostedagent/openai.go`,
`hostedagent/openai_test.go` (все — устаревшие версии того, что уже в апстриме).
⚠️ В апстриме мой код **уже исправлен мейнтейнером** (§0а) — синхронизировать надо с
`upstream/main` (`c41939f`), а не с моим `d4ab923`.
План и развилка (убрать `replace` совсем vs заменить копию) —
[[personal/plans/balda-runtime-rebuild-mm-validation]] §1/§3.
3. ⚠️ `/tmp/negctl.sh`, `/tmp/control1.py`, `/tmp/control2.py`, `/tmp/af.bak`, `/tmp/dt.bak`,
`/tmp/commitmsg.txt`, `/tmp/reply.md`, `/tmp/pr5_af.go`, `/tmp/pr5_test.go` — временные.
4. ⚠️ Проверить, не утекла ли ветка PR #4 (`feat/openai-tool-calls-v2`) — она тоже открыта.
4. ✅ Ветки PR #4/#5 больше не «утекли» — обе влиты.
---