Commit Graph

16 Commits

Author SHA1 Message Date
Nick Shirokov 929d1676bb feat(form-decompile,form-compile): формат и формат редактирования (Format/EditFormat)
Ключи format/editFormat на InputField/LabelField/CheckBoxField (1408/958
файлов в корпусе). LocalStringType как inputHint/title: строка или {ru,en} —
переиспользование Emit-MLText (компилятор) и Get-LangText (декомпилятор).
Декомпилятор: хелпер Add-FormatProps в 3 ветках. Зеркало py.

Round-trip чистый (0 остатка на 30 формах с Format/EditFormat). Кейс
input-fields: format/editFormat строкой на input/check + мультиязык-объект
на labelField; снэпшот сертифицирован загрузкой в 1С.

Заодно добавлены забытые ключи (format/editFormat/choiceParameters/
choiceParameterLinks/typeLink) в allowlist knownKeys (ps1+py), чтобы не
сыпать ложный warning «unknown key».

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 22:53:29 +03:00
Nick Shirokov f9ae24a678 fix(form-compile): пустая строка-значение self-closing + Enum.X.EmptyRef без EnumValue
Два общих бага value (всплыли на полном прогоне 2.17, чинят и choiceList,
и параметры выбора):

- Пустое строковое значение эмитилось <Value xsi:type="xs:string"></Value>
  вместо самозакрывающегося <Value xsi:type="xs:string"/>. Введён хелпер
  Get-ChoiceValueTag (3 места: choiceList scalar + choiceParam scalar +
  FixedArray inner). Форма АктивныеПользователи теперь round-trip match.
- Enum.X.EmptyRef нормализатор ломал вставкой .EnumValue. → EnumValue.EmptyRef
  (EmptyRef — пустая ссылка перечисления, не значение). Фикс в Normalize-
  ChoiceValue (Enum-ветка): EmptyRef сохраняется как есть.

Зеркало py. Кейсы: input-fields (пустая строка в choiceList), radio-auto-enum
(Enum.X.EmptyRef) — оба сертифицированы загрузкой в 1С. Регресс 36/36 ps1+py.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 22:27:04 +03:00
Nick Shirokov 339c70b457 feat(form-compile): xs:dateTime в значениях параметров выбора / choiceList
Авто-детект ISO-datetime (^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$) в
Normalize-ChoiceValue → xs:dateTime вместо xs:string. Без изменения DSL:
декомпилятор уже отдаёт строку, компилятор распознаёт формат. Заодно
исправляет choiceList со значениями-датами (та же FormChoiceListDesTimeValue).

Round-trip бит-в-бит на 3 формах с датами в параметрах выбора. Кейс
input-fields: Отбор.Дата в объектной и короткой формах; снэпшот
сертифицирован загрузкой в 1С. Закрывает микро-хвост кластера ChoiceParameters.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 22:11:34 +03:00
Nick Shirokov 65f63fbc48 feat(form-compile): короткая форма для параметров выбора / связей / связи по типу
Входной сахар (декомпилятор по-прежнему пишет объектную модель):
- choiceParameters: ["Отбор.Х=true", "Отбор.Вид=Enum.A, Enum.B"] — name=value,
  запятые → массив, литералы коэрсятся (true/false → bool, число → number,
  остальное → строка/ref через Normalize-ChoiceValue).
- choiceParameterLinks: ["Отбор.Орг=ОбычноеПоле", "Отбор.Тип=Поле:DontChange"] —
  name=dataPath, опц. хвост :Clear/:DontChange (дефолт Clear).
- typeLink: "ПолеПодсказка" или "ПолеПодсказка#0".

Парсеры на входе каждого эмиттера (строка → объект), далее общий путь.
Байт-в-байт идентично объектной форме (проверено ps1+py). Кейс input-fields:
поле ПолеСвязиКратко на короткой форме рядом с объектным; снэпшот
сертифицирован загрузкой в 1С. Версия компилятора синхронизирована (py 1.67→1.69).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 22:05:30 +03:00
Nick Shirokov 0397d8f37e feat(form-decompile,form-compile): параметры выбора / связи параметров выбора / связь по типу (кластер ChoiceParameters)
Покрытие трёх конструкций поля ввода (InputField), массовых в корпусе
(ChoiceParameters 844 / ChoiceParameterLinks 685 / TypeLink 84 файлов):

