[QA-trace][#184 7/7 финал] Верификация autonomous-runs: инвариант ДЕРЖИТСЯ (real z.ai) + 1 medium TOCTOU-гонка → чиню #241
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Процесс-трейс верификации #184 «durable detached agent runs» (feat/184-autonomous-agent-runs)
Отчёт для владельца скилла web-test-orchestrator. Фокус — на ПРОЦЕССЕ верификации, а не на коде фичи. Особенность стенда: это серверная фича без клиентского UI (в phase 1 нет новых экранов; runId живёт только в метаданных стрима, /stop принимает chatId) — поэтому оракулом служили API + БД, а не визуал.
1. Сводка и ВЕРДИКТ ФИЧИ
Прогон закрыл главный вопрос: переживает ли ход закрытие браузера, персистится ли, возвращает ли его реконнект, и отличается ли явный stop от дисконнекта. Ответ — да, инвариант держится, проверено на реальном платном провайдере (z.ai glm-5.2), а не на заглушке.
ai_chat_runs.status='running'(step=0). Ран продолжил выполнение на сервере, settledsucceeded,step_count=1,finished_atпроставлен,stop_requested_at=NULL. Переоткрытие ТОГО ЖЕ чата в свежем контексте отрисовало полный ответ (не спиннер/не пусто).POST /api/ai-chat/run {chatId}→ 200{run:{полная строка}, message:{assistant, content, status:completed, usage}}; чужой/несуществующий chatId → 403 (owner-gated).{stopped:true}, ранaborted+stop_requested_at+finished_at, assistant-сообщение финализированоaborted(воспроизведено дважды). Дисконнект без /stop → ран доезжает доsucceeded,stop_requested_at=NULL. Поздний /stop на settled-ране →{stopped:false}, штамп не ставится. Пустое тело /stop → 400.ВЕРДИКТ: фича работает, headline-инвариант держится; одна реальная брешь в «один активный run» под конкурентной гонкой + одно диагностическое наблюдение по логам.
2. Агенты и инструменты — кто и как работал
Сработали 4 роли + независимый верификатор. Все драйвили реальный путь приложения (browser → /api/ai-chat/stream через aiFetch-обёртку), что критично: на этом стенде была явная установка не подменять путь сырым curl/openai-sdk.
useChat, получил живой SSE с runId вstart.messageMetadata; psql как ground-truth поai_chat_runs/ai_chat_messages. Заложил карту эндпоинтов и lifecycle (beginRun/finalizeRun) для остальных./proc/<pid>/fd→ q184-server.log) как оракул. Развёл Case A (stop→aborted) и Case B (disconnect→succeeded).http.client+threading/Barrier для одновременных/таймированных запросов, 30–50ms watcher по psql на активные строки. Нашёл TOCTOU-гонку и одновременно подтвердил, что БД-инвариант (≤1 строки) держится.Как справились с отсутствием клиентского UI. Ни один из проверяемых аспектов не имел экрана. Агенты осознанно сделали БД и API оракулом:
ai_chat_runs(status, stop_requested_at, started/finished_at, assistant_message_id, step_count) иai_chat_messages(роль/контент/status) давали объективную истину состояния, а /run и /stop — наблюдаемое поведение. UI использовался ТОЛЬКО там, где он нужен по существу — стартануть настоящий ход и отрисовать переоткрытый чат (durable-detached). Это не ограничило покрытие: все ветки lifecycle, реконнекта и stop проверены через API+DB точнее, чем дал бы UI. Единственная честная брешь — наблюдаемость INFO-лога (его нет в UI и его отсутствие функционально безвредно).3. Находки по классу (что / как / кем / этап)
feature-works (подтверждено):
running→succeeded, поля заполнены, assistant_message_id связан — recon, psql сразу после хода.feature-broken (1, medium):
observability (1, diagnostic-only):
likely→ верификатор поднял доverified(репро с --max-time 3 до первого чанка; grep всего лога = 0; проверено, что вызов лога есть в бинаре, флаг=true) — stop-vs-disconnect → VERIFIER.env-limitation (2, не дефекты фичи):
token.pyтеневит stdlibtoken→ Playwright-импорт виснет из scratchpad-каталога; + установленному playwright 1.60 нуженexecutable_pathна chromium-1148. Обойдено запуском из чистого подкаталога — recon.4. Фолс-позитивы
0 ложных срабатываний. Верификатор независимо пересобрал обе небанальные находки (race и observability-лог) — обе подтверждены, ни одна не опровергнута и не понижена. Наоборот, неуверенная находка (
likely) была повышена доverified. Позитивные верификации (feature-works) не отправлялись на повторную проверку, т.к. опирались на прямой БД/API-оракул, а не на скриншот-«похоже работает» — то есть классический источник success-hallucination здесь был структурно исключён.5. Где скилл сработал, а где спотыкался (server-only / async-durability / реальный AI)
Сработало:
status='running'/step=0, а потом поллить psql до settled. Это поймало настоящий инвариант, а не «успело до закрытия».ai_chat_runs/ai_chat_messages+ серверный лог через/proc/<pid>/fd. Это дало детерминированную истину, недоступную через UI.Спотыкалось / ограничения:
token.py-теневание stdlib и рассинхрон версии playwright/chromium сожгли время на bisect до того, как пошла собственно верификация.6. Предложения по скиллу (как тестировать server-only / async-durability фичи)
running(а неpending/ужеdone), и только тогда рвать клиента. Без этой синхронизации тест проверяет не то.token.py) и фиксироватьexecutable_path/версию chromium — чтобы тулинговое трение не съедало бюджет до начала верификации.📌 Итог серии 7/7. Все 7 прогонов с процесс-трейс-отчётами: #235 #236 (#119 git-sync ×2), #237 #238 (#120 offline ×2), #239 (#221 captions — работает), #240 (#228 footnotes — была сломана → починил
fa929c9e), этот (#184 — работает + 1 medium гонка). Скилл-фидбэк по серии: verifier незаменим (убивал ложные контрольными экспериментами); главные провалы — нулевая межролевая дедупликация (1 баг = N находок), недо-сэмплирование verifier'а на all-pass фичах, и (отдельно) тот случай с зависанием на bash-промпте (не баг скилла — окружение).Найденную гонку (TOCTOU обход 409) чиню в #234 — второй конкурентный stream должен отклоняться (409), а не идти untracked.
🤖 web-test-orchestrator (process-trace, feature-verify)
Ghost referenced this issue2026-06-27 19:20:51 +03:00