Commit Graph
4 Commits
Author SHA1 Message Date
Nick ShirokovandClaude Opus 5 974ca3aac9 fix(form,skd,init,meta-edit): развести экранирование атрибута и текста
esc_xml был один на две задачи, и в атрибутном контексте применялся текстовый
вариант без ". form-compile с choiceParameters, имя которого содержит
кавычку, выдавал <app:item name="Отбор.Наименование "кавычка"">: lxml падает с
attributes construct error, то есть файл невалиден как XML. Затронуто 9 мест в
form-compile и 3 в skd-compile, одинаково в обоих портах.

Раундтрип через базу показал границу: в ТЕКСТЕ элемента платформа экранирует
только & < > (кавычка и апостроф возвращаются сырыми байт-в-байт), а в ЗНАЧЕНИИ
АТРИБУТА пишет &quot; — внутри "..." литеральная кавычка невалидна. Поэтому две
функции с говорящими именами, а не одна с флагом:
  esc_xml      — значение атрибута: & < > "
  esc_xml_text — текст элемента:    & < >

Заодно закрыто расхождение портов в init-навыках: PY экранировал текст с &quot;,
PS1 — через SecurityElement::Escape (ещё и &apos;), а epf-init/erf-init в PS1 не
экранировали вовсе, из-за чего амперсанд в синониме давал невалидный XML.

Кейсы: form-compile/attr-value-escaping, skd-compile/additional-properties-escaping,
cf-init/synonym-escaping — все три проверены негативным прогоном на обоих портах
и верификацией снэпшотов на платформе.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-08 20:53:12 +03:00
Nick ShirokovandClaude Opus 5 826ba3de71 fix(form,meta,skd): resolve_type_str — одно тело + срезание префикса типа
Шесть копий resolve_type_str разошлись на 6 вариантов в PY и 4 в PS1, а вместе
с формой разошлось и поведение: префикс ссылочного типа срезал только
form-compile.

Проверка на платформе (стенд 8.3.24.1691, cf-init → meta-compile → db-load-xml)
показала, что это не косметика. Префикс ломает поиск в словаре синонимов, из-за
чего русское имя типа остаётся непереведённым:
  СправочникСсылка.Склады      → cfg:CatalogRef.Склады        (верно)
  cfg:СправочникСсылка.Склады  → cfg:СправочникСсылка.Склады  (неверно)
Платформа отвечает «Неизвестное имя типа - СправочникСсылка.Склады» и
отклоняет загрузку. Именно с префиксом тип и написан в выгрузке, откуда
пользователь его копирует.

cfg: снимается всегда, d5p1: — только у ссылочных типов (с точкой): сам по себе
префикс неоднозначен, в формах d5p1:Chart, d5p1:TextDocument и ещё три типа
адресуют свои пространства имён, и там он часть канонического значения. Первая
версия правки срезала его безусловно и уронила 4 кейса form-compile.

Тело общее для всех шести навыков; словари синонимов остаются локальными, навык
объявляет на свой словарь алиас TYPE_SYNONYMS / $script:typeSynonyms.

Регресс-кейс meta-compile/type-prefix-lenient проверяет все три формы ввода.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-08 19:44:39 +03:00
Nick ShirokovandClaude Opus 5 d99d63288e refactor(skills): detect_format_version — один вариант на всех потребителей
Семья была разбита на «знает про автономную EPF/ERF» (form-*, mxl-compile,
template-add, help-add) и «не знает» (cfe-borrow, interface-edit, meta-compile,
role-compile, subsystem-compile, xdto-compile), плюс редакторски разошедшаяся
PS1-копия help-add.

Расширенный вариант корректен и для конфигурационных навыков: ветка срабатывает
только если <каталог>.xml — корень ExternalDataProcessor/ExternalReport, чего в
дереве конфигурации не бывает. Переключатель не нужен — раскопирован как есть.

Семья в реестре схлопнута до одного варианта: 11 копий, оба порта.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-08 18:18:52 +03:00
Nick ShirokovandClaude Opus 5 c8144a01e5 test(skills): реестр и гард общих inline-реализаций
Навыки автономны, общие утилиты копируются в каждый .ps1/.py, но нигде не было
зафиксировано, какая копия эталонная и какие расхождения законны. Ревизия по #60
показала два класса семей: одни держатся побайтово (support-guard — 16 копий,
db-обвязка — 12), другие разъехались без эталона (resolve_type_str — 6 копий и
6 вариантов, get_ml_text — 7 и 7).

check-inline-drift.mjs держит реестр семей внутри себя: вариант → эталон → копии.
Копия обязана совпадать с эталоном своего варианта; отклоняющийся вариант обязан
иметь обоснование, иначе печатается как долг. Часть расхождений законна (esc_xml
без &quot; в form-* ради раундтрипа), поэтому модель хранит варианты, а не одно
эталонное тело. Разъехавшиеся целиком семьи стоят на храповике maxVariants.

Извлечение тел: PS1 — до строки ровно `}` (балансировка скобок даёт ложные
18 вариантов из 18 копий Assert-EditAllowed); PY — с обязательным снятием
docstring-ов (иначе одинаковый код с разным описанием читается как расхождение).

check-all.mjs — единая точка входа: check-enum-drift и check-uuid-invariant были
рабочими, но не упоминались в README и никем не запускались.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-08 17:22:33 +03:00