WEB-676 · Дефект · Инфраструктура · web
P1: очередь индексации — массовая переиндексация обгоняет загрузки пользователей (часы ожидания), resume без предела (1975 попыток)
На проверке
P1 · важно
ведёт: —
эпик: WEB-626
Суть
Найдено 21.09.2026 при работе над ёмкостью (WEB-626), волны 4547/4551/4554/4555.
ФАКТЫ ПО ДАННЫМ БОЯ (SELECT-only): за 30 дней 20 настоящих загрузок пользователей (metadata.uploadPriority=user). Типичная: ожидание 37 с + работа 6 с ≈ 40 с. Но 4 из 20 ждали 9 543 / 11 458 / 11 467 / 38 462 с (до 10,7 ч). Две загрузки поставлены 07.09 20:07Z; в 20:14–20:29Z стартовали 50 строк reason=reindex:web-99-chunk-quarantine (все 50 отравились); пользовательские стартовали лишь 23:18Z после ручного revive-poisoned-source. Одна загрузка: 1975 попыток / 1975 resume (цикл). Одна: 10,7 ч при почти пустой очереди → poisoned.
ПРИЧИНА ПО КОДУ (cc278e18, волна 4555): обычная выборка очереди ИМЕЕТ приоритет пользователя — ORDER BY CASE user-priority THEN 0 ELSE 1 END, createdAt, id (src/lib/sources/sourceReadGateway.ts:1228-1235). НО scripts/reindex-quarantined-chunks.ts:1474-1503 подаёт воркеру каждый sourceId НАПРЯМУЮ и общую сортировку обходит — при одной полосе это отдаёт полосу переиндексации на часы. Retry: 3 попытки, backoff 60 с×2^(n-1), cap 1 ч (src/lib/ingest/processingState.ts:74-80,107-113,498-546). Resume БЕЗ cap: возвращает строку в pending, attempts растёт при каждом claim; счётчик отравления ловит только повтор одного portion (:83-90,565-659) — меняющиеся signatures его обходят. Причины штормов отравления по коду: провайдер/сеть/битый ответ (src/lib/rag/embeddings.ts:88-120,323-343), биллинг/кошелёк (src/lib/billing/meteredVendorCall.ts:435-539,619-660), перерасход 195 с, прочие ошибки (sourceIndexingQueue.ts:1311-1343).
ПРЕДЛОЖЕНИЕ (4555, proposal.md), без изменения ленивости, полос и бюджетов, без миграций:
(а) admission guard для прямого reindex с sourceId: перед claim атомарно проверить наличие eligible pending user-upload (тот же предикат, что у обычной выборки); при наличии — deferred, пасс завершается, полоса освобождается; флаг из reindex-quarantined-chunks (по умолчанию ВКЛ);
(б) счётчик resumeNoProgress с cap 5 подряд без роста completedChunks → poisoned с сохранением checkpoint и poisonedReason='resume-no-progress'; прогресс сбрасывает счётчик.
Тесты: pending user + pending reindex → прямой reindex откладывается; без user — проходит; обычная выборка сохраняет порядок; прогресс сбрасывает счётчик; 5 разных signatures без прогресса → poisoned с checkpoint; третий одинаковый — по-прежнему poisoned; прогресс после 4 пауз продолжает без роста attempts.
СТАТУС: патч с тестами пишет волна 4556 (Нео) на cc278e18; сборка и посадка — на A2 после лестницы ёмкости, одной посадкой с потолком потоков в настройке (4526). Владелец 21.09 21:08Z дал дефолтный GO.
ДОКАЗАТЕЛЬСТВА: a1nc:/home/ubuntu/waves/4547PRODREALUPLOADS-evidence/, 4551PRODUPLOADTAIL-evidence/, 4554RECHECKREALUPLOADS-evidence/; neo:~/waves/4555QUEUEPRIORITYBYCODE-evidence/ (order.md, retry-resume.md, storm.md, proposal.md). Брифы: nc-ops-scripts/waves-20260921/4547-, 4551-, 4554-, 4555-, 4556-*.md. Память координатора: reindex-cli-bypasses-user-priority-no-resume-cap.md.
## Актуализация координатора 2026-09-26 12:01Z [refresh-20260926-roles-capacity]
Правила обогащения: WEB-449.
Разделены source acceptance и доставка: историческая независимая5045 GO для общего563db146 сохраняется в своём объёме (PG17/17+generic1, targeted291/291). Новая интеграция5058 со связанной CPU/worker веткой закончилась NO-GO без артефакта/bundle. Новые Linux fixes не приняты; успешные source tests не означают новую посадку. Общий оставшийся шаг — восстановление сборки координатором, затем полная проверка пакета и отдельная посадочная приёмка. Этот тикет не объявляется заново завершённым на основании5058.
КАРТА ДОКУМЕНТОВ / доказательства: M1:/Users/poolpooly/waves/5045MERGEDCANDIDATEINDEPENDENT-REPORT.md; A2:/home/ubuntu/waves/5058INTEGRATEDLINUXSTANDBUILD-REPORT.md; A2:/home/ubuntu/waves/5058INTEGRATEDLINUXSTANDBUILD-evidence/SHA256SUMS; ноутбук:/Users/annakorin/nc-ops-scripts/material-5058/5056NEXTBOOTSTRAPCOMPATIBILITYCOMPLETION.bundle
Как воспроизвести
Поставить в очередь user-загрузку, затем запустить scripts/reindex-quarantined-chunks.ts на 50 источниках при одной полосе: загрузка стартует после всех 50 (данные 07.09: 20:07Z → 23:18Z).
Чем закрывается (приёмка)
Прямой reindex откладывается при наличии pending user-загрузки (тест); resume без прогресса ограничен 5 с сохранением checkpoint (тест); на бою после посадки: ни одна user-загрузка за 7 дней не ждёт >600 с при активной переиндексации; ленивость (1 полоса, бюджеты) не изменена.
Доказательства
4547/4551/4554 (данные), 4555 (код, proposal.md), 4556 (патч)
Лента
2026-09-21T21:30:56.073Z · coordinator[21.09 21:30Z координатор] [волна 4556 GO (Нео, манифест 6/6, маркер 21:30Z)] ПАТЧ НАПИСАН на cc278e18 (git apply --check на чистой копии RC 0), 7 файлов: scripts/reindex-quarantined-chunks.ts (+ тест), src/lib/sources/sourceReadGateway.ts, src/lib/ingest/sourceIndexingQueue.ts, src/lib/ingest/processingState.ts, тесты sourceIndexingResumeHonesty.test.ts и sourceIndexingAdmissionGuard.postgres.integration.test.ts. (а) Admission guard: включён по умолчанию в reindex-quarantined-chunks, opt-out --no-reindex-admission-guard; проверка наличия pending user-upload выполняется ВНУТРИ атомарного claim SQL; при наличии — прямой reindex возвращает deferred (не ошибка, target не меняется); обычный user-first ORDER BY сохранён. (б) Resume cap: в state только processing.indexing.resumeNoProgress (без миграций); 5-й подряд resume без роста checkpoint → poisoned с poisonedReason=resume-no-progress и сохранённым checkpoint; старый poison после 3-го одинакового portion сохранён; прогресс сбрасывает счётчик и attempts. Тесты 7 написаны, НЕ запущены (на Нео нет node_modules) — запуск на A2 при сборке. Патч и доказательства довезены на Мак и A2 (4558-material) с совпавшим манифестом. Дальше: независимая приёмка патча по коду (4557, Нео), затем сборка на A2 после лестницы ёмкости (патч 4556 + потолок в env 4526 + жёсткий выход защиты 4534) и одна посадка на бой. Доказательства: neo:~/waves/4556QUEUEGUARDRESUMECAP-evidence/ (guard.md, resume-cap.md, tests.md, diff.patch, risk.md, material-sha.md); бриф waves-20260921/4556-queue-guard-and-resume-cap-patch-brief.md.
2026-09-21T22:06:37.268Z · coordinator[21.09 22:06Z координатор] [волна 4557 NO-GO (Нео, манифест 5/5, 21:51Z) — враждебная приёмка патча 4556] 49 hunks. Найдено: GUARD_ATOMIC=НЕТ — между постановкой user-upload и admission прямого reindex есть окно гонки (проверка и claim не сериализованы одним lock/изоляцией); GUARD_PREDICATE_SHARED=ДА (предикат eligibility общий с обычной выборкой — хорошо); REINDEX_STARVATION_POSSIBLE=ДА — «вечно pending» user-upload (backoff/paused/не берётся) блокирует переиндексацию навсегда, у deferred нет верхней границы; ORDER_BY_UNTOUCHED=НЕТ — патч изменил обычную выборку, чего делать нельзя; FALSE_POISON_POSSIBLE=ДА — enrichment-прогресс не считается прогрессом, честный документ может быть отравлен cap'ом; тесты покрывают ключевое частично. Рецепт: сериализовать постановку и admission одним lock/изоляцией с retry; deferred — durable, fair, retryable с границей; enrichment исключить из cap или добавить маркер прогресса; ORDER BY вернуть байт-в-байт. РЕШЕНИЕ: итерация 2 — волна 4560 (Нео) по этому списку; на бой поедет только патч, прошедший независимую приёмку. Доказательства: neo:~/waves/4557ACCEPTQUEUEPATCH-evidence/ (hunks.md, guard-review.md, cap-review.md, risk-review.md, material-sha.md).
2026-09-21T22:40:08.988Z · coordinator[21.09 22:40Z координатор] [волна 4560 GO (Нео, 22:39Z) — патч очереди, итерация 2] Все 7 замечаний приёмки 4557 закрыты: (1) атомарность — transaction-scoped pg_advisory_xact_lock по ключу source-indexing:user-upload-admission; тот же ключ берут постановка user-upload (sourceWriter/backgroundExtraction) и guarded claim, проверка и claim в одной транзакции; (2) обычный ORDER BY возвращён байт-в-байт (ORDER_BY_UNTOUCHED=ДА); (3) starvation — deferred ограничен тремя подряд (DEFERRED_BOUND=3), затем reindex проходит с логом; eligibility — общий предикат; (4) ложное отравление — прогресс = рост checkpoint ИЛИ маркер processing.indexing.enrichmentProgressAt (без миграции); (5) тесты дописаны (6, не запущены — нет node_modules; запуск при сборке на A2); git apply --check на чистом cc278e18 RC 0. Патч и доказательства довезены на Мак и A2 (4558-material/4560…) с совпавшим манифестом. Дальше: враждебная приёмка итерации 2 (4564, Нео), затем сборка на A2 после лестницы (4560 + потолок в env 4526 + жёсткий выход защиты 4534) и одна посадка на бой. Доказательства: neo:~/waves/4560QUEUEPATCHITER2-evidence/ (fixes.md, diff.patch, tests.md, risk.md, material-sha.md).
2026-09-21T23:07:07.524Z · coordinator[21.09 23:07Z координатор] [волна 4564 NO-GO (Нео, доказательства 5/5, 23:0xZ) — враждебная приёмка итерации 2 (4560), 74 hunks] Закрыто по существу: GUARD_ATOMIC=ДА (claimProtectedSourceForIndexing открывает транзакцию, берёт pg_advisory_xact_lock, затем claim SQL в той же транзакции; в CTE pending_user_upload проверка и claim в одном statement — окна между ними нет); GUARD_PREDICATE_SHARED=ДА (sourceIndexingQueueSql({}), тот же default pending lane, что у обычной выборки); REINDEX_STARVATION_POSSIBLE=НЕТ (reindexDeferredCount в metadata, переживает requeue/перезапуск, после 3 — reindex проходит); ORDER_BY_UNTOUCHED=ДА; FALSE_POISON_POSSIBLE=НЕТ (enrichmentProgressAt). Осталось: ALL_ENQUEUE_PATHS_LOCKED=НЕТ — lock взят в writeSource, writeDeferredSource, unified upload, /api/ingest, messenger, resumable complete и markSourcePendingExtraction, но НЕ в extractionJobQueue.finishClaimedExtractionJob (src/lib/ingest/extractionJobQueue.ts:387-460; pending публикуется на :445-448) и не в legacy backgroundExtraction.finishExtraction (:580-640) → guard может взять snapshot до commit extraction и claim-нуть reindex, а следом появится user-priority pending — ровно путь «deferred extraction → backgroundExtraction». LOCK_SLOWS_UPLOADS=ДА — участок удержания lock надо оценить и сузить. Тесты покрывают ключевое частично (нужен race-тест завершения extraction). → итерация 3, волна 4565 (Нео): lock в транзакции завершения extraction (оба пути), минимальный участок удержания с оценкой худшего случая, race-тесты. Доказательства: neo:~/waves/4564ACCEPTQUEUEPATCHITER2-evidence/ (guard-review.md, cap-review.md, risk-review.md, hunks.md, material-sha.md).
2026-09-21T23:20:23.892Z · coordinator[21.09 23:20Z координатор] [волна 4565 GO (Нео, манифест 6/6, 23:2xZ) — патч очереди, итерация 3] Закрыто последнее замечание 4564: terminal completion в extractionJobQueue.finishClaimedExtractionJob (:450-463) и legacy backgroundExtraction.finishExtraction (:631-645) теперь берут общий lockSourceIndexingAdmission непосредственно перед атомарной публикацией content/contentHash + pending metadata; ALL_ENQUEUE_PATHS_LOCKED=ДА — таблица шести путей (writeSource :453-457, writeDeferredSource :224-231, markSourcePendingExtraction :141-161, оба terminal completion, прямой reindex admission в sourceReadGateway :1600-1622) на одном ключе pg_advisory_xact_lock(hashtextextended('source-indexing:user-upload-admission',4560)). Цена lock: держится только на коротком DB-участке публикации Source (create/update + commit); парсинг, storage и чанки — вне lock; guard-транзакция воркера — один claim SQL с CTE; консервативная статическая оценка худшего случая 250 мс × N одновременных публикаций (не измерение); наблюдать advisory-lock wait p95/p99 после посадки. ORDER BY нетронут; 2 race-теста добавлены (завершение extraction параллельно с admission; legacy путь); git apply --check RC 0; 14 файлов итого (итерации 2+3, полный diff.patch 4565). Патч на Маке и A2 (4558-material/4565…). Дальше: враждебная приёмка итерации 3 (4566, Нео); при GO — сборка 4558 на A2 после лестницы (cc278e18 + 4525 + 4526 + hard-exit 4534 + патч) и одна посадка. Доказательства: neo:~/waves/4565QUEUEPATCHITER3-evidence/ (lock-paths.md, lock-cost.md, fixes.md, tests.md, diff.patch, material-sha.md).
2026-09-21T23:49:46.590Z · coordinator[21.09 23:49Z координатор] [волна 4566 NO-GO (Нео, манифест 6/6, 23:36Z) — финальная враждебная приёмка итерации 3, 78 hunks / 14 файлов] Подтверждено: GUARD_ATOMIC=ДА, предикат общий, starvation НЕТ, ORDER BY нетронут, ложное отравление НЕТ, lock не держится на storage/parsing, регрессий против итерации 2 нет. НЕ пройдено по строгому критерию: ALL_ENQUEUE_PATHS_LOCKED=НЕТ — заперты writeSource, writeDeferredSource, markSourcePendingExtraction, finishClaimedExtractionJob, finishExtraction и guarded claim, но БЕЗ lock публикуют pending служебные писатели: queue pause, time-budget revive, missing-chunk cron, requeueSource, revive-poisoned-source, document edit, инструменты redownload/repair/chunk-revision/unpoison/reindex; LOCK_WAIT_TIMEOUT=нет (глобальный ключ сериализует публикации двух копий приложения без верхней границы; 250 мс×N — статическая оценка). SHIP_TO_PROD=НЕТ. РЕШЕНИЕ КООРДИНАТОРА: не запирать каждый служебный писатель (растущая поверхность и цена сериализации), а сделать guard точным для пользовательских загрузок (их пути заперты все) и best-effort для служебных ре-публикаций с ДОКАЗАННО ограниченным ущербом (≤1 claim переиндексации до обслуживания user-строки — обычный ORDER BY user-first и одна полоса); requeueSource/revive-poisoned-source, ставящие именно пользовательские строки, запереть (дёшево); добавить lock_timeout с безопасным откатом (загрузка никогда не виснет: при таймауте публикация без ожидания guard, guard при таймауте пропускает проверку с логом admission-lock-timeout); документация docs/operator/SOURCE-INDEXING-QUEUE-PRIORITY.md. → итерация 4, волна 4567 (Нео); приёмка 4568 с этими критериями. Доказательства: neo:~/waves/4566ACCEPTQUEUEPATCHITER3-evidence/ (guard-review.md, cap-review.md, risk-review.md, hunks.md, material-sha.md).
2026-09-22T00:20:20.763Z · coordinator[22.09 00:20Z координатор] [волна 4567 GO (Нео, манифест 6/6, 00:1xZ) — патч очереди, итерация 4] По критериям координатора: lock_timeout=2000 мс (SET LOCAL) в guard-транзакции воркера и в транзакциях публикации; при SQLSTATE 55P03 — лог admission-lock-timeout, новая транзакция и повтор той же публикации/claim БЕЗ ожидания advisory guard (загрузка никогда не виснет и не падает из-за lock); заперты дополнительно requeueSource и revive-poisoned-source (ставят именно пользовательские строки; WRITERS_LOCKED=2), 10 служебных писателей (pause, revive по бюджету, cron недостающих кусков, document edit, инструменты ремонта) — best-effort с доказательством ограниченного ущерба: ≤1 claim переиндексации до обслуживания user-строки (обычный ORDER BY user-first, одна полоса; худшая задержка = один reindex-документ, по данным боя ~1,4 с медиана, до 31 с большой) — bounded-harm.md; ORDER BY нетронут; документация docs/operator/SOURCE-INDEXING-QUEUE-PRIORITY.md; 3 новых теста (lock_timeout-откат публикации, guard при таймауте, гонка со служебным писателем ≤1 claim) — не запущены; полный diff (ит. 2+3+4) 25 файлов, git apply --check на чистом cc278e18 RC 0. Патч на Маке и A2 (4558-material/4567…). Дальше: финальная приёмка 4568 (Нео) — особо: безопасность отката по таймауту (нет двойной публикации/claim, нет потери pending), область действия lock_timeout, доказательство ≤1 claim для каждого служебного писателя; при GO — сборка 4558 на A2 после лестницы. Доказательства: neo:~/waves/4567QUEUEPATCHITER4-evidence/ (lock-timeout.md, bounded-harm.md, writers.md, tests.md, diff.patch, material-sha.md).
2026-09-22T00:34:26.350Z · coordinator[22.09 00:34Z координатор] [волна 4568 NO-GO (Нео, 00:3xZ) — приёмка итерации 4; РАЗВОРОТ ПОДХОДА] Итерация 4 сделала хуже: SET LOCAL lock_timeout=2000ms действует на ВСЕ блокировки транзакции (row/table/unique/advisory), а withAdmissionLockTimeoutFallback распознаёт ЛЮБОЙ 55P03 и повторяет публикацию/claim второй транзакцией без guard — таймаут строчного lock в finishClaimedExtractionJob (ExtractionJob.updateMany до advisory, Source.update после) залогируется как admission-lock-timeout и повторит body+pending без guard (TIMEOUT_FALLBACK_SAFE=НЕТ, LOCK_TIMEOUT_SCOPE=all locks); writeDeferredSource и markSourcePendingExtraction превращены из blocking lock в try-lock с игнорированием false (REGRESSION_VS_ITER3=ДА); MAX_HARM_CLAIMS=1 не доказан; FALSE_POISON_POSSIBLE=ДА (stale-running/lost-checkpoint случаи). Три итерации admission-guard с глобальным advisory lock (2, 3, 4) провалили приёмку, поверхность и риск растут. РЕШЕНИЕ КООРДИНАТОРА — вернуться к сути дефекта (4551/4555): приоритет user-загрузок в обычной выборке УЖЕ есть; проблема в том, что scripts/reindex-quarantined-chunks.ts подаёт sourceId воркеру НАПРЯМУЮ, обходя очередь. Итерация 5 (волна 4572, Нео): без замков и таймаутов — CLI переиндексации ставит источники в pending с reason=reindex и выходит, обработку делает штатный воркер в обычном порядке (user-first); явный флаг --direct (по умолчанию выкл) сохраняет старое поведение с предупреждением; cap на resume — ровно из принятой части итерации 3; ожидаемо ≤ 8 файлов. Доказательства 4568: neo:~/waves/4568ACCEPTQUEUEPATCHITER4-evidence/ (guard-review.md, cap-review.md, risk-review.md, hunks.md).
2026-09-22T01:02:21.235Z · coordinator[22.09 01:02Z координатор] [волна 4572 GO (Нео, манифест запечатан, 00:5xZ) — итерация 5, РАЗВОРОТ: без замков] scripts/reindex-quarantined-chunks.ts по умолчанию ставит источники в pending с reason=reindex:* (checkpoint сохраняется) и НЕ вызывает воркер напрямую — обработку делает штатный воркер в обычном порядке; --direct оставлен явным escape hatch с предупреждением «обходит приоритет пользователей». Обычная выборка сохраняет исходный ORDER BY байт-в-байт: pending user-строка получает CASE=0, reindex-строка без user-маркера — CASE=1 (order-proof.md). Cap на resume перенесён только из принятой части итерации 3: resumeNoProgress, предел 5, enrichmentProgressAt, сохранение checkpoint. Admission guards, advisory lock, lock_timeout, try-lock — в diff отсутствуют (grep пуст). 8 файлов, тесты написаны (не запущены), git apply --check на чистом cc278e18 RC 0. Патч на Маке и A2 (4558-material/4572…). Дальше: финальная враждебная приёмка 4574 (Нео) — все ли прямые подачи sourceId переведены, не зависают ли reindex-строки, оценка максимального ожидания user-строки при 1 полосе, регрессии; при GO — сборка 4558 на A2 (после лестниц) и одна посадка. Доказательства: neo:~/waves/4572QUEUEPATCHITER5PIVOT-evidence/ (reindex-enqueue.md, order-proof.md, resume-cap.md, tests.md, diff.patch, material-sha.md).
2026-09-22T01:26:04.964Z · coordinator[22.09 01:26Z координатор] ## 4574 (Нео, приёмка итерации 5 «без замков», NO-GO, манифест 5/5) — суть подтверждена, четыре замечания
Подтверждено: `USER_FIRST_PROVEN=ДА` (ORDER BY нетронут, user-строки первыми), `REINDEX_ROWS_ELIGIBLE=ДА`
(поставленная reindex-строка берётся обычной выборкой), `LOCKS_IN_DIFF=0`, `RESUME_CAP_AS_ITER3=ДА`,
`REGRESSION_VS_BASE=НЕТ`. Оценка ожидания user-строки при 1 полосе: максимум один уже захваченный source
(до 120 с + бюджет порции + 30 с), а не 25× как раньше.
Почему NO-GO (для нулевых агентов — это и есть остаток дефекта):
1. Постановка в очередь через `buildSourceIndexingPendingMetadata` (`processingState.ts:373-395`) **теряет
`checkpoint`/`resumes`/`resumeNoProgress`** — воркер может повторно купить уже сделанную работу.
2. Прямых подач воркеру мимо выборки ШЕСТЬ, переведена одна: `repair-live-docs-without-chunks.ts:607-616`,
cron `source-indexing/route.ts:70-78` (`sourceId`), `process-source-indexing-queue.ts` (`--source`),
`reindex-drive-sources.ts:593-608` (`processDocument`).
3. Тесты написаны, но не запускались. Риск stale-running/lost-checkpoint (4568 cap-review) остаётся.
Дальше: 4575 (итерация 6, Нео) — сохранить checkpoint при постановке, таблица шести подач (массовые →
очередь; одиночные только при «ровно один id + предупреждение в журнале + не используется массовыми»),
тесты запустить. Подход не меняется. Доказательства: `neo:~/waves/4574ACCEPTQUEUEPATCHITER5-evidence/`.
2026-09-22T01:59:27.859Z · coordinator[22.09 01:59Z координатор] ## 4575 (Нео, итерация 6, GO, манифест 8/8) — закрыты четыре замечания 4574; на независимой приёмке 4576
- Checkpoint: `preserveResume` переносит `checkpoint`/`resumes`/`resumeNoProgress` в admission-путях reindex/repair (`CHECKPOINT_PRESERVED=ДА`, тест).
- Шесть прямых подач воркеру (таблица `callers-table.md`): три массовых ПЕРЕВЕДЕНЫ на `pending` с инструментальным `reason`
(`reindex-quarantined-chunks`, `repair-live-docs-without-chunks` → `repair:web-99-live-docs-without-chunks`,
`reindex-drive-sources` → `reindex:drive-sources`); три одиночных оставлены адресными с предупреждением в журнале
(cron `sourceId`, CLI `--source`, inline user-ingest `sourceWriter.ts:480-489`) — по правилу «ровно один id + warning + не используется массовыми».
- `USER_FIRST_PROVEN=ДА`, `ORDER_BY_UNTOUCHED=ДА`, `LOCKS_IN_DIFF=0`, `RESUME_CAP=5`, `TESTS_RUN=3/3 RC=0`
(штатный `tsx` в чистом архиве недоступен — гоняли через Node resolver, команда в `tests.md`), 12 файлов, apply RC 0.
- Патч: `neo:~/waves/4575QUEUEPATCHITER6CALLERS-evidence/diff.patch` (sha `07f09e6fbe639c44…`), копии на Маке
(`waves-20260921/4575-evidence/`) и A2 (`4558-material/4575-queue-patch-iter6.patch`).
- Дальше: 4576 (Нео) — враждебная приёмка: поля resume по коду воркера, ветки трёх переведённых, уместность
предупреждения на пользовательском inline-пути, воспроизведение тестов, команда для A2. При GO → сборка 4558.
2026-09-22T02:18:43.495Z · coordinator[22.09 02:18Z координатор] ## 4576 (Нео, приёмка итерации 6, NO-GO, манифест 5/5) — два точечных блокера, суть цела
Подтверждено: `MASS_CALLERS_STILL_DIRECT=0` (три массовых инструмента больше не подают sourceId воркеру), одиночные — по одному id доказано,
`USER_FIRST_PROVEN=ДА`, `RESUME_CAP_AS_ITER3=ДА` (значение 5 и chunk cap), `LOCKS_IN_DIFF=0`, `REGRESSION_VS_BASE=НЕТ`, apply RC 0.
Оценка ожидания user-строки при 1 полосе: максимум один уже захваченный source ≈ 120 с прогон + 45 с порция + 30 с grace ≈ 3 мин 15 с.
Блокеры:
1. `scripts/reindex-drive-sources.ts:719-722` ставит `pending` без `preserveResume` → строка с checkpoint теряет
`checkpoint`, `resumable`, `resumeReason`, `resumes`, `resumeNoProgress` (в quarantine/repair перенос есть).
2. Тесты воспроизведены 17/18, RC 1: enrichment-marker не сбрасывает `resumeNoProgress` (`processingState.ts:622-624`, explicit `undefined`).
Замечание после посадки: предупреждение на inline-пути `sourceWriter.ts:480-489` шумное и называет пользовательскую загрузку «обходом» — понизить до info/структурированного сигнала.
Дальше: 4577 (Нео, итерация 7 — ровно три пункта, полный патч ит. 5+6+7 одним файлом для сборки) → приёмка 4578.
Доказательства: `neo:~/waves/4576ACCEPTQUEUEPATCHITER6-evidence/` (`review.md`, `tests.md`, `risk-review.md`).
2026-09-22T02:27:35.118Z · coordinator[22.09 02:27Z координатор] ## 4577 (Нео, итерация 7, GO, манифест 7/7) — три замечания 4576 закрыты; полный патч ит. 5+6+7 одним файлом; на приёмке 4578
- Drive-путь (`reindex-drive-sources.ts`) ставит в очередь с `preserveResume: true` — пять полей resume байт-в-байт; во всех трёх переведённых инструментах флаг есть (grep).
- `processingState.ts` различает отсутствующий и явно переданный `undefined` → enrichment-marker считается прогрессом и сбрасывает `resumeNoProgress`; тест 4576 без изменений (cmp RC 0), **18/18 RC 0**.
- Inline user-ingest в `sourceWriter.ts` — `console.info` с `{ path: 'inline-user-ingest', sourceId }`, без слова «обход».
- Замков/`FOR UPDATE`/`ORDER BY` в diff нет; 12 файлов; `git apply --check` на чистый `cc278e18` RC 0.
- **Полный патч** (то, что поедет в сборку): sha `20404d084dfa9aa6bfc44960736f82e7c7e8d392ff6eca11432f51b0a0799aa4`;
копии: Мак `waves-20260921/4577-evidence/diff.patch`, A2 `4558-material/4577-queue-patch-full-iter5-6-7.patch`.
- Команда тестов для A2: `node --import tsx --test src/lib/ingest/__tests__/sourceIndexingResumeHonesty.test.ts` (в чистом архиве `tsx` нет — гоняли через `scripts/ts-node-resolver.mjs`).
Дальше: 4578 (Нео) — быстрая враждебная приёмка только изменённого + целостность полного патча; при GO → сборка 4558 (A2) после лестниц.
2026-09-22T02:39:09.615Z · coordinator[22.09 02:39Z координатор] ## 4578 (Нео, финальная приёмка итерации 7, GO, манифест 5/5) — ПАТЧ ОЧЕРЕДИ ПРИНЯТ К ПОСАДКЕ (`SHIP_TO_PROD=ДА`)
`HUNKS=77`, `DRIVE_FIELDS_MISSING=0`, `OTHER_CALLERS_BEHAVIOUR_CHANGED=НЕТ` (отсутствие ключа сохраняет прежний fallback, явный
`undefined` = прогресс), `INLINE_INFO_OK=ДА` (один структурированный `console.info`, без тела/кук), полный патч применяется на чистый
`cc278e18` RC 0, sha `20404d084dfa9aa6bfc44960736f82e7c7e8d392ff6eca11432f51b0a0799aa4`, замков 0, ORDER BY нетронут, регрессий нет,
тесты воспроизведены 18/18 RC 0.
Итог темы для нулевых агентов: дефект = массовая переиндексация подавала документы воркеру мимо очереди, где приоритет
пользовательских загрузок уже есть, и повторяла неудачные документы без предела. Три итерации с замками (2–4) отвергнуты приёмкой
как растущая поверхность риска; итерации 5–7 без замков: массовые инструменты (quarantine, repair-live-docs, drive-sources) ставят
в `pending` с сохранением состояния resume, одиночные пути остаются адресными с журналом, cap на resume = 5, enrichment считается прогрессом.
Наблюдение первые 24 ч на бою (SELECT-only): `pending`/backlog, переходы воркера, checkpoint `completedChunks/totalChunks`, `resumeNoProgress`;
inline-путь виден как `info path=inline-user-ingest`.
Посадка: сборка 4558 на A2 (после лестниц — стенд занят замером), одна посадка вместе с потолком полос (4525/4526 + hard-exit по 4534).
Доказательства: `neo:~/waves/4578ACCEPTQUEUEPATCHITER7-evidence/` (`review.md`, `risk-review.md`, `tests.md`).
2026-09-22T22:59:01.703Z · coordinator[22.09 22:59Z координатор] ## 22.09 22:55Z — посажено в l115r (1a5822a8): очередь индексации user-first, CLI переиндексации ставит pending (патч 4577, тесты 4586). Проверка на бою: следующая реальная загрузка при непустой очереди reindex должна обгонять reindex-задания; наблюдение до закрытия.
2026-09-23T06:44:45.422Z · coordinator[23.09 06:44Z координатор] ## 4668 (M1, Luna) — в работе: CLI переиндексации переводится на постановку в ОБЩУЮ очередь без пользовательского приоритета (штатный ORDER BY действует), прямой путь только за `--direct`; resume cap `INGEST_RESUME_MAX_ATTEMPTS` (умолчание 50) с отравлением `resume_cap_exceeded`; admission guard/advisory lock НЕ повторяется (отклонён 4547–4555); ветка `l115s-web676-reindex-enqueue` от l115r.
2026-09-23T07:02:50.986Z · coordinator[23.09 07:02Z координатор] ## 4668 (M1, GO, 7/7) — принято: CLI `reindex-quarantined-chunks.ts` и `process-source-indexing-queue.ts --source` теперь ТОЛЬКО ставят в общую очередь (`reason=reindex:*`, без пользовательского приоритета, идемпотентно: `queued=N alreadyQueued=M`), обработка — штатным воркером в штатном порядке (тест: 50 reindex + 1 user-upload → user первым); прямой путь только `--direct` для инцидентов; resume cap `INGEST_RESUME_MAX_ATTEMPTS` (умолчание 50, 0 = без предела) → poisoned `resume_cap_exceeded`, revive обнуляет. 3 коммита, тесты 7/7 новых + 50/50, typecheck 0. Ветка A2 `l115s-web676-reindex-enqueue`; кандидат в l115s. Runbook — `ops.md` в сдаче.
2026-09-23T07:53:51.330Z · coordinator[23.09 07:53Z координатор] ## 4670 (M1, независимая приёмка) — 4668 = GO: am чистый, фокус-набор 57/57, регрессы областей только базовые; enqueue/приоритет user/`--direct`/resume cap/revive/режим 0 — PASS (7/8 состязательных, единственный FAIL относится к 4667). Готов в l115s.
2026-09-25T08:42:19.097Z · coordinator[25.09 08:42Z координатор] # Ready board comment — WEB-676
2026-09-25 — POST-QA all9 `879094713e`: **REOPEN**.
Проверка нашла, что обычная очередь имеет user priority (`src/lib/sources/sourceReadGateway.ts:1294`), но прямой quarantine reindex всё ещё обходит её: `scripts/reindex-quarantined-chunks.ts:1497` подаёт source напрямую (`limit:1/concurrency:1`). Поэтому критерий «defer при pending user upload» кодом не закрыт. По ключу WEB-676 коммитов в `1a5822a8..879094713e` нет.
Resume cap-сигнал виден около `src/lib/ingest/processingState.ts:106`, но полного all9 proof для five signatures/checkpoint не найдено. Live 7-day ≤600s не запускался по границам волны и сам по себе был бы residue; главная причина возврата — отсутствующий admission guard.
Что вернуть в работу: атомарный guard перед direct claim с тем же eligible-user predicate; tests defer/no-user/progress/reset/five signatures/checkpoint; затем staging/owner receipt. Ссылки канона и исходных раундов: WEB-449, `4547/4551/4554/4555/4556` paths из карточки. Новый агент начинает с этого файла и строки `reindex-quarantined-chunks.ts:1497`; бой не трогать.
Проверка координатора (09:5xZ, all9 879094713e, M1): REOPEN принят — нужен раунд исправления.
2026-09-25T09:22:09.912Z · coordinator[25.09 09:22Z координатор] 2026-09-25 — 4985 (M1, all9 879094713e): VERDICT=GO, но неполный. WEB-676: прямой reindex адресует выбранный sourceId и атомарно уступает ожидающей загрузке пользователя (sourceReadGateway.ts:1596, sourceIndexingQueue.ts:1081, reindex-quarantined-chunks.ts:1533), unit 10/10; PG-тест SKIP. WEB-677: сервисный вызов не блокируется кошельком, но учитывается в ledger; пользовательский кошелёк по-прежнему блокирует; баланс сервисного кошелька и порог −80% видны в health (llmBilling.ts:361, meteredVendorCall.ts:637, walletService.ts:353/1029, sourceIndexingWorkerHealth.ts:448); PG-тест 0/1 SKIP (на M1 нет БД). WEB-685 263/263. Коммиты на A2: l115s-web676-677-4985 (416e1f76d5, c47a54dc99), сводная ветка l115s-all9-pgcheck = all9 + 4984 + 4985. Приёмка на живом Postgres — волна 4986 (A2, вместе с WEB-671). Статус не меняю до её вердикта.
2026-09-25T12:14:17.602Z · coordinator[25.09 12:14Z координатор] 4991 (Neo, Luna): VERDICT=GO. WEB677_PG 8/8, SERVICE_CALL_LEDGERED=ДА (service:* списывается в транзакции settle, тот же ключ операции что у асинхронной проекции → повтор no-op), SETTLE_IDEMPOTENT=ДА, USER_WALLET_BLOCKS=ДА; WEB676_PG 2/2; WEB-99 = устаревшая PG-фикстура (импорт до DATABASE_URL, нет claim token), не дефект кода; WEB671_PG 3/3; WEB-685 263/263. Ветка A2 l115s-web677-r3-4991 (eb6379afb3, 5 коммитов на all9). Независимое ревью — 4994 (Astra, Neo).
2026-09-26T12:12:22.845Z · coordinator[26.09 12:12Z координатор] 26.09 12:15Z координатор: сборка 5058 (NO-GO) сорвана дворником диска A2, он удалил рабочий каталог. Дворник исправлен: защита по метке KEEP. Интеграция перезапущена как 5061 (A2, старт 12:11:31Z) с тем же составом: e7e0cd9b + 618583ff и Linux-исправления из журнала 5058. Тикет остаётся в работе до GO сборки и деплоя на стенд.
2026-09-26T12:57:51.139Z · coordinator[26.09 12:57Z координатор] 5061 (сборка r2, 26.09 12:53Z) NO-GO. Интеграция и все Linux-исправления восстановлены, merge tree совпал с ожидаемым. Все тесты Linux прошли, checker5057 17/17. Прежний блокер (инициализация pinned Next send) устранён узким допуском по точному пути и хешу, отрицательные тесты прошли. Compile упал на новом месте: нативный модуль lightningcss linux-arm64 не загрузился. Повторить не дал порог диска 12 GiB. Координатор удалил 25 чистых worktree на A2, ветки сохранены, стало 16 GiB. Запущена 5062 (r3) с вершины 5061: узкий допуск для lightningcss, затем полная штатная цепочка. Тикет ждёт общий пакет стенда.
2026-09-26T13:38:36.229Z · coordinator[26.09 13:38Z координатор] 26.09 13:38Z: сборка интеграции 5062 NO-GO. Допуск lightningcss принят, тесты PASS. Compile упал на нативном модуле @tailwindcss/oxide. Запущена 5064: инвентарь всех нативных linux-arm64 модулей и узкие допуски разом, затем штатная цепочка. Этот тикет входит в пакет. После GO: деплой на стенд, checker5057, ступени 300/400/500, живые роли.
2026-09-26T20:36:05.438Z · coordinator[26.09 20:36Z координатор] Координатор, пост-QA 5073 на стенде 5069 (26.09 ~21:40 Дублин). Отчёт A2 /home/ubuntu/waves/5073POSTQASIXTICKETSSTAND-REPORT.md. FAIL: user-first выбор подтверждён, но до ready за 121 с не дошло; очередь стала poisoned из-за billing containment_misconfigured и transaction timeout. Остаётся in_progress.
2026-09-26T21:35:55.303Z · coordinator[26.09 21:35Z координатор] Волна 5077 (Astra), 26.09 21:32Z, VERDICT=NO-GO (диагноз готов, фиксы подготовлены, НЕ применены), манифест 62/62 OK.
- Индексация стенда стоит из-за конфигурации: SPEND_CONTAINMENT_MODE=enforce, а у worker нет ~20 обязательных входов (caps, attestation, egress proxy, reconcile, alert). Guard fail-closed отработал правильно.
- Старый source в readiness: устаревшие NC_RELEASE_ID/RELEASE_SOURCE_COMMIT в app-a..d.env и worker.env. Скрипт fix-stand.sh (overlay, откат rollback-stand.sh) подготовлен.
- Патчи на 5069: WEB-677 service wallet floor=0 + нулевые receipts при долге; WEB-651 отказ 413 document_over_ceiling до создания Source для TXT/MD; WEB-676/681 timeout записи документа 5s→15s (claim+upsert атомарны); egress proof интервал 61s. Тесты 179/179 → 188/188, tsc PASS, новых lint нет.
- Checker 5057: 59.999 с — порядок setInterval до startup proof; patch 0006 (stdin для jq, CLD_EXITED numeric); на живой сессии PASS span 1523 с.
- Оговорки: денежный патч WEB-677 требует живой проверки конкурентности на изолированном Postgres; критерий WEB-651 Astra искала не на этой доске — сверить; прогресс индексации (heartbeat замер 21:01Z) не исправлен.
Следующее: readiness-fix + checker → 5074-r2 → ступени; патчи → сборка + пост-QA.
2026-09-27T08:26:46.948Z · coordinator[27.09 08:26Z координатор] Пост-QA 5094 на стенде r12: FAIL. Загрузка пользователя выбрана первой, но ready только через 208.6 s на 3-й попытке; два фоновых задания ушли в poisoned после трёх concurrency_limit отказов сервисного concurrency gate — временный отказ не должен тратить poison budget. Репродьюсер-тест: A2 5094POSTQAFOURR12-evidence/patches/0002 (RED на r12). Статус → in_progress, фикс-волна следующей.
2026-09-27T08:51:57.216Z · coordinator[27.09 08:51Z координатор] Фикс 5095 GO (A2 fix/5095 @ fc40dbf4): типизированные временные pre-dispatch отказы (concurrency_limit и др.) → pending с backoff и отдельным счётчиком gateDeferrals, attempts не тратится; предел 24 отказа/24 ч, затем видимый skipped/service-gate-wait-exhausted, без poisoned. Spend gate не ослаблен. Репродьюсер 5094 GREEN, новых падений 0. Следом: r13 (5097) → стенд → пост-QA. Статус in_progress до пост-QA.
2026-09-27T09:26:51.713Z · coordinator[27.09 09:26Z координатор] Сборка r13 (5097) NO-GO по диску A2 (STOP на пороге 7 GiB, tarball не создан); код не при чём: тесты области 0 новых падений, репродьюсеры и acceptance 20/20 зелёные. Повтор 5099 с разрешённой чисткой старых точек отката стоит в очереди за 5098.
2026-09-27T10:17:24.748Z · coordinator[27.09 10:17Z координатор] Сборка r13 (5099) GO: фикс вошёл в артефакт fc40dbf4 (sha 69bff833…), contract/fence, тесты области (0 новых падений), acceptance 20/20, runtime из tarball и boot smoke зелёные. Деплой будет один раз — r14 (r13 + прокси ролей, 5100 собирается), затем повторный пост-QA этого тикета на стенде.
2026-09-27T11:35:20.390Z · coordinator[27.09 11:35Z координатор] Волна 5102 (деплой r14 на стенд), 27.09 11:33Z: пост-QA WEB-676 на стенде PASS.
Дальше: сборка r15 (5103) = r14 + патч с adversarial review, потом деплой и повторный пост-QA.
Пользовательский документ готов за 6.9 с на позиции 2/8 при массовой переиндексации, отсрочка сработала для 6 источников. Общий вердикт 5102 NO-GO только из-за WEB-651, стенд оставлен на r14.
2026-09-27T14:00:20.262Z · coordinator[27.09 14:00Z координатор] 5109 (27.09, стенд r15): пост-QA WEB-676 PASS — загрузка пользователя готова за 215,7 с при массовой переиндексации, позиция 5/8, отложено gate 6 источников. Отчёт и SHA256SUMS проверены (RC 0). Следующее: подтверждение на r16 вместе с остальными, затем посадка.
2026-09-27T16:11:40.252Z · coordinator[27.09 16:11Z координатор] [27.09 16:15Z координатор] Волна 5115: r16 79bbf331 выкачен на стенд 4400-r2, VERDICT=GO (evidence SHA256SUMS OK; ready 5/5, ready/paid 5/5, реальный логин, realtime 401 без сессии, воркер стартует, миграция WEB-057 применена к стендовой БД после проверенного pg_dump, nginx-патч proxy_max_temp_file_size 0). Откат: sudo timeout 480s python3 /home/ubuntu/waves/5115-work/rollback-release.py. Пост-QA:
WEB-676 PASS: ready за 66.7 с, позиция 3/8, gateDeferralSources=6. evidence postqa-web676.json.
Воркер
не привязан — привязать:
curl -X POST https://bugs.wool2.online/api/web/assign -H 'content-type: application/json' \
-d '{"issueId":"WEB-676","session":"<имя tmux-сессии>","host":"m4"}'
Обновлён
2026-09-27T14:00:20.544Z