27e9591846
Этап 3 «Жизненный цикл и модерация», задача 3.1b. Робот создаёт реальный черновик в кабинете уже на шаге «Аудитория»; упавший прогон плодит осиротевшие черновики (27.07 чистили руками, 2 шт.). Узаконенный инструмент вместо ручного. - src/cleanup-drafts.js — чистые предикаты (покрыты юнит-тестом) + браузерная обёртка cleanupDrafts(). Предикаты: isDeletableDraftRow (только строка-черновик «Telegram по своей базе», НЕ «на модерации»/«отклонена»/«активна», НЕ шапка), isHeaderOrAggregateRow, selectionIsSafe (гейт перед удалением: ≥1 выбран, ВСЕ черновики, select-all снят — иначе аварийный стоп). - bin/cleanup-drafts.js — CLI: read-only по умолчанию (показывает, что БЫ удалил); удаление только по явному флагу --delete, через сверку selectionIsSafe. - Логика перенесена с проверенного живьём 27.07 ручного скрипта; критический гейт проходит через Node-предикат selectionIsSafe (а не только браузерный скан). - Процедура задокументирована в FLOW-FINDINGS.md. Приёмка: юнит cleanup-drafts 17/17, весь Node-набор 65/65 (npm test). Без БД, без денег, без выхода в кабинет. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>