- choiceParameters: [{name, value}] — параметры выбора. value через общий
  Normalize-ChoiceValue (bool/число/строка/ref-путь + синонимы Перечисление./
  Справочник.); массив значений → v8:FixedArray. Presentation всегда пустой.
- choiceParameterLinks: [{name, dataPath, valueChange?}] — связи параметров
  выбора. valueChange дефолт Clear (опускается декомпилятором), forgiving
  Clear/DontChange + рус.синонимы. DataPath xsi:type=xs:string.
- typeLink: {dataPath, linkItem} — связь по типу. linkItem дефолт 0.

Декомпилятор: регистрация app namespace; инверсные хелперы (FixedArray →
массив, дефолт Clear опускается). Компилятор ps1 + зеркало py (байт-в-байт).
Spec: секция в #### input. Тест-кейс input-fields расширен полем со всеми
тремя конструкциями; round-trip бит-в-бит на 3 реальных формах; снэпшот
сертифицирован загрузкой в 1С 8.3.24.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 21:59:26 +03:00
Nick Shirokov 5112dbec9e feat(form-decompile,form-compile): HorizontalStretch/VerticalStretch — захват явного false
Растягивание (<HorizontalStretch>/<VerticalStretch>) платформа эмитит явным значением
(false 38145 / true 25002 для HS; на Input/Label/Picture/Group/CommandBar). Декомпилятор/
компилятор работали только с true → явный false терялся.

Теперь захват и эмиссия фактического значения (true И false); отсутствие = дефолт
(не эмитим). Бэк-совместимо: true как раньше, +false. Раньше декомпилятор писал ключ
лишь при true — теперь и при false.

TOTAL diff lines выборки 2.17: 2912 → 2727 (-185), match 20 → 22. Stretch residual
92 → 1 (остаток — на companion ExtendedTooltip, отдельный кластер). Снапшот input-fields
(+stretch false) сертифицирован в 1С (8.3.24). Регресс form-compile 34/34 зелёный
на ps + python. decompile v0.40, compile v1.58.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 15:11:12 +03:00
Nick Shirokov 701d56b075 feat(form-decompile,form-compile): размазанный блок скаляров InputField + общие cell-свойства полей
Партия простых скаляров полей, которые не захватывались (платформа эмитит явное
не-дефолтное значение):
  - InputField-специфичные: Wrap, OpenButton, ListChoiceMode, ExtendedEditMultipleValues,
    ChooseType, ChoiceButtonRepresentation — в Emit-Input / InputField-кейс.
  - Общие cell-свойства поля-колонки (Input/Label/Picture/CheckBox/ColumnGroup):
    ShowInHeader, ShowInFooter, AutoCellHeight, FooterHorizontalAlign, HeaderHorizontalAlign —
    вынесены в общий Emit-CommonElementProps / Add-Layout (захват «как есть»).
    ColumnGroup: собственная эмиссия ShowInHeader убрана (общий путь покрывает) —
    устранён двойной эмит.

TOTAL diff lines выборки 2.17: 3179 → 2912 (-267), match 17 → 20 (+3 чистых формы).
Все обработанные скаляры residual → 0. Снапшот input-fields (+скаляры) сертифицирован
в 1С (8.3.24). Регресс form-compile 34/34 зелёный на ps + python.
decompile v0.39, compile v1.57.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 14:58:17 +03:00
Nick Shirokov daf7f1526a feat(form-decompile,form-compile): choiceList у InputField (переиспользование радио)
ChoiceList (<ChoiceList>) встречается на RadioButtonField (уже было) и InputField
(2142 в корпусе) — не захватывался у InputField. Логику вынесли в общие хелперы
Emit-ChoiceList / Decompile-ChoiceList (PS1) и emit_choice_list (PY), подключили к
обоим полям. Грамматика та же: [ { value, presentation?/title? } ] (+ рус. синонимы),
авто-вывод presentation. Порядок в InputField: после input-свойств/InputHint, до companions.

