fix(drawio): content= — entity-XML вместо base64 (кириллица в редакторе) (#507) #521

Merged
vvzvlad merged 2 commits from fix/507-drawio-cyrillic into develop 2026-07-12 05:09:01 +03:00
Collaborator

Summary

Реviewer-filed баг #507: draw.io-редактор декодил наш base64 content= как Latin-1 → кириллические подписи → мойбейк, автосейв редактора персистил порчу и убивал превью. closes #507.

Причина: для base64-значения content= draw.io применяет atob (Latin-1, без UTF-8-декода). Нативная форма draw.io — entity-encoded mxfile-XML (content="<mxfile…"), которая DOM-декодится как UTF-8.

Фикс двух write-путей на XML-escape вместо base64:

  • buildDrawioSvg (packages/mcp/src/lib/drawio-xml.ts) — все create/update MCP-пути.
  • createDrawioSvg (import-attachment.service.ts) — Confluence-импорт (тот же латентный баг).
    Декодер (decodeDrawioSvg/extractContentAttr) уже различал startsWith("<") (entity XML) vs base64 — обе формы читаются, старые base64-файлы открываются.

How verified

  • mcp node --test test/unit test/mock: 836 pass (4 новых #507). Server import spec: 2 pass.
  • Критерии приёмки: content= нового .drawio.svg — entity-XML (не base64); byte-stable round-trip drawioCreatedrawioGet; старая base64-форма читается (back-compat); негативный тест (кириллица в value + не-ASCII заголовок в <diagram name=…>).
  • Внутренний ре-ревью: эскейп корректен (&<>" , & первым; апостроф не нужен внутри content="…"); byte-stable через edge-контент (&, ]]>, &#xa;, сырой <); других base64-писателей нет.

Миграция

Старые агентские кириллические диаграммы (base64) — «мины», лечатся drawioGetdrawioUpdate тем же XML (в CHANGELOG). Отдельный скрипт не нужен.

Checklist

  • баг #507 закрыт (5 критериев)
  • preview/file-serving не тронуты; 0 node_modules
## Summary Реviewer-filed баг #507: draw.io-редактор декодил наш base64 `content=` как Latin-1 → кириллические подписи → мойбейк, автосейв редактора персистил порчу и убивал превью. closes #507. Причина: для base64-значения `content=` draw.io применяет atob (Latin-1, без UTF-8-декода). Нативная форма draw.io — entity-encoded mxfile-XML (`content="&lt;mxfile…"`), которая DOM-декодится как UTF-8. Фикс двух write-путей на XML-escape вместо base64: - `buildDrawioSvg` (`packages/mcp/src/lib/drawio-xml.ts`) — все create/update MCP-пути. - `createDrawioSvg` (`import-attachment.service.ts`) — Confluence-импорт (тот же латентный баг). Декодер (`decodeDrawioSvg`/`extractContentAttr`) уже различал `startsWith("<")` (entity XML) vs base64 — обе формы читаются, старые base64-файлы открываются. ## How verified - mcp `node --test test/unit test/mock`: **836 pass** (4 новых #507). Server import spec: **2 pass**. - Критерии приёмки: `content=` нового `.drawio.svg` — entity-XML (не base64); byte-stable round-trip `drawioCreate`→`drawioGet`; старая base64-форма читается (back-compat); негативный тест (кириллица в value + не-ASCII заголовок в `<diagram name=…>`). - Внутренний ре-ревью: эскейп корректен (`&`<>" , `&` первым; апостроф не нужен внутри `content="…"`); byte-stable через edge-контент (`&`, `]]>`, `&#xa;`, сырой `<`); других base64-писателей нет. ## Миграция Старые агентские кириллические диаграммы (base64) — «мины», лечатся `drawioGet`→`drawioUpdate` тем же XML (в CHANGELOG). Отдельный скрипт не нужен. ## Checklist - [x] баг #507 закрыт (5 критериев) - [x] preview/file-serving не тронуты; 0 node_modules
agent_coder added the review/needs label 2026-07-12 00:09:25 +03:00
Collaborator

🤖 Авто-ревень · #521 (drawio content= entity-XML, #507) — голова 355bb81a. Вердикт: CHANGES

Фикс верный по сути (base64→entity-XML лечит мойибейк, escape инъекций-безопасен), но вводит новый класс потери данных, который нарушает собственный критерий приёмки #507 «byte-stable round-trip». Плюс 2 доводки.

Прогнал 9-аспектный веер + гейт (mcp 836/836, tsc 0, import-spec 2/2). Security/regressions/architecture/test-coverage LGTM: escape инъекций-безопасен (& первым, "&quot;, breakout невозможен), back-compat цел (старый base64 читается), baseHash format-agnostic (нет ложных конфликтов).

🔧 Do — потом ре-ревью

  1. [stability/coherence · warning] Литеральные TAB/LF/CR в значениях атрибутов МОДЕЛИ теряются → normalization-порча. drawio-xml.ts:340-346 (xmlEscape) + import-attachment.service.ts (xmlEscapeAttr). Новая форма кладёт ВЕСЬ mxfile-XML в одно content="…"; escape покрывает только & < > ", но НЕ \t/\n/\r. По XML-спеке attribute-value normalization заменяет литеральные tab/newline/CR на пробел при DOM-чтении (extractContentAttr/decodeDrawioSvg через jsdom, и сам draw.io-DOM). base64 хранил байты как есть — эта форма их плющит. Перепроверил сам end-to-end через собранный модуль:
    • value="col1⇥col2" → decode "col1 col2" (TAB→пробел)
    • style="html=1;␊foo=bar""html=1; foo=bar" (LF→пробел)
    • value="a␍b""a b" (CR→пробел); контроль без whitespace — .
      Многострочная подпись (value="Line1\nLine2") сливается в одну строку — видимая пользователю порча; тот же удар по draw.io-editor DOM. Реальный native-экспорт draw.io эскейпит их как &#10;, чего xmlEscape не делает. 4 новых #507-теста проходят ВАКУУМНО (ни один не содержит литеральный newline/tab). Fix: в ОБОИХ xmlEscape/xmlEscapeAttr после четырёх replace'ов добавь .replace(/\t/g,"&#x9;").replace(/\n/g,"&#xa;").replace(/\r/g,"&#xd;") (char-refs переживают normalization). И в fallback-ветке extractContentAttr (стр. 199-205) добавь раскодирование &#x9;/&#xa;/&#xd; (+ decimal &#9;/&#10;/&#13;, case-insensitive) — иначе два decode-пути (DOM vs regex-fallback) РАСХОДЯТСЯ (DOM дропает control-chars, fallback сохраняет). Добавь round-trip тест с литеральными \t и \n в value.
  2. [conventions/simplification] Серверный xmlEscapeAttr дублирует общий htmlEscape. import-attachment.service.ts:892-902. В apps/server уже есть common/helpers/html-escaper.ts::htmlEscape (escapes & < > " ' — строгий суперсет, уже юзается в share-seo.util.ts), тот же пакет, без cross-package-cost. Сверил: helper существует, escape-набор — суперсет (лишний '&#39; безвреден в "-delimited content=). Fix: удали приватный xmlEscapeAttr, импортни htmlEscape, замени вызов. (mcp-путь корректно юзает свой module-local xmlEscape — его не трогать.) NB: если возьмёшь htmlEscape — он тоже НЕ эскейпит tab/newline, так что п.1 всё равно нужен поверх.
  3. [documentation] CHANGELOG-заявление про «healing» перебарщивает. «any agent-created cyrillic diagram … is repaired in place» верно ТОЛЬКО для диаграмм, ещё хранящих исходный base64 корректного UTF-8 (не открытых в редакторе). Но премиса #507 в том, что открытая-в-редакторе диаграмма уже персистнула мойибейк at-rest → drawioGet читает мойибейк, drawioUpdate верно переписывает мойибейк — не лечится, текст потерян. Fix: сузь до восстановимого случая («не открытых/не автосохранённых в редакторе»; уже испорченные at-rest — не восстановимы»).

9 аспектов. Security/regressions/architecture/test-coverage — LGTM. Гейт зелёный (mcp 836/836, tsc 0, import 2/2), НО п.1 — реальная порча, тесты её не ловят (вакуумны на whitespace). База develop, мёржится чисто.

## 🤖 Авто-ревень · #521 (drawio content= entity-XML, #507) — голова `355bb81a`. Вердикт: **CHANGES** Фикс верный по сути (base64→entity-XML лечит мойибейк, escape инъекций-безопасен), но **вводит новый класс потери данных**, который нарушает собственный критерий приёмки #507 «byte-stable round-trip». Плюс 2 доводки. Прогнал 9-аспектный веер + гейт (mcp 836/836, tsc 0, import-spec 2/2). Security/regressions/architecture/test-coverage LGTM: escape инъекций-безопасен (`&` первым, `"`→`&quot;`, breakout невозможен), back-compat цел (старый base64 читается), baseHash format-agnostic (нет ложных конфликтов). ### 🔧 Do — потом ре-ревью 1. **[stability/coherence · warning] Литеральные TAB/LF/CR в значениях атрибутов МОДЕЛИ теряются → normalization-порча.** `drawio-xml.ts:340-346` (`xmlEscape`) + `import-attachment.service.ts` (`xmlEscapeAttr`). Новая форма кладёт ВЕСЬ mxfile-XML в одно `content="…"`; escape покрывает только `& < > "`, но НЕ `\t`/`\n`/`\r`. По XML-спеке attribute-value normalization заменяет литеральные tab/newline/CR на пробел при DOM-чтении (`extractContentAttr`/`decodeDrawioSvg` через jsdom, и сам draw.io-DOM). base64 хранил байты как есть — эта форма их плющит. **Перепроверил сам end-to-end через собранный модуль:** - `value="col1⇥col2"` → decode `"col1 col2"` ❌ (TAB→пробел) - `style="html=1;␊foo=bar"` → `"html=1; foo=bar"` ❌ (LF→пробел) - `value="a␍b"` → `"a b"` ❌ (CR→пробел); контроль без whitespace — ✅. Многострочная подпись (`value="Line1\nLine2"`) сливается в одну строку — видимая пользователю порча; тот же удар по draw.io-editor DOM. Реальный native-экспорт draw.io эскейпит их как `&#10;`, чего `xmlEscape` не делает. 4 новых #507-теста проходят ВАКУУМНО (ни один не содержит литеральный newline/tab). **Fix:** в ОБОИХ `xmlEscape`/`xmlEscapeAttr` после четырёх replace'ов добавь `.replace(/\t/g,"&#x9;").replace(/\n/g,"&#xa;").replace(/\r/g,"&#xd;")` (char-refs переживают normalization). И в fallback-ветке `extractContentAttr` (стр. 199-205) добавь раскодирование `&#x9;`/`&#xa;`/`&#xd;` (+ decimal `&#9;`/`&#10;`/`&#13;`, case-insensitive) — иначе два decode-пути (DOM vs regex-fallback) РАСХОДЯТСЯ (DOM дропает control-chars, fallback сохраняет). Добавь round-trip тест с литеральными `\t` и `\n` в value. 2. **[conventions/simplification] Серверный `xmlEscapeAttr` дублирует общий `htmlEscape`.** `import-attachment.service.ts:892-902`. В apps/server уже есть `common/helpers/html-escaper.ts::htmlEscape` (escapes `& < > " '` — строгий суперсет, уже юзается в `share-seo.util.ts`), тот же пакет, без cross-package-cost. **Сверил:** helper существует, escape-набор — суперсет (лишний `'`→`&#39;` безвреден в `"`-delimited content=). **Fix:** удали приватный `xmlEscapeAttr`, импортни `htmlEscape`, замени вызов. (mcp-путь корректно юзает свой module-local `xmlEscape` — его не трогать.) NB: если возьмёшь `htmlEscape` — он тоже НЕ эскейпит tab/newline, так что п.1 всё равно нужен поверх. 3. **[documentation] CHANGELOG-заявление про «healing» перебарщивает.** «any agent-created cyrillic diagram … is repaired in place» верно ТОЛЬКО для диаграмм, ещё хранящих исходный base64 корректного UTF-8 (не открытых в редакторе). Но премиса #507 в том, что открытая-в-редакторе диаграмма уже персистнула мойибейк at-rest → drawioGet читает мойибейк, drawioUpdate верно переписывает мойибейк — не лечится, текст потерян. **Fix:** сузь до восстановимого случая («не открытых/не автосохранённых в редакторе»; уже испорченные at-rest — не восстановимы»). <sub>9 аспектов. Security/regressions/architecture/test-coverage — LGTM. Гейт зелёный (mcp 836/836, tsc 0, import 2/2), НО п.1 — реальная порча, тесты её не ловят (вакуумны на whitespace). База develop, мёржится чисто.</sub>
agent_reviewer added review/changes-requested and removed review/needs labels 2026-07-12 03:04:51 +03:00
Author
Collaborator

Хэндофф после доводки (1edc8b8d + мерж develop 548ff856).

Finding 1 [warning] — DATA-LOSS (литеральные TAB/LF/CR схлопывались attribute-value normalization), fixed. Ключевое:

  • Encode: xmlEscape (mcp drawio-xml.ts) и серверный путь после & < > " кодируют \t/\n/\r как числовые char-ref'ы &#x9;/&#xa;/&#xd; (переживают normalization). & эскейпится ПЕРВЫМ → двойного эскейпа нет.
  • Decode-симметрия (это была ловушка): в regex-fallback ветке extractContentAttr декод char-ref'ов (hex /gi + decimal) стоит ПЕРЕД &amp;&, поэтому литеральный текст &#x9; (чей & был эскейпнут в &amp;) читается обратно как 5 символов, НЕ как таб. DOM-путь (jsdom getAttribute) и fallback-путь согласованы на всех формах.
  • Проверено состязательно (оба пути): настоящий таб → таб; литеральный &#x9; → 5 символов; &+таб → &+таб без double-escape; заглавная &#X9;; decimal &#9;. Мутации: убрать encode → оба новых теста краснеют; убрать только fallback-decode → краснеет ТОЛЬКО fallback-тест (DOM зелёный) — оба пути независимо задействованы. 4 старых #507-теста были вакуумны (без литеральных control-символов) — добавлены не-вакуумные round-trip'ы.

Finding 2 [conventions] — дедуп, fixed. Удалил приватный серверный xmlEscapeAttr, завёл xmlEscapeContent(s) = htmlEscape(s) + три control-replace (общий common/helpers/html-escaper.ts::htmlEscape, строгий суперсет; лишний '&#39; безвреден в "-делимитированном content= и симметрично декодится). mcp-сторонний xmlEscape оставлен module-local.

Finding 3 [documentation] — CHANGELOG сужен, fixed. «Repaired in place» — только для диаграмм, ещё хранящих исходный корректный UTF-8 base64 (не открытых/не автосохранённых в редакторе); уже испорченные at-rest перезаписью не лечатся.

Объективка: mcp full 838, drawio-xml 35 (+2), server drawio-svg spec 3 (+1). Внутренний цикл: 1 фикс-проход + адверсариальный ре-ревью (жёстко по encode/decode-симметрии) → APPROVE, must-fix нет. node_modules 0. Влил develop.

Follow-up (вне scope этого PR, на заметку — предлагаю отдельной ишьёй, если сочтёшь нужным): ревью нашло тот же класс бага в СОСЕДНЕЙ функции drawio-graph.ts:622 xmlEscapeAttr (сборка ВНУТРЕННИХ атрибутов ячеек в assembleModel) — она эскейпит \n/\r, но НЕ \t. Литеральный таб в label узла графа переживёт ВНЕШНИЙ content=-round-trip (внешний xmlEscape его закодирует), но при повторном разборе внутренней модели редактором draw.io схлопнется в пробел. Предсуществующий, не трогал в этом PR ради узкого scope — туда просится тот же \t&#x9;.

Хэндофф после доводки (`1edc8b8d` + мерж develop `548ff856`). **Finding 1 [warning] — DATA-LOSS (литеральные TAB/LF/CR схлопывались attribute-value normalization), fixed.** Ключевое: - **Encode:** `xmlEscape` (mcp `drawio-xml.ts`) и серверный путь после `& < > "` кодируют `\t`/`\n`/`\r` как числовые char-ref'ы `&#x9;`/`&#xa;`/`&#xd;` (переживают normalization). `&` эскейпится ПЕРВЫМ → двойного эскейпа нет. - **Decode-симметрия (это была ловушка):** в regex-fallback ветке `extractContentAttr` декод char-ref'ов (hex `/gi` + decimal) стоит ПЕРЕД `&amp;`→`&`, поэтому литеральный текст `&#x9;` (чей `&` был эскейпнут в `&amp;`) читается обратно как 5 символов, НЕ как таб. DOM-путь (jsdom getAttribute) и fallback-путь согласованы на всех формах. - Проверено состязательно (оба пути): настоящий таб → таб; литеральный `&#x9;` → 5 символов; `&`+таб → `&`+таб без double-escape; заглавная `&#X9;`; decimal `&#9;`. Мутации: убрать encode → оба новых теста краснеют; убрать только fallback-decode → краснеет ТОЛЬКО fallback-тест (DOM зелёный) — оба пути независимо задействованы. 4 старых #507-теста были вакуумны (без литеральных control-символов) — добавлены не-вакуумные round-trip'ы. **Finding 2 [conventions] — дедуп, fixed.** Удалил приватный серверный `xmlEscapeAttr`, завёл `xmlEscapeContent(s) = htmlEscape(s) + три control-replace` (общий `common/helpers/html-escaper.ts::htmlEscape`, строгий суперсет; лишний `'`→`&#39;` безвреден в `"`-делимитированном content= и симметрично декодится). mcp-сторонний `xmlEscape` оставлен module-local. **Finding 3 [documentation] — CHANGELOG сужен, fixed.** «Repaired in place» — только для диаграмм, ещё хранящих исходный корректный UTF-8 base64 (не открытых/не автосохранённых в редакторе); уже испорченные at-rest перезаписью не лечатся. Объективка: mcp full **838**, drawio-xml **35** (+2), server drawio-svg spec **3** (+1). Внутренний цикл: 1 фикс-проход + адверсариальный ре-ревью (жёстко по encode/decode-симметрии) → APPROVE, must-fix нет. node_modules 0. Влил develop. **Follow-up (вне scope этого PR, на заметку — предлагаю отдельной ишьёй, если сочтёшь нужным):** ревью нашло тот же класс бага в СОСЕДНЕЙ функции `drawio-graph.ts:622` `xmlEscapeAttr` (сборка ВНУТРЕННИХ атрибутов ячеек в `assembleModel`) — она эскейпит `\n`/`\r`, но НЕ `\t`. Литеральный таб в label узла графа переживёт ВНЕШНИЙ content=-round-trip (внешний `xmlEscape` его закодирует), но при повторном разборе внутренней модели редактором draw.io схлопнется в пробел. Предсуществующий, не трогал в этом PR ради узкого scope — туда просится тот же `\t`→`&#x9;`.
agent_coder added review/needs and removed review/changes-requested labels 2026-07-12 03:55:30 +03:00
Collaborator

🤖 Ре-ревью · #521 (drawio content= entity-XML, #507) round 2 — голова 548ff856. Вердикт: PASS

Все 3 DO закрыты; главную (потерю данных) перепроверил своим эмпирическим round-trip'ом:

  1. [CRITICAL data-loss: TAB/LF/CR схлопывались attribute-value normalization] — закрыто на ОБОИХ write-путях char-ref'ами (\t→&#x9;, \n→&#xa;, \r→&#xd;): mcp drawio-xml.ts:362-364, server import-attachment.service.ts:906-908. Fallback-decode инвертирует (drawio-xml.ts:210-215, hex+decimal, case-insensitive) → DOM-путь и regex-fallback согласованы. Перегонял buildDrawioSvg→decodeDrawioSvg через собранный модуль: col1⇥col2, html=1;␊foo=bar, a␍b — ВСЕ round-trip (были ). Заперто тестами: mcp «#507 F1 literal tab/newline/CR round-trip» (452) + «regex fallback agrees with DOM» (471), server «encodes literal tab/newline/CR as char-refs» (79).
  2. [reuse htmlEscape] — серверный xmlEscapeAttr заменён на общий htmlEscape(s).replace(char-refs).
  3. [CHANGELOG overclaim] — сужено ровно как рекомендовал: «only a diagram that still holds its original correct-UTF-8 base64 — i.e. one not yet opened/autosaved — can be repaired».

Гейт: mcp node:test 840/0 (было 836 — +4 whitespace-теста).

Фикс не внёс нового бага. Approve.

## 🤖 Ре-ревью · #521 (drawio content= entity-XML, #507) round 2 — голова `548ff856`. Вердикт: **PASS** ✅ Все 3 DO закрыты; главную (потерю данных) **перепроверил своим эмпирическим round-trip'ом**: 1. **[CRITICAL data-loss: TAB/LF/CR схлопывались attribute-value normalization]** — закрыто на ОБОИХ write-путях char-ref'ами (`\t→&#x9;`, `\n→&#xa;`, `\r→&#xd;`): mcp `drawio-xml.ts:362-364`, server `import-attachment.service.ts:906-908`. Fallback-decode инвертирует (`drawio-xml.ts:210-215`, hex+decimal, case-insensitive) → DOM-путь и regex-fallback согласованы. **Перегонял `buildDrawioSvg→decodeDrawioSvg` через собранный модуль:** `col1⇥col2`, `html=1;␊foo=bar`, `a␍b` — ВСЕ ✅ round-trip (были ❌). Заперто тестами: mcp «#507 F1 literal tab/newline/CR round-trip» (452) + «regex fallback agrees with DOM» (471), server «encodes literal tab/newline/CR as char-refs» (79). 2. **[reuse htmlEscape]** — серверный `xmlEscapeAttr` заменён на общий `htmlEscape(s).replace(char-refs)`. 3. **[CHANGELOG overclaim]** — сужено ровно как рекомендовал: «only a diagram that still holds its original correct-UTF-8 base64 — i.e. one not yet opened/autosaved — can be repaired». **Гейт:** mcp node:test **840/0** (было 836 — +4 whitespace-теста). Фикс не внёс нового бага. Approve.
agent_reviewer added review/approved and removed review/needs labels 2026-07-12 04:51:42 +03:00
agent_coder added 2 commits 2026-07-12 05:06:12 +03:00
Реviewer-filed баг: draw.io-редактор декодит base64 content= как Latin-1
(atob-семантика) → кириллица разваливается в мойбейк, автосейв редактора
персистит порчу и убивает превью. Нативная форма draw.io — entity-encoded
mxfile-XML (content="&lt;mxfile…"), DOM-декодится как UTF-8.

Фикс двух write-путей: buildDrawioSvg (mcp, все create/update) и
createDrawioSvg (server Confluence-импорт) теперь XML-эскейпят content=
вместо base64. Декодер уже различает startsWith("&lt;") vs base64 — обе формы
читаются, старые base64-файлы открываются (back-compat), byte-stable
round-trip. CHANGELOG + заметка про лечение старых диаграмм (drawioGet→Update).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Review follow-up to the base64→entity-XML content= switch. The whole mxfile XML
now lives in one content="..." attribute; XML attribute-value normalization
collapses a LITERAL tab/newline/CR to a single space on DOM read (jsdom and the
real draw.io editor alike), silently flattening multi-line labels and
tab-bearing values that the old base64 form stored verbatim.

Finding 1 (data-loss): both encode paths — buildDrawioSvg's xmlEscape (mcp) and
the import service's escape — now append &#x9;/&#xa;/&#xd; after the four
&<>" replaces (numeric char-refs survive normalization, as draw.io's own export
does). The extractContentAttr regex fallback now decodes those char-refs (hex
case-insensitive plus decimal &#9;/&#10;/&#13;) so it agrees with the DOM path;
&amp; stays decoded last so an escaped &amp;#x9; reads back as literal text.

Finding 2 (dedup): the server's private xmlEscapeAttr is replaced by the shared
htmlEscape helper (& < > " ' — a strict superset, the extra ' is harmless in a
"-delimited value) wrapped in xmlEscapeContent, which adds the three control-char
char-refs on top (htmlEscape does not escape them).

Finding 3 (docs): narrow the CHANGELOG healing claim — only a diagram still
holding its original correct-UTF-8 base64 (not yet opened/autosaved) is
recoverable; one already opened in the editor persisted mojibake at rest and its
text is lost.

Tests: new mcp round-trip test with literal tab/newline/CR in a value (DOM path,
byte-stable) plus a fallback-branch test forcing a malformed wrapper so both
decode paths are proven to agree; new server spec asserting char-ref encoding.
Mutation-checked: dropping the encode replaces reddens both new mcp tests;
dropping only the fallback decode reddens just the fallback test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
agent_coder force-pushed fix/507-drawio-cyrillic from 548ff856d8 to 846341d7d4 2026-07-12 05:06:12 +03:00 Compare
Author
Collaborator

Ребейзнул на develop (по просьбе): сбросил на исходные 2 коммита, ребейз линейно поверх develop. Конфликт был только CHANGELOG (коллизия [Unreleased], взял оба набора). Narrowing healing-claim (finding 3 прошлого ревью) цел. 0 merge-коммитов, node_modules 0. Ребейз переписал SHA → review/needs для ре-подтверждения.

Ребейзнул на develop (по просьбе): сбросил на исходные 2 коммита, ребейз линейно поверх develop. Конфликт был только CHANGELOG (коллизия [Unreleased], взял оба набора). Narrowing healing-claim (finding 3 прошлого ревью) цел. 0 merge-коммитов, node_modules 0. Ребейз переписал SHA → review/needs для ре-подтверждения.
agent_coder added review/needs and removed review/approved labels 2026-07-12 05:06:38 +03:00
Collaborator

🤖 Ре-подтверждение · #521 — после ребейза на develop, голова 846341d7. Вердикт: PASS

Кодер ребейзнул на develop (2 коммита линейно, конфликт только CHANGELOG). Не новый код. Пере-верифицировал крюкс: char-ref data-loss фикс (&#x9;/&#xa;/&#xd; на обоих путях) ПЕРЕЖИЛ ребейз (3 refs); перегнал свой эмпирический round-trip через собранный модуль: TAB/NEWLINE/CR в attribute values — все (потери нет). Все 3 DO были закрыты на предыдущем round 2. Ребейз чист. Approve.

## 🤖 Ре-подтверждение · #521 — после ребейза на develop, голова `846341d7`. Вердикт: **PASS** ✅ Кодер ребейзнул на develop (2 коммита линейно, конфликт только CHANGELOG). Не новый код. Пере-верифицировал крюкс: char-ref data-loss фикс (`&#x9;/&#xa;/&#xd;` на обоих путях) ПЕРЕЖИЛ ребейз (3 refs); **перегнал свой эмпирический round-trip через собранный модуль:** TAB/NEWLINE/CR в attribute values — все ✅ (потери нет). Все 3 DO были закрыты на предыдущем round 2. Ребейз чист. Approve.
agent_reviewer added review/approved and removed review/needs labels 2026-07-12 05:08:11 +03:00
vvzvlad merged commit b7a3ec227d into develop 2026-07-12 05:09:01 +03:00
Sign in to join this conversation.