Проверка кандидата A28–A31 исполнением.
1. Дублирование ролей. RoleRegistry.migrate_legacy_roles написана верно, но
НЕ ВЫЗЫВАЛАСЬ НИОТКУДА — проверено поиском по всему коду. Вместо неё
работала «идемпотентная миграция» в router_config, дописывавшая недостающие
умолчания и не убиравшая старые роли. На конфигурации владельца интерфейс
показывал 19 агентов, причём шесть пар были неотличимы по названию:
orchestrator и manager — оба «Менеджер проекта», reviewer и code-reviewer —
оба «Ревьюер кода». Разложить аккаунты по такому списку невозможно.
Миграция подключена. Внутри неё нашлась вторая ошибка: при обходе одним
проходом пустая каноническая роль затирала цепочку, перенесённую из старой.
У владельца сработало бы именно так — в manager попал бы codex-orch вместо
выставленного им ag-orch-fallback. Старые роли теперь обрабатываются
первыми: в них и лежит настроенный порядок аккаунтов.
Проверено на живой конфигурации владельца: было 19 ролей, стало 13, все
цепочки совпадают с исходными.
2. Сохранённый workflow мигрируется вместе с ролями. Идентификаторы агентов
повторяют идентификаторы ролей, и без переименования рёбра ссылались бы на
исчезнувших агентов — «Ребро ссылается на отсутствующего агента».
3. Поиск локальных серверов моделей. Раньше адрес вводился руками. Теперь
опрашиваются известные порты на петле — Ollama 11434, LM Studio 1234,
llama.cpp 8080-8082, vLLM 8000, Jan, GPT4All, Text Generation WebUI, —
параллельно, девять портов за 1.5 с. Наружу идёт только то, что ответило;
список моделей берётся у сервера. Порт, занятый чужим сервисом, показывается
с причиной, закрытые не показываются вовсе. Действие discover_local_models.
Роль в фикстурах test_workflow_service_a30 переименована в test-developer:
«developer» — псевдоним канонической developer-1, и тест проверял бы работу
псевдонимов вместо механики workflow.
475 passed, 2 skipped; ruff чисто.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Preflight and updater tests no longer probe 8081/8082 or GitHub.
Hermetic runs fail-fast on non-loopback sockets. GUI helpers are
importable without customtkinter. CI installs the web extra, and
pytest-timeout plus a wall-clock wrapper bound the suite.