TOTAL diff lines выборки 2.17: 5149 → 4443 (-706). InputField>ChoiceList закрыт
(остаток ~5 — другое: app:value в app-неймспейсе = списки выбора параметров/настроек;
ChoiceListButton = отдельное input-свойство). Снапшот input-fields сертифицирован в 1С
(8.3.24). Регресс form-compile 33/33 зелёный на ps + python. decompile v0.33, compile v1.51.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 22:33:32 +03:00
Nick Shirokov 908af27bf0 feat(form-decompile,form-compile): tooltipRepresentation элемента (кластер ToolTipRepresentation)
<ToolTipRepresentation> (режим показа подсказки: None/Button/ShowBottom/ShowTop/
ShowLeft/ShowRight/ShowAuto/Balloon) — общее свойство элемента (Button 13785,
Popup 6417, ButtonGroup, InputField, CheckBoxField, LabelDecoration, группы и
др.; None доминирует — 25241). Терялся: декомпилятор не читал, компилятор не эмитил.

Введён общий passthrough-ключ tooltipRepresentation:
- декомпилятор: захват в Add-CommonProps;
- компилятор: эмиссия в Emit-Title (после ToolTip) — покрывает все эмиттеры,
  зовущие Emit-Title; плюс отдельно в Emit-Label (свой title-блок, не зовёт
  Emit-Title).

Декомпилятор (ps1) + компилятор (ps1+py) + spec §4.1. Покрытие: input-fields
(input, ShowBottom), events (label-декорация, Button) — сертифицировано в 1С
8.3.24. Раундтрип БанковскиеСчета/Wildberries: остаток ToolTipRepresentation = 0.
Регресс ps+py 33/33.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 16:02:06 +03:00
Nick Shirokov 22e929ecb3 feat(form-decompile,form-compile): tooltip элемента + фикс экранирования текста (кластер ToolTip)
Два дефекта вокруг текста <v8:content>, оба вскрылись на формах с подсказками.

1. ToolTip элемента (484 LOST в корпусе). <ToolTip> — прямой мультиязычный
   текст подсказки на элементе (UsualGroup 42150, Popup, Page, InputField,
   и почти все типы). Декомпилятор пропускал (как companion), компилятор не
   эмитил. Введён общий ключ tooltip (string|{ru,en}), как title:
   - декомпилятор: захват в Add-CommonProps;
   - компилятор: эмиссия в Emit-Title (сразу после Title) — покрывает все
     эмиттеры, зовущие Emit-Title.
   Попутно выяснилось, что Emit-Pages/Emit-CommandBar вовсе не звали Emit-Title
   (теряли и Title, и ToolTip), а Emit-Label эмитит Title по-своему — во все три
   добавлена обработка title/tooltip.

2. Экранирование кавычек. Esc-Xml экранировал " → &quot; в тексте элемента,
   но 1С в <v8:content> пишет " литерально (экранирует только & < >).
   Это ломало раундтрип любого текста с кавычками. Убрано экранирование " .

Декомпилятор (ps1) + компилятор (ps1+py) + spec (§4.1 tooltip). Покрытие:
input-fields (input+tooltip), pages (pages/page tooltip, page с кавычкой в
тексте — проверяет литеральность) — сертифицировано в 1С 8.3.24. Раундтрип
БанковскиеСчета/Wildberries/АдреснаяКнига: ToolTip и &quot; остаток = 0.
Регресс ps+py 33/33.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 15:36:30 +03:00
Nick Shirokov c43041c0b7 feat(form-decompile,form-compile): TitleLocation у LabelField/PictureField/Table (кластер TitleLocation)
TitleLocation обрабатывался только у input (passthrough), check/radio
(smart-default) и calendar. У LabelField (7362 в корпусе), PictureField (2479)
и Table (381) тег молча терялся — ни декомпилятор, ни компилятор его не знали.

Профиль доли элементов с тегом: Table 2.9%, LabelField 15.8%, PictureField
80.5% (но 20% без тега). Платформа НЕ всегда эмитит → выбран passthrough
(эмитим при наличии ключа, как у input/calendar), не smart-default. Корректно
и консистентно; переиспользован существующий ключ titleLocation + Map-TitleLoc.

