fix(installer): ошибка 12 при установке — проверка требовала конфигурацию от 20 августа
Владелец получил «Ошибка установки (Код: 12)» на чистой машине. Причина: scripts/verify_multi_provider_router.py, который установщик запускает после развёртывания, требовал РОВНО 16 профилей и дословно заданные цепочки ролей. Миграция из A9 законно доводит конфигурацию до 22 профилей, добавляя claude и grok. Проверено: скрипт падал с «Expected 16 profiles, got 22», то есть установка обрывалась на любой машине, где миграция отработала. Проверки переписаны структурными: есть ли профили у каждого провайдера, непусты ли цепочки ролей и ссылаются ли они только на существующие профили. Смысл проверки — работоспособна ли маршрутизация, а не совпадает ли конфигурация с зафиксированной когда-то. Скрипт проходит 10/10. Отдельно: код 12 возвращался и при отказе проверки, и из общего catch — владелец видел число без причины. Непредвиденный сбой отделён в код 15, обе ветки теперь пишут пояснение в интерфейс установщика. Тесты: 373 passed, ruff чисто. Установщик пересобран. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
8f62adb760
commit
36b449bc6c
5 changed files with 37 additions and 16 deletions
|
|
@ -396,6 +396,12 @@ namespace HermesHubSetup
|
||||||
p.WaitForExit(10000);
|
p.WaitForExit(10000);
|
||||||
if (p.ExitCode != 0)
|
if (p.ExitCode != 0)
|
||||||
{
|
{
|
||||||
|
// Код 12 сам по себе ничего не объясняет: раньше он
|
||||||
|
// возвращался и отсюда, и из общего catch. Владелец
|
||||||
|
// видел «Ошибка установки (Код: 12)» без причины.
|
||||||
|
if (progressCallback != null)
|
||||||
|
progressCallback("Проверка маршрутизации не прошла. Подробности: "
|
||||||
|
+ verifyScript, 0);
|
||||||
return 12; // Router Verification failed
|
return 12; // Router Verification failed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -406,8 +412,11 @@ namespace HermesHubSetup
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
if (progressCallback != null) progressCallback("Error: " + ex.Message, 0);
|
// Отдельный код для непредвиденного сбоя: смешивать его с
|
||||||
return 12;
|
// отказом проверки маршрутизации значит лишать владельца
|
||||||
|
// возможности отличить одно от другого.
|
||||||
|
if (progressCallback != null) progressCallback("Ошибка установки: " + ex.Message, 0);
|
||||||
|
return 15;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -43,24 +43,36 @@ def run_checks() -> int:
|
||||||
# 1. Config inventory
|
# 1. Config inventory
|
||||||
print("1. Checking profile inventory and provider counts...")
|
print("1. Checking profile inventory and provider counts...")
|
||||||
config = get_default_router_config()
|
config = get_default_router_config()
|
||||||
assert len(config.profiles) == 16, f"Expected 16 profiles, got {len(config.profiles)}"
|
# Проверка структурная, а не пересчёт. Раньше здесь стояло «ровно 16
|
||||||
codex_count = sum(1 for p in config.profiles.values() if p.provider == "openai-codex")
|
# профилей» и дословные цепочки от 20 августа. Миграция законно довела
|
||||||
ag_count = sum(1 for p in config.profiles.values() if p.provider == "antigravity")
|
# конфигурацию до 22 профилей, добавив claude и grok, — и установка стала
|
||||||
opengo_count = sum(1 for p in config.profiles.values() if p.provider == "opencode-go")
|
# падать с кодом 12 на любой машине, где миграция отработала. Смысл этой
|
||||||
assert codex_count == 3, f"Expected 3 Codex profiles, got {codex_count}"
|
# проверки в том, работоспособна ли маршрутизация, а не совпадает ли
|
||||||
assert ag_count == 10, f"Expected 10 Antigravity profiles, got {ag_count}"
|
# конфигурация с зафиксированной когда-то.
|
||||||
assert opengo_count == 3, f"Expected 3 OpenCode Go profiles, got {opengo_count}"
|
counts = {}
|
||||||
print(f" [PASS] 16 profiles registered ({codex_count} Codex, {ag_count} Antigravity [7 active, 3 cold], {opengo_count} OpenCode Go)")
|
for prof in config.profiles.values():
|
||||||
|
counts[prof.provider] = counts.get(prof.provider, 0) + 1
|
||||||
|
assert config.profiles, "В конфигурации нет ни одного профиля"
|
||||||
|
for required in ("openai-codex", "antigravity", "opencode-go"):
|
||||||
|
assert counts.get(required), f"Нет ни одного профиля провайдера {required}"
|
||||||
|
summary = ", ".join(f"{prov}: {n}" for prov, n in sorted(counts.items()))
|
||||||
|
print(f" [PASS] Профилей: {len(config.profiles)} ({summary})")
|
||||||
passed += 1
|
passed += 1
|
||||||
|
|
||||||
# 2. Role Fallback Chains
|
# 2. Role Fallback Chains
|
||||||
print("2. Checking role fallback policies...")
|
print("2. Checking role fallback policies...")
|
||||||
assert "orchestrator" in config.roles
|
assert "orchestrator" in config.roles, "Роль orchestrator отсутствует"
|
||||||
assert config.roles["orchestrator"].preferred_chain == ["codex-orch", "ag-orch-fallback", "opengo-3"]
|
# Цепочки настраиваются владельцем и меняются — дословно их сверять нельзя.
|
||||||
assert config.roles["coder-primary"].preferred_chain == ["codex-worker-1", "ag-w1", "opengo-3"]
|
# Проверяем то, что действительно ломает маршрутизацию: цепочка непуста и
|
||||||
assert config.roles["reviewer"].preferred_chain == ["codex-worker-2", "opengo-2", "ag-w2"]
|
# каждый профиль в ней существует.
|
||||||
assert config.roles["research"].preferred_chain == ["opengo-1", "ag-w3", "ag-w4"]
|
for role_name, policy in config.roles.items():
|
||||||
print(" [PASS] All 6 logical role fallback chains validated")
|
chain = policy.preferred_chain or []
|
||||||
|
assert chain, f"У роли {role_name} пустая цепочка отказоустойчивости"
|
||||||
|
for pid in chain:
|
||||||
|
assert pid in config.profiles, (
|
||||||
|
f"Роль {role_name} ссылается на несуществующий профиль {pid}"
|
||||||
|
)
|
||||||
|
print(f" [PASS] Цепочки {len(config.roles)} ролей ссылаются только на существующие профили")
|
||||||
passed += 1
|
passed += 1
|
||||||
|
|
||||||
# 3. Model family extraction
|
# 3. Model family extraction
|
||||||
|
|
|
||||||
0
tests/fixtures/scratch_state.lock
vendored
Normal file
0
tests/fixtures/scratch_state.lock
vendored
Normal file
Loading…
Reference in a new issue