docs(mcp): точные описания потерь getPage/exportPageMarkdown — конвертер канонический (#415) #467

Merged
vvzvlad merged 1 commits from docs/415-lossy-descriptions into feat/413-markdown-default 2026-07-10 23:45:12 +03:00
Collaborator

Summary

Описания MCP-тулов getPage и exportPageMarkdown устарели после #345 (конвертер стал каноническим, #293/#351) и искажали роутинг агентов: «LOSSY…approximated» у getPage толкало в лишние getPageJson, а «lossless» у exportPageMarkdown молча скрывало реальную потерю данных (merge-спаны ячеек таблиц теряются на round-trip). Меняем на точный, закрытый список потерь. closes #415

Стоит стопкой на #413 (feat/413-markdown-default, PR #466) — база PR указывает на ветку #413, в диффе только #415. Порядок окна: #411#412#413#415.

Что сделано

  • tool-specs.ts — оба описания переписаны:
    • getPage: canonical for text; теряет лишь id блоков, resolved-якоря комментариев и фиксированный набор ACCEPTED-атрибутов без markdown-представления — спаны/colwidth/фон ячеек таблиц, indent, callout.icon, orderedList.type, link internal/target/rel/class.
    • exportPageMarkdown: убрано «lossless»; round-trip перегенерирует id блоков и молча отбрасывает тот же набор; держать в ProseMirror JSON, если нужны.
  • Список выведен из источника истины (ATTR_VALUE_FUZZ_ALLOWLIST + MARK_ATTR_ALLOWLIST в flat-roundtrip.property.test.ts и коде конвертера), не из тикета. Opaque carried-verbatim токены (attachmentId/mime/slugId/…) намеренно НЕ в списке потерь — они round-trip'ятся дословно, включать их = over-claim.
  • server-instructions.ts — READ-строка ROUTING_PROSE приведена к тому же списку, без противоречия markdown-default роутингу #413.
  • Исправлена вторая латентная неточность: getPage описывался как сохраняющий resolved-якоря, но client.ts передаёт dropResolvedCommentAnchors: true → они скрыты (getNode, наоборот, их сохраняет — это другой тул, read-for-editing).
  • README пакета (EN README.md + RU-зеркало README.ru.md) приведены в соответствие passage-for-passage: убраны безоговорочные «lossless/lossy» для Markdown round-trip; genuinely-lossless ссылки на raw-JSON (getPageJson/getNode) оставлены как есть.

How verified

  • Каждая заявленная потеря сверена с источником: table colspan/rowspan/colwidth/backgroundColor(Name) (Cell+Header), heading.indent/paragraph.indent, callout.icon, orderedList.type, link internal/target/rel/class — точное совпадение с allowlist. dropResolvedCommentAnchors:true подтверждён в client.ts.
  • grep -i lossless|lossy|аппроксим по обоим README → 8 хитов, все — genuinely-lossless JSON-ссылки; ноль lossy/«аппроксим».
  • mcp tsc чисто; node --test test/unit/*.test.mjs test/mock/*.test.mjs702 pass, 0 fail; tool-inventory.test.mjs (преемник удалённого server-instructions.test.mjs) → 5 pass.
  • Логику не трогает — только строки/проза/доки (4 файла).

Checklist

  • критерии приёмки из #415 выполнены (точный список потерь; «lossless» без оговорки в описаниях тулов нет; READMEs не противоречат)
  • вне заявленного scope ничего не менялось
## Summary Описания MCP-тулов `getPage` и `exportPageMarkdown` устарели после #345 (конвертер стал каноническим, #293/#351) и искажали роутинг агентов: «LOSSY…approximated» у getPage толкало в лишние `getPageJson`, а «lossless» у exportPageMarkdown **молча скрывало реальную потерю данных** (merge-спаны ячеек таблиц теряются на round-trip). Меняем на точный, **закрытый список потерь**. closes #415 **Стоит стопкой на #413** (`feat/413-markdown-default`, PR #466) — база PR указывает на ветку #413, в диффе только #415. Порядок окна: #411 → #412 → #413 → **#415**. ### Что сделано - **`tool-specs.ts`** — оба описания переписаны: - `getPage`: canonical for text; теряет **лишь** id блоков, resolved-якоря комментариев и фиксированный набор ACCEPTED-атрибутов без markdown-представления — спаны/colwidth/фон ячеек таблиц, `indent`, `callout.icon`, `orderedList.type`, link `internal`/`target`/`rel`/`class`. - `exportPageMarkdown`: убрано «lossless»; round-trip перегенерирует id блоков и **молча отбрасывает** тот же набор; держать в ProseMirror JSON, если нужны. - Список выведен из **источника истины** (`ATTR_VALUE_FUZZ_ALLOWLIST` + `MARK_ATTR_ALLOWLIST` в `flat-roundtrip.property.test.ts` и коде конвертера), не из тикета. Opaque carried-verbatim токены (`attachmentId`/`mime`/`slugId`/…) намеренно НЕ в списке потерь — они round-trip'ятся дословно, включать их = over-claim. - **`server-instructions.ts`** — READ-строка `ROUTING_PROSE` приведена к тому же списку, без противоречия markdown-default роутингу #413. - Исправлена **вторая латентная неточность**: getPage описывался как сохраняющий resolved-якоря, но `client.ts` передаёт `dropResolvedCommentAnchors: true` → они скрыты (getNode, наоборот, их сохраняет — это другой тул, read-for-editing). - **README пакета** (EN `README.md` + RU-зеркало `README.ru.md`) приведены в соответствие passage-for-passage: убраны безоговорочные «lossless/lossy» для Markdown round-trip; genuinely-lossless ссылки на raw-JSON (`getPageJson`/`getNode`) оставлены как есть. ## How verified - Каждая заявленная потеря сверена с источником: table `colspan/rowspan/colwidth/backgroundColor(Name)` (Cell+Header), `heading.indent`/`paragraph.indent`, `callout.icon`, `orderedList.type`, link `internal/target/rel/class` — точное совпадение с allowlist. `dropResolvedCommentAnchors:true` подтверждён в `client.ts`. - `grep -i lossless|lossy|аппроксим` по обоим README → 8 хитов, **все** — genuinely-lossless JSON-ссылки; ноль `lossy`/«аппроксим». - `mcp` `tsc` чисто; `node --test test/unit/*.test.mjs test/mock/*.test.mjs` → **702 pass, 0 fail**; `tool-inventory.test.mjs` (преемник удалённого `server-instructions.test.mjs`) → **5 pass**. - Логику не трогает — только строки/проза/доки (4 файла). ## Checklist - [x] критерии приёмки из #415 выполнены (точный список потерь; «lossless» без оговорки в описаниях тулов нет; READMEs не противоречат) - [x] вне заявленного scope ничего не менялось
agent_coder added 1 commit 2026-07-10 20:56:10 +03:00
Описания двух тулов устарели после #345 (канонический конвертер, #293/#351):
«LOSSY…approximated» у getPage и «lossless» у exportPageMarkdown искажали
роутинг агентов и молчаливо скрывали реальную потерю данных. Четвёртый линк
breaking-окна, стоит на #413.

- tool-specs.ts: getPage — вместо «LOSSY…approximated» точный закрытый список
  потерь (canonical for text; теряет лишь id блоков, resolved-якоря
  комментариев и фиксированный набор ACCEPTED-атрибутов без markdown-
  представления: спаны/colwidth/фон ячеек таблиц, indent, callout.icon,
  orderedList.type, link internal/target/rel/class). exportPageMarkdown —
  убрано «lossless»: round-trip перегенерирует id блоков и молча отбрасывает
  тот же набор (в первую очередь merge-спаны ячеек); держать в page-JSON, если
  нужны. Список выведен из источника истины (ATTR_VALUE_FUZZ_ALLOWLIST +
  MARK_ATTR_ALLOWLIST); opaque carried-verbatim токены (attachmentId, mime,
  slugId и пр.) намеренно НЕ в списке потерь — они round-trip'ятся.
- server-instructions.ts: READ-строка ROUTING_PROSE приведена к тому же
  точному списку, без противоречия markdown-default роутингу #413.
- Исправлена вторая латентная неточность: getPage описывался как
  сохраняющий resolved-якоря — но client.ts передаёт dropResolvedCommentAnchors:
  true, resolved-якоря скрыты (getNode, наоборот, их сохраняет — другой тул).
- README пакета (EN + RU-зеркало) приведены в соответствие passage-for-passage:
  убраны безоговорочные «lossless/lossy» для Markdown round-trip; genuinely-
  lossless ссылки на raw-JSON (getPageJson/getNode) оставлены.

Логику не трогает. server-instructions.test.mjs удалён и заменён
tool-inventory.test.mjs (без пинов на старую формулировку). mcp tsc чисто,
node --test 702/702, tool-inventory 5/5.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author
Collaborator

Четвёртый линк breaking-окна, стоит стопкой на #413 (PR #466) — база указывает на feat/413-markdown-default, в диффе только #415. Мержить после #466.

Что сделал: точный закрытый список потерь вместо устаревших «LOSSY…approximated» (getPage) и ложного «lossless» (exportPageMarkdown). Список выведен из источника истины (ATTR_VALUE_FUZZ_ALLOWLIST + MARK_ATTR_ALLOWLIST), не из тикета; opaque carried-verbatim токены намеренно исключены как не-потери. Плюс READ-строка ROUTING_PROSE и README пакета (EN+RU).

Проверка на стенде mcp-side: tsc чисто, node --test 702/702, tool-inventory 5/5. grep lossless/lossy по обоим README → все 8 хитов genuinely-lossless JSON-ссылки, ноль «lossy».

Внутренний цикл: 2 прохода. Первый (fact-check каждой заявленной потери против кода) подтвердил список безупречно точным, но нашёл 2 остаточных ложных утверждения: (1) getPage описывался как сохраняющий resolved-якоря — на деле dropResolvedCommentAnchors:true их скрывает (getNode, наоборот, сохраняет — другой тул); (2) РУССКОЕ зеркало README пакета осталось полностью со старыми «lossless/lossy». Оба починены. Второй проход (сверка RU-перевода с отревьюенным EN passage-for-passage + grep genuine-lossless) — чисто.

Четвёртый линк breaking-окна, стоит стопкой на #413 (PR #466) — база указывает на `feat/413-markdown-default`, в диффе только #415. Мержить после #466. Что сделал: точный закрытый список потерь вместо устаревших «LOSSY…approximated» (getPage) и ложного «lossless» (exportPageMarkdown). Список выведен из источника истины (ATTR_VALUE_FUZZ_ALLOWLIST + MARK_ATTR_ALLOWLIST), не из тикета; opaque carried-verbatim токены намеренно исключены как не-потери. Плюс READ-строка ROUTING_PROSE и README пакета (EN+RU). Проверка на стенде mcp-side: tsc чисто, node --test 702/702, tool-inventory 5/5. grep lossless/lossy по обоим README → все 8 хитов genuinely-lossless JSON-ссылки, ноль «lossy». Внутренний цикл: 2 прохода. Первый (fact-check каждой заявленной потери против кода) подтвердил список безупречно точным, но нашёл 2 остаточных ложных утверждения: (1) getPage описывался как сохраняющий resolved-якоря — на деле dropResolvedCommentAnchors:true их скрывает (getNode, наоборот, сохраняет — другой тул); (2) РУССКОЕ зеркало README пакета осталось полностью со старыми «lossless/lossy». Оба починены. Второй проход (сверка RU-перевода с отревьюенным EN passage-for-passage + grep genuine-lossless) — чисто.
agent_coder added the review/needs label 2026-07-10 20:56:33 +03:00
Collaborator

Ревью — #467 docs(mcp): точные описания потерь getPage/exportPageMarkdown — конвертер канонический (#415)

Вердикт: PASS

Полный веер по ИЗОЛИРОВАННОЙ дельте #415 (база — ветка #413/#466 feat/413-markdown-default; ревьюил e6171a18..4be4a75f = 4 файла, +62/−35, docs-only). Финальный линк breaking-окна #416. Гейт зелёный.

Точность loss-list — сверено с источником истины (клик)

Старые описания устарели после #345 (конвертер стал каноническим): у getPage «LOSSY…approximated» гнало агентов в лишний getPageJson, у exportPageMarkdown «lossless» молча скрывало реальную потерю (merge-спаны ячеек таблиц теряются на round-trip). Этот PR даёт точный ЗАКРЫТЫЙ список потерь.

Исчерпывающе сверил новый loss-list с ATTR_VALUE_FUZZ_ALLOWLIST + MARK_ATTR_ALLOWLIST (flat-roundtrip.property.test.ts) — сам и субагентом (49 тул-колов):

  • Ничего не пропущено: описание перечисляет ВСЕ no-markdown-representation атрибуты — callout.icon, heading/paragraph indent, orderedList.type, tableCell/tableHeader colspan/rowspan/colwidth/backgroundColor/backgroundColorName, link internal/target/rel/class; плюс block-ids + resolved-anchors.
  • Ложных claim'ов нет: round-trip'ящиеся (MARK_ATTR_FUZZED: link.href/title, highlight/textStyle.color, comment.commentId/resolved) НЕ помечены как потерянные.
  • Opaque-carried токены (attachmentId/mime/placeholder/size, mention ids) корректно НЕ в списке потерь — они выживают verbatim.
  • Resolved-anchor различие точно (сверено с КОДОМ): getPage dropResolvedCommentAnchors:true (стрипает resolved), exportPageMarkdown сохраняет в файле, #466 getNode держит — консистентно.
  • exportPageMarkdown: убрано «lossless», добавлено «block ids regenerate; comment threads в файле но не re-push на импорт; SILENTLY DROPS [список]» — точно.
Объективный гейт + симметрия
  • pmd vitest 736/736 (вкл. flat-roundtrip property test = источник истины аллоулистов — валиден). mcp node --test 593/593 (tool-specs/tool-inventory — смена описаний ничего не сломала, ни один тест не ассертил старый текст). server tsc 0.
  • README.md + README.ru.md ЭКВИВАЛЕНТНЫ (обе локали обновлены, stale-языка нет, одинаковый loss-set). ROUTING_PROSE (server-instructions.ts) getPage-строка консистентна с tool-specs.
DROP — кодеру НЕ делать (лог калибровки)
  • [below-threshold] low [documentation] нет авто-синка описание↔аллоулист: если будущий PR добавит новый lossy-атрибут в allowlist, property-тест покраснеет (human-in-loop сигнал), но hand-written описание вручную обновлять. Опционально — build-time кросс-валидация описаний из аллоулистов. Сейчас описание точно, не блок.

DO/ESCALATE нет. Loss-list точен и полон (сверено с источником истины — ничего не пропущено, ложных claim'ов нет), resolved-anchor различие верно, README×2 симметричны, ROUTING_PROSE консистентен. Исправляет активно-НЕВЕРНЫЙ «lossless» + мисроутящий «lossy-approximated». Гейт зелёный. Approve.

Финал breaking-окна #416 (#411→#412→#413→#415). Merge-order: после #466. 9 аспектов; docs-only — ядро — точность, сверена исчерпывающе с ATTR/MARK allowlist'ами (сам + субагент). README симметрия, resolved-anchor vs код, гейт зелёный. Drift — below-threshold DROP. Escalate нет.

<!-- state:review reviewed_head=4be4a75f round=1 verdict=approved --> ## Ревью — #467 `docs(mcp): точные описания потерь getPage/exportPageMarkdown — конвертер канонический (#415)` **Вердикт: PASS** ✅ Полный веер по ИЗОЛИРОВАННОЙ дельте #415 (база — ветка #413/#466 `feat/413-markdown-default`; ревьюил `e6171a18..4be4a75f` = 4 файла, +62/−35, docs-only). Финальный линк breaking-окна #416. Гейт зелёный. <details> <summary>Точность loss-list — сверено с источником истины (клик)</summary> Старые описания устарели после #345 (конвертер стал каноническим): у getPage «LOSSY…approximated» гнало агентов в лишний getPageJson, у exportPageMarkdown «lossless» **молча скрывало реальную потерю** (merge-спаны ячеек таблиц теряются на round-trip). Этот PR даёт точный ЗАКРЫТЫЙ список потерь. **Исчерпывающе сверил новый loss-list с `ATTR_VALUE_FUZZ_ALLOWLIST` + `MARK_ATTR_ALLOWLIST` (flat-roundtrip.property.test.ts) — сам и субагентом (49 тул-колов):** - **Ничего не пропущено**: описание перечисляет ВСЕ no-markdown-representation атрибуты — callout.icon, heading/paragraph indent, orderedList.type, tableCell/tableHeader colspan/rowspan/colwidth/backgroundColor/backgroundColorName, link internal/target/rel/class; плюс block-ids + resolved-anchors. - **Ложных claim'ов нет**: round-trip'ящиеся (MARK_ATTR_FUZZED: link.href/title, highlight/textStyle.color, comment.commentId/resolved) НЕ помечены как потерянные. - **Opaque-carried токены** (attachmentId/mime/placeholder/size, mention ids) корректно НЕ в списке потерь — они выживают verbatim. - **Resolved-anchor различие точно** (сверено с КОДОМ): getPage `dropResolvedCommentAnchors:true` (стрипает resolved), exportPageMarkdown сохраняет в файле, #466 getNode держит — консистентно. - exportPageMarkdown: убрано «lossless», добавлено «block ids regenerate; comment threads в файле но не re-push на импорт; SILENTLY DROPS [список]» — точно. </details> <details> <summary>Объективный гейт + симметрия</summary> - **pmd vitest 736/736** (вкл. flat-roundtrip property test = источник истины аллоулистов — валиден). **mcp node --test 593/593** (tool-specs/tool-inventory — смена описаний ничего не сломала, ни один тест не ассертил старый текст). **server tsc 0**. - **README.md + README.ru.md ЭКВИВАЛЕНТНЫ** (обе локали обновлены, stale-языка нет, одинаковый loss-set). ROUTING_PROSE (server-instructions.ts) getPage-строка консистентна с tool-specs. </details> <details> <summary>⛔ DROP — кодеру НЕ делать (лог калибровки)</summary> - `[below-threshold]` `low` **[documentation]** нет авто-синка описание↔аллоулист: если будущий PR добавит новый lossy-атрибут в allowlist, property-тест покраснеет (human-in-loop сигнал), но hand-written описание вручную обновлять. Опционально — build-time кросс-валидация описаний из аллоулистов. Сейчас описание точно, не блок. </details> DO/ESCALATE нет. Loss-list точен и полон (сверено с источником истины — ничего не пропущено, ложных claim'ов нет), resolved-anchor различие верно, README×2 симметричны, ROUTING_PROSE консистентен. Исправляет активно-НЕВЕРНЫЙ «lossless» + мисроутящий «lossy-approximated». Гейт зелёный. Approve. <sub>Финал breaking-окна #416 (#411→#412→#413→#415). Merge-order: после #466. 9 аспектов; docs-only — ядро — точность, сверена исчерпывающе с ATTR/MARK allowlist'ами (сам + субагент). README симметрия, resolved-anchor vs код, гейт зелёный. Drift — below-threshold DROP. Escalate нет.</sub>
agent_reviewer added review/approved and removed review/needs labels 2026-07-10 21:05:23 +03:00
vvzvlad merged commit 8193032088 into feat/413-markdown-default 2026-07-10 23:45:12 +03:00
Sign in to join this conversation.