[QA-trace][#119 2/7] Процесс-отчёт прогона web-test-orchestrator (git-sync) — стабильность vs прогон 1 #236

Closed
opened 2026-06-27 14:26:11 +03:00 by Ghost · 0 comments

Прогон 2/7 · эпик PR #119 (git-sync) · web-test-orchestrator · 22 агента / 21 сырых → 12 подтверждено / 2 ложных.
Процесс-отчёт для отладки скилла (агенты/инструменты/класс багов/фолс-позитивы), без кода багов. Сравни с прогоном 1 (#235) — стабильность находок/FP между прогонами.

Process-trace QA отчёт — PR #119 «native two-way git-sync» (gitmost / Docmost fork)

Фокус отчёта — НЕ конкретный баговый код, а ПРОЦЕСС работы skill web-test-orchestrator: какие агенты/инструменты отработали, какой КЛАСС бага каждый нашёл, КАК и на каком ЭТАПЕ он всплыл, и КТО системно фолс-позитивит. Это материал для отладки самого скилла.


1. Сводка прогона

Стадии (как шёл конвейер):
recon → mapping → charters (6 слайсов-персон) → execution (Whittaker-туры) → oracle-eval (FEW HICCUPPS + дешёвые объективные сигналы: console-errors, HTTP 4xx/5xx, failed-requests, пустые тела, git-clone ground-truth) → independent Doer-Verifier pass → report.

Агентов: 8 ролей — recon + 6 слайс-агентов (editor-content QA/note-taker, tree-nav QA/organizer, share-search-settings QA/power-user, ai-chat-ui QA, git-roundtrip-tester, dual-edit-tester) + verifier.

Воронка находок:

  • Сырых находок: 21.
  • Из них «продуктовые/sync-баги» (ушли в verifier по сути): 14; чистых env/tooling/self-caught-FP-hazard (корректно отсеяны самими агентами, не баги): 7.
  • После verifier-прохода: 12 подтверждено, 2 убито/понижено до speculative (false-positive), 7 env-ограничений признаны корректной классификацией (не баги и не FP).
  • Verifier при этом дважды ПОВЫСИЛ уверенность (speculative→verified) и дважды переписал МЕХАНИЗМ подтверждённого бага (premise был неверен, артефакт — реален).

Тяжесть подтверждённого: 2×HIGH (callout-strip data-loss; same-line dual-edit wedge всей синхры), несколько medium (callout-type flatten, body-duplication, AI-chat misleading error), остальное low (console-noise, render-stale).


2. Какие агенты/инструменты отработали

recon — карта приложения + базовые оракулы.
Инструменты: Playwright (python sync_api, headless chromium через явный executable_path на chromium-1148), Bash+git для smart-HTTP clone волта, Read скриншотов/исходников, grep/find для маппинга кода.
Проявил себя: первый же скрипт упал на запуске (нашёл tooling-mismatch), затем поймал login-race и зафиксировал правило «гейтиться на post-login URL/cookie, а не на networkidle» — это правило спасло остальные слайсы. Подтвердил console.error-флуд на cold-mount редактора. Чистый, без продуктовых FP.

editor-content QA (note-taker) — содержимое страниц, редактор, round-trip в git.
Инструменты: Playwright (console+network+pageerror listeners; eval_on_selector структурные/innerHTML снимки; TIMED innerText sampling t+0.3/1/2/3/5/8/9s; полностраничные скриншоты), Bash git clone волта как out-of-band ground truth + idle re-clone monitor (3×20s), API cookie-login через http.cookiejar (обход login-429).
Проявил: его TIMED-сэмплинг — единственный способ поймать «нода исчезает на холостом ходу между t+3 и t+5s». Сильный по data-loss/duplication, но дал 1 FP на input-shortcut-классе (см. §4).

tree-nav QA (organizer) — дерево навигации, move/trash/restore, DnD.
Инструменты: Playwright (create page/subpage, chevron collapse/expand, node-menu move-to-trash, restore+confirm-modal, native-DnD mouse down/move/up → /pages/move 200, reloads, свежие контексты), in-page fetch() с credentials к бэкенду (/pages/sidebar-pages, /pages/trash, /pages/tree, /pages/breadcrumbs) как out-of-band оракул, git clone волта, console/pageerror/HTTP≥400 на каждой странице, чтение исходников дерева.
Проявил: образцовая дисциплина — дважды поймал СОБСТВЕННЫЙ would-be high-sev FP (виртуализованное дерево; пропущенный клик confirm-modal) и сам их дисконфёрмил триангуляцией с бэкендом. Реальный баг отдал только один (atomFamily deprecation).

share-search-settings QA (power-user) — публичный share, spotlight-поиск, SSR/crawler.
Инструменты: Playwright (storage_state reuse; console/pageerror/requestfailed + HTTP≥400; frame-by-frame DOM poll ~12ms input.value vs results), curl + urllib/http.client для прямых API и SSR-пути на :3000 (302/404, Googlebot UA), grep+Read исходников share/search.
Проявил: микро-поллинг кадров поймал stale-render, который verifier потом подтвердил и даже повысил (speculative→verified). 0 FP.

ai-chat-ui QA — AI-чат UI/стрим.
Инструменты: Playwright (инжект authToken cookie для обхода 429; console/response/requestfailed/pageerror; клик floating-кнопки, send via Enter; проверка badge/composer/disabled; скриншоты), curl (POST /api/ai-chat/stream напрямую, 3× тайминги ~0.11s), Postgres через docker-exec psql (workspaces.settings→ai, ai_chats, ai_chat_messages), серверный лог через /proc/<pid>/fd, node require.resolve/ESM-probe для подтверждения mcp build-mismatch, чтение клиент+сервер исходников.
Проявил: самая глубокая триангуляция (тайминг → DB → исходники → build-probe). Все 3 находки реальны, 0 FP. Эталон по «докопаться до root-cause, а не до симптома».

git-roundtrip-tester — двусторонний git↔docmost round-trip.
Инструменты: Playwright (chromium-1148 via executable_path+--no-sandbox; cookie state.json), Bash git (clone/edit .md/commit/fetch+rebase/push/reset --hard pulls волта), curl для API-токена (обход login rate-limit), console+response(4xx/5xx), websocket(:3001/collab) readiness, скриншоты, reload-still-present после каждого save.
Проявил: классический git-export-оракул (автор .md → push → wait → fetch/reset → diff). Поймал fidelity-loss и contention-503. 0 FP, одна находка повышена verifier'ом.

dual-edit-tester — конкурентные правки одной строки с двух сторон.
Инструменты: Playwright (живой collab-редактор, постановка курсора по тексту, body vs title editor, наблюдение git→editor live-апдейтов), REST API /api/pages/info,/api/spaces/info, Bash git + SERVER-VAULT forensics (git -C <vault> status --porcelain, ls-files -u, .git/MERGE_HEAD, git show <branch>:file, git log), инспекция серверных логов двух инстансов, чтение cycle.ts/pull.ts/yjs-body-merge.ts.
Проявил: нашёл флагманский HIGH (wedge всей синхры) благодаря серверной форензике волта — то, чего никакой UI-оракул не увидит. Но он же — главный фолс-позитивщик (§4): второй финдинг verifier дисконфёрмил.

verifier (independent Doer-Verifier pass) — анти-галлюцинация.
Инструменты: повторял находки независимо — Playwright clean-context reloads, контрольные документы (table-doc vs plain-doc; top-level fence vs list fence), свежий git clone + git log/git show по ревизиям sync-коммитов, psql, curl, frame-poll, чтение исходников.
Проявил: убил 2 FP, повысил 2 speculative, переписал механизм у 2 подтверждённых (premise неверен — артефакт реален). Ключевой элемент, без него прошли бы 2 ложных high/medium-звучащих финдинга.


3. Найденные баги — по КЛАССУ

DATA-LOSS (silent)

  • Callout strips body (HIGH) — проявление: вставил callout, через t+3..5s БЕЗ действий/reload вся нода и текст исчезают, в т.ч. соседний обычный параграф; git clone показывает пустое тело (frontmatter-only); ноль console/4xx/5xx. Найден: editor-content QA, этап execution; метод — TIMED innerText sampling поймал исчезновение на холостом ходу, подтверждён out-of-band git clone, изолирован контролем (Toggle-блок выжил), репро 5×.
  • Loss-on-fast-close (collab-flush-race) — проявление: контент виден на экране, закрыл вкладку ~3s → reload пустой, git = 59-байтный frontmatter-only. Найден: git-roundtrip-tester варьированием open-wait (3/18/35s) + git-clone сигнатура 59 байт. Verifier ПОВЫСИЛ до verified, уточнив окно потери до ≥18s.

AVAILABILITY / SILENT-WEDGE (отдельный класс — самый опасный)

  • Single same-line dual-edit wedge (HIGH) — проявление: одна коллизия по строке на ОДНОЙ странице замораживает sync для всех 344 страниц в обе стороны бессрочно, без индикации в UI; 1685 «unresolved merge … skipping cycle» в логе. Найден: dual-edit-tester — стенд приехал уже замороженным; форензика server-vault (UU, MERGE_HEAD, ls-files -u) + доказанная НЕ-recovery (merge --abort → следующий цикл снова конфликтует).

IDEMPOTENCY / ДУБЛИРОВАНИЕ

  • Body written twice (reconcile-doubling) — проявление: .md в git содержит тело дважды (221 байт, стабильно 2×, не растёт). Найден: editor-content QA git-clone diff + idle re-clone monitor; verifier дотрассировал через git log 0→1→2 по последовательным sync-коммитам и поправил premise («в редакторе одна копия» — на деле тоже две).
  • Orphan «Untitled chat» (state-litter) — проявление: каждый упавший send плодит новый chat + одинокую user-строку без assistant. Найден: ai-chat-ui QA через psql ai_chats/ai_chat_messages + рендер истории.

ROUNDTRIP-FIDELITY

  • Callout type → [!info] — проявление: [!tip]/[!note]/[!important]/[!caution]/[!question] после импорта/ре-сериализации схлопываются в [!info]; выживают только info/warning/danger/success. Найден: git-roundtrip-tester — авторский .md с 9 типами → push → wait ~20s → fetch/reset → grep -o дал 1:1 маппинг; verifier воспроизвёл независимо.

SILENT-FAILURE / MISLEADING-ERROR / DIAGNOSABILITY

  • AI-chat «Please try again» — проявление: детерминированный 500 на 100% сендов, но баннер советует «попробуйте снова», реальная причина (provider/build) скрыта. Найден: ai-chat-ui QA response-listener (500 {"error":"Internal server error"}) + трассировка post-hijack в исходниках; verifier подтвердил по отсутствию ; charset=utf-8 на 500 (отпечаток raw-socket write).
  • mcp stale build (env, root-cause всех 500) — найден тем же агентом через детерминированный ~0.11s тайминг (нет round-trip к провайдеру) + DB + node require.resolve.

CONTENTION / TRANSIENT

  • git push 503 / remote hung up — проявление: push отбивается 503 пока docmost в середине sync-цикла + non-ff из-за автокоммитов docmost. Найден: git-roundtrip-tester; verifier воспроизвёл двумя путями (2 параллельных clone; 6 быстрых push подряд → 503 на 4/6).

RENDERING / CONSOLE-NOISE

  • flushSync на cold-mount редактораrecon, console-listener на прямом goto (4 ошибки), контроль: in-app навигация = 0.
  • flushSync на reload страницы с таблицейeditor-content QA, console-listener + контроль plain-doc (0 ошибок) изолировал причину на таблицу.
  • atomFamily deprecatedtree-nav QA, console-capture + grep исходника jotai; verifier уточнил: только dev-build, once-per-module.
  • Share-spotlight stale rendershare-search QA, frame-by-frame ~12ms poll; verifier ПОВЫСИЛ speculative→verified, но поправил атрибуцию (не keepPreviousData, а 300ms debounce).

ORACLE-CONTAMINATION (процессная находка, не баг продукта)

  • Виртуализованное дерево как невалидный оракулtree-nav QA сам дисконфёрмил «пропавшие страницы» через пагинацию /pages/sidebar-pages (360 root pages) + grep useVirtualizer. Записан как урок для скилла.

ENV / TOOLING

  • Playwright 1.60 ждёт chromium-1223, есть только 1148 (recon); login-race до установки cookie (recon); auth-throttler 10/min делит бакет с обычными SPA-вызовами → 429 (git-roundtrip-tester). Все корректно помечены env-limitation.

3b. Кто что нашёл (finding → агент → класс → вердикт)

Finding Агент Класс Вердикт
Playwright 1223 vs 1148 recon tooling-mismatch env (корректно)
Login-race до cookie recon async-timing env/tooling pitfall
flushSync cold-mount редактора recon render console-noise verified
Callout strips body editor-content silent-data-loss verified (HIGH)
Body written twice editor-content serialization/reconcile dup verified (механизм переписан)
flushSync на таблице editor-content render console-error verified
``` fence в list-item editor-content input-shortcut speculative — FP (list-причина опровергнута)
Virtualized tree oracle tree-nav oracle-contamination self-caught FP-hazard (корректно)
Restore confirm-modal timing tree-nav interaction-timing self-caught FP-hazard (корректно)
atomFamily deprecated tree-nav console-noise verified
Share-spotlight stale share-search rendering verified (↑ из speculative)
Ask-AI widget не тестируем share-search silent-failure (env) env (корректно)
AI-chat misleading error ai-chat-ui misleading-error verified
Orphan «Untitled chat» ai-chat-ui idempotency/litter verified
@docmost/mcp stale build ai-chat-ui build/packaging (env) env root-cause (корректно)
Callout type → [!info] git-roundtrip roundtrip-fidelity verified
git push 503 git-roundtrip contention/transient verified
Loss-on-fast-close git-roundtrip collab-flush-race verified (↑ из speculative)
Auth throttler 429 git-roundtrip rate-limit (env) env (корректно)
Same-line dual-edit wedge dual-edit silent-wedge/availability verified (HIGH)
Wedged-vault misleading git-err dual-edit silent-failure/diagnosability speculative — FP (тезис опровергнут)

4. ФОЛС-ПОЗИТИВЫ — кто и насколько (ключевой раздел)

Считаем по продуктовым находкам, прошедшим через verifier (env-ограничения и self-caught FP-hazard не штрафуем — это корректная классификация).

Агент Продуктовых находок Подтверждено Убито verifier (FP) Доля FP
recon 1 (+2 env) 1 0 0%
editor-content QA 4 3 1 25%
tree-nav QA 1 (+2 self-caught) 1 0 0% (сам ловит свои FP)
share-search QA 1 (+1 env) 1 0 0% (даже ↑)
ai-chat-ui QA 2 (+1 env) 2 0 0%
git-roundtrip-tester 3 (+1 env) 3 0 0% (одна ↑)
dual-edit-tester 2 1 1 50%

Системно фолс-позитивят:

  • dual-edit-tester — 50% (1/2), и именно на «громком» классе. Реальный wedge он нашёл блестяще, но второй финдинг («misleading git-error маскирует сломанное серверное дерево, rebase+retry НЕ помогает») verifier опроверг: «fetch first» — это КОРРЕКТНАЯ git-семантика, remote реально опережает клиента из-за непрерывных автокоммитов docmost; rebase+retry СРАБОТАЛ. Корень FP — наблюдение в idle-окне («origin/main стабилен 3 фетча») было интерпретировано как «дерево сломано», хотя под нагрузкой tip двигался ~раз/1-2s. Класс ошибки: over-attribution симптома к худшему корню при недостаточной нагрузке во время наблюдения.
  • editor-content QA — 25% (1/4) на input-shortcut классе: склеил два независимых явления («fence ломается в list-item» — на деле ломается и top-level из-за пропущенного пробела после js; list-причина опровергнута grep'ом по волту). Класс ошибки: conflation двух феноменов + причинно-следственная гипотеза без контроля. При этом его data-loss/duplication находки безупречны.

Надёжные агенты:

  • ai-chat-ui QA и git-roundtrip-tester — 0% FP при глубине (DB+тайминг+исходники / git-export-оракул). Самые доверенные.
  • tree-nav QA — образец: дважды САМ дисконфёрмил свои потенциальные high-sev FP до отправки (виртуализация дерева; пропуск клика в confirm-modal). Его дисциплина — модель поведения, которую стоит зашить в charter всех агентов.
  • share-search QA и recon — чисто.

Важно про verifier: он не только убивает FP (2), но и СПАСАЕТ недооценённое (fast-close и share-stale подняты speculative→verified) и ЧИНИТ механизм у верных находок (body-dup, share-stale-атрибуция). То есть verifier работает в обе стороны — и анти-галлюцинация, и анти-недооценка.


5. Где скилл сработал/провалился

Сработал именно ПРОЦЕСС (а не везение):

  • git-export как out-of-band ground-truth — поймал то, что UI скрывает: callout-strip (пустое тело), body-duplication (221 байт ×2), callout-type-flatten, 59-байтные frontmatter-only при fast-close. Это — главный оракул для git-sync фичи и он окупился многократно.
  • TIMED innerText sampling на холостом ходу — единственный способ увидеть «нода исчезает между t+3 и t+5s без действий». Обычный snapshot-after-action этого не ловит.
  • Контрольные документы (controls) — Toggle vs Callout изолировал data-loss на конкретный узел; plain-doc vs table-doc изолировал flushSync на таблицу; top-level vs list fence развалил ложную гипотезу. Контроль — то, что отличает находку от догадки.
  • Серверная форензика волта (status/MERGE_HEAD/ls-files -u/лог) — поймала флагманский wedge, невидимый ни в UI, ни в API.
  • Verifier-проход — убил 2 FP, которые звучали как high/medium, и докрутил механизмы.
  • Глубокая триангуляция тайминг→DB→исходники→build-probe (ai-chat) — довела симптом «try again» до настоящего root-cause (stale mcp build), а не остановилась на баннере.

Чуть не упустил / провалился:

  • Виртуализованное дерево едва не дало false high «созданные страницы пропали» — спас только инстинкт триангулировать DOM-счёт с бэкендом. Если бы агент доверился DOM-оракулу, ушёл бы ложный data-loss.
  • dual-edit «misleading error» прошёл слайс как verified и был дисконфёрмлен только verifier'ом — без независимого прохода ушёл бы ложный medium.
  • Login-429 / throttler многократно ломал браузерный логин и заставлял агентов городить cookie-инжект/curl-логин — потерянное время и риск, что слабый агент спишет это на «приложение сломано».
  • Атрибуция причин — слабое место: share-stale (keepPreviousData), body-dup («одна копия в редакторе»), fence-list — во всех трёх premise/механизм был неверен, хотя артефакт (кроме fence) реален.

6. Предложения по улучшению скилла

Оракулы:

  1. Зашить правило «никогда не считать DOM-строки виртуализованного списка как presence/loss-оракул» — при подозрении на пропажу всегда триангулировать с бэкендом (пагинация API) или git-clone. Это чуть не дало false high.
  2. Для любой save/round-trip фичи сделать git-export (или DB) обязательным out-of-band оракулом — UI-снапшот недостаточен; самые тяжёлые баги видны только в .md/в DB.
  3. Добавить idle-watch оракул: после ввода контента сэмплировать innerText на холостом ходу (t+1/3/5/8s) — целый класс silent-data-loss виден только так.
  4. Требовать контрольный документ для любого «X ломается»: тот же сценарий без подозреваемого фактора. Без контроля находка = гипотеза.

Charters / дисциплина агентов:
5. Кодифицировать «tree-nav discipline» во все charters: прежде чем репортить loss/ghost — доказать, что мутация реально дошла до бэкенда (проверить API), а наблюдение сделано НЕ в idle-окне под нагрузкой sync.
6. Для git-sync charters явно предупредить: «remote main двигается сам каждые 1-2s из-за автокоммитов docmost; fetch first-rejection — НОРМА, а не маскировка». Это убрало бы 50% FP dual-edit-тестера.
7. Запретить conflation: одна находка = один воспроизводимый феномен; если два симптома, развести их и дать каждому свой контроль (кейс fence).

Verifier-гейты:
8. Любой финдинг с severity≥medium, у которого корень = «сломан сервер/масштабное состояние», обязан пройти повторение под нагрузкой (а не в idle-окне) — именно это развалило dual-edit FP.
9. Verifier должен явно проверять premise/механизм, а не только наличие артефакта — у 3 находок артефакт верен, объяснение нет; в отчёт должен идти исправленный механизм.
10. Verifier должен уметь повышать (speculative→verified), а не только убивать — иначе fast-close и share-stale ушли бы недооценёнными.

Окружение / дедуп:
11. Решить login-429 централизованно один раз на прогон (общий curl-минтинг authToken + reuse storage_state), а не заставлять каждый слайс изобретать обход — экономия времени и снятие риска ложного «приложение не аутентифицирует».
12. Дедуп console-noise: flushSync (cold-mount + table) и atomFamily всплыли у трёх агентов независимо — добавить общий «known-console-noise» реестр, чтобы агенты не репортили одно и то же трижды как новое.
13. Зафиксировать в окружении executable_path к chromium-1148 как дефолт, чтобы recon не падал на старте каждого прогона.


Мета-фидбэк: этот прогон НЕ завис — добавленный per-agent timeout (9 мин) + timebox в verify сработали (в прогоне 1 один verifier висел 5.5ч). Рекомендация в скилл подтверждена практикой.

🤖 web-test-orchestrator (process-trace)

> **Прогон 2/7** · эпик **PR #119** (git-sync) · web-test-orchestrator · 22 агента / 21 сырых → 12 подтверждено / 2 ложных. > Процесс-отчёт для отладки скилла (агенты/инструменты/класс багов/фолс-позитивы), без кода багов. Сравни с прогоном 1 (#235) — стабильность находок/FP между прогонами. # Process-trace QA отчёт — PR #119 «native two-way git-sync» (gitmost / Docmost fork) Фокус отчёта — НЕ конкретный баговый код, а ПРОЦЕСС работы skill `web-test-orchestrator`: какие агенты/инструменты отработали, какой КЛАСС бага каждый нашёл, КАК и на каком ЭТАПЕ он всплыл, и КТО системно фолс-позитивит. Это материал для отладки самого скилла. --- ## 1. Сводка прогона **Стадии (как шёл конвейер):** recon → mapping → charters (6 слайсов-персон) → execution (Whittaker-туры) → oracle-eval (FEW HICCUPPS + дешёвые объективные сигналы: console-errors, HTTP 4xx/5xx, failed-requests, пустые тела, git-clone ground-truth) → independent Doer-Verifier pass → report. **Агентов:** 8 ролей — `recon` + 6 слайс-агентов (`editor-content QA`/note-taker, `tree-nav QA`/organizer, `share-search-settings QA`/power-user, `ai-chat-ui QA`, `git-roundtrip-tester`, `dual-edit-tester`) + `verifier`. **Воронка находок:** - Сырых находок: **21**. - Из них «продуктовые/sync-баги» (ушли в verifier по сути): 14; чистых env/tooling/self-caught-FP-hazard (корректно отсеяны самими агентами, не баги): 7. - После verifier-прохода: **12 подтверждено**, **2 убито/понижено до speculative** (false-positive), 7 env-ограничений признаны корректной классификацией (не баги и не FP). - Verifier при этом дважды ПОВЫСИЛ уверенность (speculative→verified) и дважды переписал МЕХАНИЗМ подтверждённого бага (premise был неверен, артефакт — реален). **Тяжесть подтверждённого:** 2×HIGH (callout-strip data-loss; same-line dual-edit wedge всей синхры), несколько medium (callout-type flatten, body-duplication, AI-chat misleading error), остальное low (console-noise, render-stale). --- ## 2. Какие агенты/инструменты отработали **recon** — карта приложения + базовые оракулы. Инструменты: Playwright (python sync_api, headless chromium через явный `executable_path` на chromium-1148), Bash+git для smart-HTTP clone волта, Read скриншотов/исходников, grep/find для маппинга кода. Проявил себя: первый же скрипт упал на запуске (нашёл tooling-mismatch), затем поймал login-race и зафиксировал правило «гейтиться на post-login URL/cookie, а не на networkidle» — это правило спасло остальные слайсы. Подтвердил console.error-флуд на cold-mount редактора. Чистый, без продуктовых FP. **editor-content QA (note-taker)** — содержимое страниц, редактор, round-trip в git. Инструменты: Playwright (console+network+pageerror listeners; eval_on_selector структурные/innerHTML снимки; **TIMED innerText sampling** t+0.3/1/2/3/5/8/9s; полностраничные скриншоты), Bash `git clone` волта как out-of-band ground truth + idle re-clone monitor (3×20s), API cookie-login через http.cookiejar (обход login-429). Проявил: его TIMED-сэмплинг — единственный способ поймать «нода исчезает на холостом ходу между t+3 и t+5s». Сильный по data-loss/duplication, но дал 1 FP на input-shortcut-классе (см. §4). **tree-nav QA (organizer)** — дерево навигации, move/trash/restore, DnD. Инструменты: Playwright (create page/subpage, chevron collapse/expand, node-menu move-to-trash, restore+confirm-modal, native-DnD mouse down/move/up → `/pages/move` 200, reloads, свежие контексты), in-page `fetch()` с credentials к бэкенду (`/pages/sidebar-pages`, `/pages/trash`, `/pages/tree`, `/pages/breadcrumbs`) как out-of-band оракул, git clone волта, console/pageerror/HTTP≥400 на каждой странице, чтение исходников дерева. Проявил: **образцовая дисциплина** — дважды поймал СОБСТВЕННЫЙ would-be high-sev FP (виртуализованное дерево; пропущенный клик confirm-modal) и сам их дисконфёрмил триангуляцией с бэкендом. Реальный баг отдал только один (atomFamily deprecation). **share-search-settings QA (power-user)** — публичный share, spotlight-поиск, SSR/crawler. Инструменты: Playwright (storage_state reuse; console/pageerror/requestfailed + HTTP≥400; **frame-by-frame DOM poll ~12ms** input.value vs results), curl + urllib/http.client для прямых API и SSR-пути на :3000 (302/404, Googlebot UA), grep+Read исходников share/search. Проявил: микро-поллинг кадров поймал stale-render, который verifier потом подтвердил и даже повысил (speculative→verified). 0 FP. **ai-chat-ui QA** — AI-чат UI/стрим. Инструменты: Playwright (инжект authToken cookie для обхода 429; console/response/requestfailed/pageerror; клик floating-кнопки, send via Enter; проверка badge/composer/disabled; скриншоты), curl (POST `/api/ai-chat/stream` напрямую, 3× тайминги ~0.11s), **Postgres через docker-exec psql** (workspaces.settings→ai, ai_chats, ai_chat_messages), серверный лог через `/proc/<pid>/fd`, node `require.resolve`/ESM-probe для подтверждения mcp build-mismatch, чтение клиент+сервер исходников. Проявил: самая глубокая триангуляция (тайминг → DB → исходники → build-probe). Все 3 находки реальны, 0 FP. Эталон по «докопаться до root-cause, а не до симптома». **git-roundtrip-tester** — двусторонний git↔docmost round-trip. Инструменты: Playwright (chromium-1148 via executable_path+--no-sandbox; cookie state.json), Bash git (clone/edit .md/commit/fetch+rebase/push/reset --hard pulls волта), curl для API-токена (обход login rate-limit), console+response(4xx/5xx), websocket(:3001/collab) readiness, скриншоты, reload-still-present после каждого save. Проявил: классический git-export-оракул (автор .md → push → wait → fetch/reset → diff). Поймал fidelity-loss и contention-503. 0 FP, одна находка повышена verifier'ом. **dual-edit-tester** — конкурентные правки одной строки с двух сторон. Инструменты: Playwright (живой collab-редактор, постановка курсора по тексту, body vs title editor, наблюдение git→editor live-апдейтов), REST API `/api/pages/info`,`/api/spaces/info`, Bash git + **SERVER-VAULT forensics** (`git -C <vault> status --porcelain`, `ls-files -u`, `.git/MERGE_HEAD`, `git show <branch>:file`, `git log`), инспекция серверных логов двух инстансов, чтение cycle.ts/pull.ts/yjs-body-merge.ts. Проявил: нашёл флагманский HIGH (wedge всей синхры) благодаря серверной форензике волта — то, чего никакой UI-оракул не увидит. Но он же — главный фолс-позитивщик (§4): второй финдинг verifier дисконфёрмил. **verifier (independent Doer-Verifier pass)** — анти-галлюцинация. Инструменты: повторял находки независимо — Playwright clean-context reloads, контрольные документы (table-doc vs plain-doc; top-level fence vs list fence), свежий git clone + `git log`/`git show` по ревизиям sync-коммитов, psql, curl, frame-poll, чтение исходников. Проявил: убил 2 FP, повысил 2 speculative, переписал механизм у 2 подтверждённых (premise неверен — артефакт реален). Ключевой элемент, без него прошли бы 2 ложных high/medium-звучащих финдинга. --- ## 3. Найденные баги — по КЛАССУ **DATA-LOSS (silent)** - *Callout strips body* (HIGH) — проявление: вставил callout, через t+3..5s БЕЗ действий/reload вся нода и текст исчезают, в т.ч. соседний обычный параграф; git clone показывает пустое тело (frontmatter-only); ноль console/4xx/5xx. Найден: **editor-content QA**, этап execution; метод — TIMED innerText sampling поймал исчезновение на холостом ходу, подтверждён out-of-band git clone, изолирован контролем (Toggle-блок выжил), репро 5×. - *Loss-on-fast-close* (collab-flush-race) — проявление: контент виден на экране, закрыл вкладку ~3s → reload пустой, git = 59-байтный frontmatter-only. Найден: **git-roundtrip-tester** варьированием open-wait (3/18/35s) + git-clone сигнатура 59 байт. Verifier ПОВЫСИЛ до verified, уточнив окно потери до ≥18s. **AVAILABILITY / SILENT-WEDGE** (отдельный класс — самый опасный) - *Single same-line dual-edit wedge* (HIGH) — проявление: одна коллизия по строке на ОДНОЙ странице замораживает sync для всех 344 страниц в обе стороны бессрочно, без индикации в UI; 1685 «unresolved merge … skipping cycle» в логе. Найден: **dual-edit-tester** — стенд приехал уже замороженным; форензика server-vault (UU, MERGE_HEAD, ls-files -u) + доказанная НЕ-recovery (merge --abort → следующий цикл снова конфликтует). **IDEMPOTENCY / ДУБЛИРОВАНИЕ** - *Body written twice* (reconcile-doubling) — проявление: .md в git содержит тело дважды (221 байт, стабильно 2×, не растёт). Найден: **editor-content QA** git-clone diff + idle re-clone monitor; verifier дотрассировал через `git log` 0→1→2 по последовательным sync-коммитам и поправил premise («в редакторе одна копия» — на деле тоже две). - *Orphan «Untitled chat»* (state-litter) — проявление: каждый упавший send плодит новый chat + одинокую user-строку без assistant. Найден: **ai-chat-ui QA** через psql ai_chats/ai_chat_messages + рендер истории. **ROUNDTRIP-FIDELITY** - *Callout type → [!info]* — проявление: `[!tip]/[!note]/[!important]/[!caution]/[!question]` после импорта/ре-сериализации схлопываются в `[!info]`; выживают только info/warning/danger/success. Найден: **git-roundtrip-tester** — авторский .md с 9 типами → push → wait ~20s → fetch/reset → `grep -o` дал 1:1 маппинг; verifier воспроизвёл независимо. **SILENT-FAILURE / MISLEADING-ERROR / DIAGNOSABILITY** - *AI-chat «Please try again»* — проявление: детерминированный 500 на 100% сендов, но баннер советует «попробуйте снова», реальная причина (provider/build) скрыта. Найден: **ai-chat-ui QA** response-listener (500 `{"error":"Internal server error"}`) + трассировка post-hijack в исходниках; verifier подтвердил по отсутствию `; charset=utf-8` на 500 (отпечаток raw-socket write). - *mcp stale build* (env, root-cause всех 500) — найден тем же агентом через детерминированный ~0.11s тайминг (нет round-trip к провайдеру) + DB + node require.resolve. **CONTENTION / TRANSIENT** - *git push 503 / remote hung up* — проявление: push отбивается 503 пока docmost в середине sync-цикла + non-ff из-за автокоммитов docmost. Найден: **git-roundtrip-tester**; verifier воспроизвёл двумя путями (2 параллельных clone; 6 быстрых push подряд → 503 на 4/6). **RENDERING / CONSOLE-NOISE** - *flushSync на cold-mount редактора* — **recon**, console-listener на прямом goto (4 ошибки), контроль: in-app навигация = 0. - *flushSync на reload страницы с таблицей* — **editor-content QA**, console-listener + контроль plain-doc (0 ошибок) изолировал причину на таблицу. - *atomFamily deprecated* — **tree-nav QA**, console-capture + grep исходника jotai; verifier уточнил: только dev-build, once-per-module. - *Share-spotlight stale render* — **share-search QA**, frame-by-frame ~12ms poll; verifier ПОВЫСИЛ speculative→verified, но поправил атрибуцию (не keepPreviousData, а 300ms debounce). **ORACLE-CONTAMINATION (процессная находка, не баг продукта)** - *Виртуализованное дерево как невалидный оракул* — **tree-nav QA** сам дисконфёрмил «пропавшие страницы» через пагинацию `/pages/sidebar-pages` (360 root pages) + grep useVirtualizer. Записан как урок для скилла. **ENV / TOOLING** - Playwright 1.60 ждёт chromium-1223, есть только 1148 (**recon**); login-race до установки cookie (**recon**); auth-throttler 10/min делит бакет с обычными SPA-вызовами → 429 (**git-roundtrip-tester**). Все корректно помечены env-limitation. --- ## 3b. Кто что нашёл (finding → агент → класс → вердикт) | Finding | Агент | Класс | Вердикт | |---|---|---|---| | Playwright 1223 vs 1148 | recon | tooling-mismatch | env (корректно) | | Login-race до cookie | recon | async-timing | env/tooling pitfall | | flushSync cold-mount редактора | recon | render console-noise | **verified** | | Callout strips body | editor-content | silent-data-loss | **verified (HIGH)** | | Body written twice | editor-content | serialization/reconcile dup | **verified** (механизм переписан) | | flushSync на таблице | editor-content | render console-error | **verified** | | ``` fence в list-item | editor-content | input-shortcut | **speculative — FP** (list-причина опровергнута) | | Virtualized tree oracle | tree-nav | oracle-contamination | self-caught FP-hazard (корректно) | | Restore confirm-modal timing | tree-nav | interaction-timing | self-caught FP-hazard (корректно) | | atomFamily deprecated | tree-nav | console-noise | **verified** | | Share-spotlight stale | share-search | rendering | **verified** (↑ из speculative) | | Ask-AI widget не тестируем | share-search | silent-failure (env) | env (корректно) | | AI-chat misleading error | ai-chat-ui | misleading-error | **verified** | | Orphan «Untitled chat» | ai-chat-ui | idempotency/litter | **verified** | | @docmost/mcp stale build | ai-chat-ui | build/packaging (env) | env root-cause (корректно) | | Callout type → [!info] | git-roundtrip | roundtrip-fidelity | **verified** | | git push 503 | git-roundtrip | contention/transient | **verified** | | Loss-on-fast-close | git-roundtrip | collab-flush-race | **verified** (↑ из speculative) | | Auth throttler 429 | git-roundtrip | rate-limit (env) | env (корректно) | | Same-line dual-edit wedge | dual-edit | silent-wedge/availability | **verified (HIGH)** | | Wedged-vault misleading git-err | dual-edit | silent-failure/diagnosability | **speculative — FP** (тезис опровергнут) | --- ## 4. ФОЛС-ПОЗИТИВЫ — кто и насколько (ключевой раздел) Считаем по продуктовым находкам, прошедшим через verifier (env-ограничения и self-caught FP-hazard не штрафуем — это корректная классификация). | Агент | Продуктовых находок | Подтверждено | Убито verifier (FP) | Доля FP | |---|---|---|---|---| | recon | 1 (+2 env) | 1 | 0 | 0% | | editor-content QA | 4 | 3 | 1 | **25%** | | tree-nav QA | 1 (+2 self-caught) | 1 | 0 | 0% (сам ловит свои FP) | | share-search QA | 1 (+1 env) | 1 | 0 | 0% (даже ↑) | | ai-chat-ui QA | 2 (+1 env) | 2 | 0 | 0% | | git-roundtrip-tester | 3 (+1 env) | 3 | 0 | 0% (одна ↑) | | dual-edit-tester | 2 | 1 | 1 | **50%** | **Системно фолс-позитивят:** - **dual-edit-tester — 50% (1/2)**, и именно на «громком» классе. Реальный wedge он нашёл блестяще, но второй финдинг («misleading git-error маскирует сломанное серверное дерево, rebase+retry НЕ помогает») verifier опроверг: «fetch first» — это КОРРЕКТНАЯ git-семантика, remote реально опережает клиента из-за непрерывных автокоммитов docmost; rebase+retry СРАБОТАЛ. Корень FP — наблюдение в idle-окне («origin/main стабилен 3 фетча») было интерпретировано как «дерево сломано», хотя под нагрузкой tip двигался ~раз/1-2s. Класс ошибки: **over-attribution симптома к худшему корню при недостаточной нагрузке во время наблюдения**. - **editor-content QA — 25% (1/4)** на input-shortcut классе: склеил два независимых явления («fence ломается в list-item» — на деле ломается и top-level из-за пропущенного пробела после `js`; list-причина опровергнута grep'ом по волту). Класс ошибки: **conflation двух феноменов + причинно-следственная гипотеза без контроля**. При этом его data-loss/duplication находки безупречны. **Надёжные агенты:** - **ai-chat-ui QA** и **git-roundtrip-tester** — 0% FP при глубине (DB+тайминг+исходники / git-export-оракул). Самые доверенные. - **tree-nav QA** — образец: дважды САМ дисконфёрмил свои потенциальные high-sev FP до отправки (виртуализация дерева; пропуск клика в confirm-modal). Его дисциплина — модель поведения, которую стоит зашить в charter всех агентов. - **share-search QA** и **recon** — чисто. **Важно про verifier:** он не только убивает FP (2), но и СПАСАЕТ недооценённое (fast-close и share-stale подняты speculative→verified) и ЧИНИТ механизм у верных находок (body-dup, share-stale-атрибуция). То есть verifier работает в обе стороны — и анти-галлюцинация, и анти-недооценка. --- ## 5. Где скилл сработал/провалился **Сработал именно ПРОЦЕСС (а не везение):** - **git-export как out-of-band ground-truth** — поймал то, что UI скрывает: callout-strip (пустое тело), body-duplication (221 байт ×2), callout-type-flatten, 59-байтные frontmatter-only при fast-close. Это — главный оракул для git-sync фичи и он окупился многократно. - **TIMED innerText sampling на холостом ходу** — единственный способ увидеть «нода исчезает между t+3 и t+5s без действий». Обычный snapshot-after-action этого не ловит. - **Контрольные документы (controls)** — Toggle vs Callout изолировал data-loss на конкретный узел; plain-doc vs table-doc изолировал flushSync на таблицу; top-level vs list fence развалил ложную гипотезу. Контроль — то, что отличает находку от догадки. - **Серверная форензика волта** (status/MERGE_HEAD/ls-files -u/лог) — поймала флагманский wedge, невидимый ни в UI, ни в API. - **Verifier-проход** — убил 2 FP, которые звучали как high/medium, и докрутил механизмы. - **Глубокая триангуляция тайминг→DB→исходники→build-probe** (ai-chat) — довела симптом «try again» до настоящего root-cause (stale mcp build), а не остановилась на баннере. **Чуть не упустил / провалился:** - **Виртуализованное дерево едва не дало false high «созданные страницы пропали»** — спас только инстинкт триангулировать DOM-счёт с бэкендом. Если бы агент доверился DOM-оракулу, ушёл бы ложный data-loss. - **dual-edit «misleading error»** прошёл слайс как verified и был дисконфёрмлен только verifier'ом — без независимого прохода ушёл бы ложный medium. - **Login-429 / throttler** многократно ломал браузерный логин и заставлял агентов городить cookie-инжект/curl-логин — потерянное время и риск, что слабый агент спишет это на «приложение сломано». - **Атрибуция причин** — слабое место: share-stale (keepPreviousData), body-dup («одна копия в редакторе»), fence-list — во всех трёх premise/механизм был неверен, хотя артефакт (кроме fence) реален. --- ## 6. Предложения по улучшению скилла **Оракулы:** 1. Зашить правило «**никогда не считать DOM-строки виртуализованного списка как presence/loss-оракул**» — при подозрении на пропажу всегда триангулировать с бэкендом (пагинация API) или git-clone. Это чуть не дало false high. 2. Для любой save/round-trip фичи сделать **git-export (или DB) обязательным out-of-band оракулом** — UI-снапшот недостаточен; самые тяжёлые баги видны только в .md/в DB. 3. Добавить **idle-watch оракул**: после ввода контента сэмплировать innerText на холостом ходу (t+1/3/5/8s) — целый класс silent-data-loss виден только так. 4. Требовать **контрольный документ** для любого «X ломается»: тот же сценарий без подозреваемого фактора. Без контроля находка = гипотеза. **Charters / дисциплина агентов:** 5. Кодифицировать «**tree-nav discipline**» во все charters: прежде чем репортить loss/ghost — доказать, что мутация реально дошла до бэкенда (проверить API), а наблюдение сделано НЕ в idle-окне под нагрузкой sync. 6. Для git-sync charters явно предупредить: «remote main двигается сам каждые 1-2s из-за автокоммитов docmost; `fetch first`-rejection — НОРМА, а не маскировка». Это убрало бы 50% FP dual-edit-тестера. 7. Запретить **conflation**: одна находка = один воспроизводимый феномен; если два симптома, развести их и дать каждому свой контроль (кейс fence). **Verifier-гейты:** 8. Любой финдинг с severity≥medium, у которого корень = «сломан сервер/масштабное состояние», обязан пройти **повторение под нагрузкой** (а не в idle-окне) — именно это развалило dual-edit FP. 9. Verifier должен **явно проверять premise/механизм**, а не только наличие артефакта — у 3 находок артефакт верен, объяснение нет; в отчёт должен идти исправленный механизм. 10. Verifier должен уметь **повышать** (speculative→verified), а не только убивать — иначе fast-close и share-stale ушли бы недооценёнными. **Окружение / дедуп:** 11. **Решить login-429 централизованно** один раз на прогон (общий curl-минтинг authToken + reuse storage_state), а не заставлять каждый слайс изобретать обход — экономия времени и снятие риска ложного «приложение не аутентифицирует». 12. **Дедуп console-noise**: flushSync (cold-mount + table) и atomFamily всплыли у трёх агентов независимо — добавить общий «known-console-noise» реестр, чтобы агенты не репортили одно и то же трижды как новое. 13. Зафиксировать в окружении **executable_path к chromium-1148** как дефолт, чтобы recon не падал на старте каждого прогона. --- ✅ **Мета-фидбэк:** этот прогон НЕ завис — добавленный per-agent timeout (9 мин) + timebox в verify сработали (в прогоне 1 один verifier висел 5.5ч). Рекомендация в скилл подтверждена практикой. 🤖 web-test-orchestrator (process-trace)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: vvzvlad/gitmost#236