Декомпилятор (ps1): захват titleLocation в трёх ветках. Компилятор (ps1+py):
эмиссия в Emit-LabelField/Emit-Table/Emit-PictureField в позиции по схеме.
spec §4.1: titleLocation вынесен в общие свойства с пометкой охвата.

Тест-покрытие добавлено в input-fields (labelField=left), picture-field
(picField=none), table (table=top) — снэпшоты сертифицированы в 1С 8.3.24.
Раундтрип 60 форм с TitleLocation на label/pic/table/radio: остатка нет.
Регресс ps+py 33/33.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 13:33:05 +03:00
Nick Shirokov b4fc9bf42c feat(form-decompile,form-compile): листовые свойства полей + фикс Hiperlink (кластер L)
БАГ: у LabelField платформенный тег <Hiperlink> (опечатка 1С), компилятор
эмитил <Hyperlink> — гиперссылка не работала и не роундтрипилась. Проверено
по корпусу: LabelField→Hiperlink во всех версиях формата (2.17 и 2.20).

- compiler PS1+PY: LabelField <Hiperlink>; EditMode (input/check/labelField);
  CheckBoxType (check, умный дефолт Auto + suppress как radioButtonType).
- decompiler: editMode, checkBoxType (Auto→опустить), markIncomplete (раньше не ловился),
  labelField читает <Hiperlink>.
- docs/form-dsl-spec: editMode, checkBoxType, примечание про Hiperlink.
- tests: input-fields расширен (editMode/checkBoxType/labelField+hyperlink), сертифицирован.

Регресс 32/32 PS1+PY, churn по флажкам обновлён и сертифицирован.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 20:29:31 +03:00
Nick Shirokov 0941fc717d feat(form-decompile,form-compile): семантика TitleLocation (кластер G2)
Принцип: компилятор не эмитит значение, равное дефолту платформы (который
платформа сама не пишет в XML). Умный дефолт (check→Right, radio→None) —
отдельная вещь, эмитится (он ≠ дефолт платформы Left).

- net ключа titleLocation → умный дефолт; titleLocation: "" → подавить
  (дефолт платформы); значение → эмитить с маппингом регистра.
- compiler PS1+PY: Emit-TitleLocation/emit_title_location + Map-TitleLoc
  (общий маппинг; у check раньше его не было — сырьё).
- decompiler: Add-TitleLocation (дефолт → опустить, нет тега → "", иначе значение).
- docs/form-dsl-spec: семантика titleLocation у check/radio.
- tests: input-fields расширен (Right-дефолт / ""-подавление / явный Top), сертифицирован.

АварийныйРежим: полный MATCH. Регресс 32/32 PS1+PY, churn нулевой.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 18:53:28 +03:00
Nick Shirokov 20adf4f463 fix(tests): correct ExternalDataProcessorObject→DataProcessorObject in config-context DSLs
Fix test DSLs that used ExternalDataProcessorObject (EPF type) for
DataProcessors inside configurations. Also fix: chart-of-accounts
(remove maxExtDimensionCount without ПВХТ), calculation-register
(remove actionPeriod without infrastructure), document-multiple-tabparts
(remove registerRecords referencing non-existent register),
role-compile/explicit-rights (add dimensions to empty InformationRegister).

Regenerated all affected snapshots.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 20:10:49 +03:00
Nick Shirokov 0778cc89ee feat: post-run validation + integration tests for skill pipeline
- runner.mjs v0.4: --with-validation flag runs validators on real output
- postValidate config in 20 _skill.json files (maps skill → validator)
- validatePath in ~100 positive test cases
- skipValidation for 5 cross-reference cases (isolated workspace limitation)
- Integration tests: build-config (19 steps), build-epf (6), build-cfe (4)
- base-config cache from build-config for downstream tests
- Fix chart-of-calculation-types test data (DependenceOnCalculationTypes)
- 285/285 unit + 3/3 integration, all green with validation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 17:30:03 +03:00
Nick Shirokov a1b3fdd4e2 feat: deepen skill test coverage — 52 → 247 cases across all 43 skills
Add 195 new test cases covering examples from SKILL.md, edge cases,
and parameter combinations. Create _skill.json for form-edit, skd-edit,
subsystem-edit. Add fixtures for negative validate cases. Fix
normalizeUuids in meta-validate/meta-info configs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 15:38:06 +03:00