14 KiB
02 — Техническое задание (ТЗ)
Work Item: ORCH-044 Основано на: 01-brd.md
Примечание: ТЗ фиксирует что должно измениться и наблюдаемое поведение. Выбор конкретной реализации (например, формат проверки
.credentials.jsonvs парсинг маркера в логе) — за архитектором (стадия architecture, ADR). Где описаны варианты — это границы допустимого решения, а не предписание.
⛔ КОРРЕКЦИЯ SCOPE ВЛАДЕЛЬЦЕМ (Слава, 06.06) — ЧИТАТЬ ПЕРВЫМ
P2 (
--effort) ПОЛНОСТЬЮ ИСКЛЮЧЁН из этой задачи. Решение владельца:
- effort НУЖЕН и работает — его НЕЛЬЗЯ убирать как unsupported. Вариант B запрещён.
- В ORCH-044 НЕ трогать
--effort: ни_spawneffort_flag, ниresolve_agent_effort, ни дефолтыagent_effort_*вconfig.py, ни ORCH-41 effort-доки.- Текущий прод-хотфикс
ORCH_AGENT_EFFORT_*=""в.envоставить как есть — не снимать, не менять.- Полноценный возврат effort (расследование флагов + json) вынесен в ОТДЕЛЬНУЮ задачу ORCH-50 («Эффорт агентов: заставить --effort работать с --print/json»). Туда же — любое расследование причины пустого stdout.
Архитектор/дев игнорируют все TR-2.x и AC-7/AC-8/AC-9, относящиеся к effort. Реализуем ТОЛЬКО:
- P1 — preflight ловит auth (ОБА подхода: проактивно cred-файл
expiresAt+ постфактум маркерNot logged in);- P3 — пустой лог / нет result-JSON ⇒ job
failed(неdone, не вечныйrunning).Заголовок задачи содержит «--effort фикс» по историческим причинам — это НЕ часть scope. Effort = ORCH-50.
1. Задействованные модули src/
| Модуль | Текущее место | Изменение |
|---|---|---|
src/preflight.py |
_run_version, _compute, check |
Добавить дешёвую token-free проверку авторизации (P1) |
src/config.py |
блок ORCH-41 effort (стр. 98–108), новый блок настроек preflight-auth | Настройки auth-проверки; решение по effort-дефолтам (P2) |
src/agents/launcher.py |
_spawn (effort_flag, стр. 290–292, 303–311), _monitor_agent (стр. 460–615), _finalize_job (стр. 630–667) |
Решение по --effort (P2); детекция пустого лога / отсутствия result-JSON (P3) |
src/queue_worker.py |
_drain_once claim-gating (стр. 158–165) |
Учесть новый auth-fail preflight в гейтинге клейма (P1) — при необходимости |
src/db.py |
mark_job |
Использование существующего перевода job → failed (P3); новых колонок не требуется |
Новых файлов модулей не предполагается обязательно; допускается выделение хелпера
(например, _check_auth() в preflight.py) — на усмотрение архитектора.
2. Требования по проблемам
P1 — Preflight ловит авторизацию (token-free)
- TR-1.1. Preflight ДОЛЖЕН, помимо
os.path.exists(bin)иclaude --version, выполнять дешёвую проверку авторизации без обращения к API модели и без prompt-ping. - TR-1.2. Допустимые подходы (выбор — за архитектором, ADR):
- (a) Проверка существования и читаемости файла учётных данных
~/.claude/.credentials.json(HOME агента —/home/slin, см. launcher env, стр. 326) и валидности OAuth-токена по дате истечения внутри (claudeAiOauth.expiresAt, epoch ms) —expiresAt <= now⇒ протух ⇒ fail; - (b) Парсинг реального run-вывода на маркер
Not logged in(и подобные) с переводом job в провал и размыканием/учётом circuit breaker. - Подход (a) предпочтителен как проактивный (ловит ДО клейма); (b) — как защитная сетка постфактум. Допускается комбинация.
- (a) Проверка существования и читаемости файла учётных данных
- TR-1.3. Путь к файлу учётных данных ДОЛЖЕН резолвиться согласованно с тем HOME,
под которым launcher реально спавнит claude (
/home/slin), а не из окружения процесса оркестратора (аналогично тому, как_claude_bin()следует за реально исполняемым путём). - TR-1.4. Результат auth-проверки кешируется тем же механизмом, что и version-check
(
preflight_cache_ttl), чтобы не читать файл на каждый тик воркера. - TR-1.5. При
auth=fail:check()возвращает(False, reason)с информативным reason (например,claude not logged in: credentials missing/OAuth token expired at <iso>). Job НЕ клеймится (поведение_drain_onceуже корректно приok=False). - TR-1.6. Граница ответственности: preflight остаётся локальным (BR-1). Сетевая валидация токена у провайдера — вне объёма.
- TR-1.7. Поведение при «всё хорошо» не меняется: залогинен + валидный токен ⇒
ok=True.
P2 — Решение по --effort
- TR-2.1. Провести расследование (стадия architecture/development): причина пустого
stdout при
--effort+--print --output-format jsonв CLI 2.1.142 — несовместимость с json-форматом, иной синтаксис флага, или баг CLI. Зафиксировать вывод в ADR/10-tech-risks.md. - TR-2.2. По итогам выбрать ровно один исход и привести к нему код+доки+дефолты:
- Вариант A (вернуть effort): найден корректный способ (например, иной синтаксис или
несовместимость только с конкретным output-format) —
--effortснова формируется в_spawnкорректно; прод-хотфиксORCH_AGENT_EFFORT_*=""снимается; добавить регресс-тест, что вывод не пустой. - Вариант B (unsupported): effort несовместим — убрать
--effortиз активного пути запуска (_spawnне формируетeffort_flag), убрать/нейтрализовать дефолты effort вconfig.py, обновить ORCH-41-доки (INFRA.md, internals.md) пометив фичу как unsupported на данной версии CLI.resolve_agent_effortлибо удаляется, либо документированно оставляется заглушкой (решение — ADR).
- Вариант A (вернуть effort): найден корректный способ (например, иной синтаксис или
несовместимость только с конкретным output-format) —
- TR-2.3. Независимо от A/B: не должно остаться «мёртвого» флага, который тихо гасит вывод. После задачи запуск с дефолтной конфигурацией прода ДОЛЖЕН давать непустой result-JSON.
- TR-2.4. Изменение дефолтов/удаление флага не должно ломать
resolve_agent_model(модель — независимая фича ORCH-41) и существующие тестыtest_resolve_agent_effort.py(их допустимо обновить под новый контракт).
P3 — Пустой лог / нет result-JSON ⇒ провал
- TR-3.1. В
_monitor_agent/_finalize_job: приexit_code == 0ДОЛЖНА выполняться проверка валидности результата перед тем как считать job успешным:- run-лог непустой (размер > 0 и/или содержит непустой текст), И
- из него извлекается валидный result-JSON (тот же контракт, что использует
usage._extract_last_json_object/parse_usage_from_log).
- TR-3.2. Если результат невалиден (пустой лог ИЛИ нет валидного JSON) при
exit_code==0, job ДОЛЖЕН трактоваться как провал:- НЕ переводиться в
done; - попасть в путь ретрая/провала (
attempts < max_attempts⇒ requeue, иначеfailed), аналогично permanent-ветке_finalize_permanent, с информативнымerror(например,empty run log / no result JSON (run_id=...)); - сгенерировать алерт (Telegram), как прочие провалы;
- НЕ выполнять авто-advance стадии (
_try_advance_stage) и НЕ постить «успешный» status-коммент.
- НЕ переводиться в
- TR-3.3. Классификация такого провала: по умолчанию — permanent (это не 429/overload).
Если в логе присутствует transient-маркер (через
error_classifier) — допускается transient-путь. Auth-провал (Not logged in) — на усмотрение архитектора: может маршрутизироваться как сигнал брейкеру (P1/TR-1.2b). - TR-3.4. Никогда не оставлять job в
runningнавечно из-за пустого результата: либоdone(валидно), либоfailed/queued(retry). (Watchdog ORCH-7 продолжает закрывать случай таймаута; здесь закрывается случай «быстрая смерть с exit 0».) - TR-3.5. Защитность: вся проверка обёрнута так, что её собственная ошибка не роняет
монитор (как и прочий код
_monitor_agent); при сомнении — fail-safe в сторону провала job.
3. Изменения API
Нет новых/изменённых HTTP-endpoint'ов. Допускается обогащение поля preflight_reason в
/queue (через существующий worker.status() / QueueWorker.last_preflight_reason) более
информативным auth-сообщением — без изменения схемы ответа.
4. Изменения схемы БД
Нет. Используются существующие колонки jobs (status, error, attempts,
max_attempts, transient_attempts) и agent_runs. Новых таблиц/колонок не требуется.
5. Требования к новым QG checks
Новых Quality Gate проверок не требуется — изменения в слое запуска/preflight, не в гейтах
стадий. Реестр QG_CHECKS не меняется.
6. Конфигурация (env / config.py)
- Возможные новые настройки preflight-auth (имена — на усмотрение архитектора), например:
ORCH_PREFLIGHT_CHECK_AUTH(bool, default true) — включение auth-проверки;- путь к credentials, если не выводится из HOME автоматически.
- Решение по effort-дефолтам (
agent_effort_*) согласно TR-2.2 (нейтрализовать при варианте B). - Все новые настройки документируются в
config.pydocstring и в INFRA.md (env-карта).
7. Артефакты pipeline (обязательны к созданию/обновлению)
06-adr/ADR-NNN-*.md— решение по подходу preflight-auth (a/b/комбо) и по effort (A/B).10-tech-risks.md— риск ложноположительной auth-проверки, риск регрессии effort, риск fail-safe-провала на легитимных пустых выводах.12-review.md,13-test-report.md— по стадиям.- Обновить
docs/operations/INFRA.mdиdocs/architecture/internals.md(effort-секции),CHANGELOG.md. Документация = golden source (правило агентов №2).
8. Ограничения и запреты
- ❌ Prompt-ping в preflight (жжёт rate limit) — запрещено (BR-1, комментарий в preflight.py).
- ❌ Сетевые вызовы к API модели в preflight.
- ❌ Оставлять job в
runningбез таймаута при пустом результате. - ❌
--no-verify/обход хуков без одобрения Owner. - ⚠️ Self-hosting: не ронять прод-контейнер
orchestrator; проверка изменений — через staging (8501) перед прод-деплоем (см. CLAUDE.md, INFRA.md).