[QA-trace][#228 6/7] Верификация footnotes: 🔴 ФИЧА СЛОМАНА на import-пути (канонизатор не подключён в apps/server) — чиню #240
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?
Process-trace отчёт: верификация PR #228 (inline footnotes / каноникализация)
Стенд: gitmost (форк Docmost), UI :5173, API :3000, collab :3001. Инструментарий: Playwright (python, headless chromium-1148, --no-sandbox), curl для API, grep/Read для статической трассировки. Оракулы: рендер DOM (data-footnote-number / --footnote-number CSS-var на надстрочниках и нижнем списке) + POST /api/pages/info (хранимый ProseMirror-JSON) + исходники.
1. Сводка и ВЕРДИКТ ФИЧИ
Вердикт: каноникализация НЕ работает на главном заявленном пути (markdown-import / paste). Фича сломана.
PR заявляет, что нумерация и нижний список выводятся детерминированно на write-путях (markdown import, updatePageJson, после каждого docmost_transform). По факту в
apps/serverканоникализатор не подключён вообще:grep canonicalizeFootnotes apps/server/srcдаёт 0 совпадений (я перепроверил живьём — пусто). Функция существует только вpackages/mcpиpackages/editor-ext.import.service.ts:127делаетmarkdownToHtml->htmlToJsonбез шага канонизации. Поэтому:footnoteContentKey()подключён только вinsertInlineFootnote(MCP inline-tool).footnoteSyncPluginпо дизайну роняет orphan и переиздаёт id-коллизии, но НЕ переупорядочивает существующий список (noChangeNeeded игнорирует внутрисписочный порядок). Открытие/сохранение в редакторе фиксирует физический порядок навсегда.enableSync=false) запускает только numbering-декорацию — orphan не выкидывается, порядок не чинится; зритель свежеимпортированной страницы видит и orphan, и кривой порядок.Что РАБОТАЕТ (позитивные контроли): нумерация надстрочников-ссылок верна (порядок первого упоминания, повтор того же id переиспользует номер); сырой хвостовой блок
[^id]:убирается marked-конвертером (в теле нет литералов[^); дубль-определение одного id — first-wins; интерактивная вставка через slash-меню с перенумерацией insert-before работает и переживает reload; страница без сносок не плодит пустой список.Итог: единственная корректная часть — reference-numbering и зачистка сырого блока. Сам акт каноникализации (reorder + content-dedup + orphan-drop на write-path + идемпотентность) на пользовательском пути отсутствует. Каноникализатор подключён ТОЛЬКО в MCP/AI-chat путь, который на стенде недостижим (нет MCP-листенера на :3000/:3001/:5173) и остался непроверенным.
2. Агенты и инструменты — кто как загонял footnote-markdown
Четыре исполнителя + recon, плюс независимый verifier-проход. Ключевая ценность для оракула — все использовали ДВОЙНОЙ оракул (хранимый JSON через /pages/info + реальный рендер DOM), а не один сигнал.
Ingest-методы покрыты: REST
/api/pages/import(все), paste (1 агент), interactive slash-insert (1 агент); UI Import->Markdown заявлен, но de-facto тот же серверный путь, что REST. DOM-оракул нумерации реализован двумя способами (data-footnote-number атрибут и --footnote-number CSS-var) — хорошая перекрёстная проверка. Reload-идемпотентность проверена «свежим browser load» (effective reload) против /pages/info.3. Находки по классу (как / кем / этап)
4. Фолс-позитивы
0. Verifier пересэмплировал 6 из 12 находок (включая обе high-репродукции, content-dedup, flushSync, read-only-orphan) — все reported=verified подтверждены как verifier=verified, ни одна не понижена. Позитивные контроли честно помечены как feature-works, а не выданы за баги. False-positive rate в этом прогоне = 0.
5. Где скилл сработал / провалился на верификации этой фичи
Сработал:
Провалился / ограничения:
6. Предложения по скиллу (без кода)
📌 Это и есть ценность верификации: скилл поймал, что
canonicalizeFootnotesподключён только в MCP/editor-ext, а вapps/server(REST/pages/import+ paste) — 0 call-sites, поэтому trigger-баг (сноски вразнобой + orphan) воспроизводится. 4 агента независимо. Чиню #232 — подключаю канонизацию в серверный import/paste-путь.(Мелочь по скиллу: 1 агент улетел в StructuredOutput retry-cap — редкий сбой схемы, отчёт всё равно синтезирован.)
🤖 web-test-orchestrator (process-trace, feature-verify)
Ghost referenced this issue2026-06-27 17:11:59 +03:00