Commit Graph

101 Commits

Author SHA1 Message Date
Nick Shirokov a5a1636918 feat(skd-validate): catch broken XDTO in valueType and value
skd-validate was purely structural (names/refs/duplicates) and missed an
entire class of bugs that XDTO rejects at db-load-xml — exactly the
kinds of mistakes the LLM (or hand-edits) commonly introduce.

New section 16: valueType structural — each <v8:Type> must have a known
prefix (xs:/v8: or any prefix bound to enterprise/current-config),
qualifier blocks must match their preceding type, and qualifier
internals (Digits/FractionDigits/AllowedSign, Length/AllowedLength,
DateFractions) must use legal tokens.

New section 17: value content — <value xsi:type="dcscor:DesignTimeValue">
rejects literal placeholders ('_') and empty strings, since these are
the exact symptom of the titan team's BUG-2.

5 new fixtures cover: bare-decimal, missing-qualifiers,
qualifier/type mismatch, ref-literal '_', bad AllowedSign token.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 11:57:20 +03:00
Nick Shirokov 05374100c1 fix(skd-compile): accept bare decimal and decimal(N) with sensible defaults
Emit-SingleValueType / emit_single_value_type previously required full
decimal(D,F) — anything else fell through to a fallback that produced
invalid <v8:Type>decimal</v8:Type> (no xs: prefix, no qualifiers).

New regex `^decimal(\((\d+)(,(\d+))?(,nonneg)?\))?$` accepts:
- decimal                → 10,2,Any (money default — most common 1C intent)
- decimal(N)             → N,0,Any (integer)
- decimal(N,nonneg)      → N,0,Nonnegative
- decimal(N,M)           → as before
- decimal(N,M,nonneg)    → as before

Synonyms (число, число(N), etc.) inherit the same forms via Resolve-TypeStr.

Shared Emit-ValueType is called from fields, parameters, and output
parameters — one fix covers all three paths. 3 existing snapshots
regenerated with proper xs:decimal + qualifiers, plus new
decimal-qualifier-defaults test case covering all 5 forms × synonyms.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 11:45:23 +03:00
Nick Shirokov 449f814d16 fix(skd-compile): Designer-compatible empty parameter values
Centralized empty-value handling: shorthand `=`, `= _`, `= null` and
object-form `value: null` / `""` now serialize per type, matching what 1C
Designer writes:
- ref / no-type → <value xsi:nil="true"/>
- string → <value xsi:type="xs:string"/>
- date/decimal/boolean → typed zero (0001-01-01 / 0 / false)
- StandardPeriod → Custom variant with zero dates
- @valueList → omit <value> entirely

Closes BUG-1 (StandardPeriod @autoDates) and BUG-2 (CatalogRef.X = _
producing invalid <value>_</value>) reported by titan team. New helpers
Test-EmptyValue / Emit-EmptyValue (ps1) and is_empty_value /
emit_empty_value (py) shared by Emit-ParamValue, availableValues loop,
and explicit dataParameters emit. Shorthand regex .+ → .* so trailing
`=` parses as empty.

Reference: upload/erf/ПроверкаЭкранирования (live Designer dump).
New test case empty-param-values covers all 10 type×sentinel combos;
3 existing snapshots regenerated to include the now-correct <value>
tags.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 11:27:24 +03:00
Nick Shirokov 3eaa7ffa3b fix(skd-edit): drop unneeded " → &quot; in query/expression
Зеркалим решение из skd-compile: убираем .Replace('"','&quot;') из Esc-Xml
и удаляем post-process, который принудительно ставил &quot; внутри
<query>/<expression>. Реальный Конфигуратор так не пишет — экранирование
было анти-1С-стилем и портило round-trip diff.

Снимок add-calculated-field-restrict обновлён под новый формат.
Кейс preserve-entities-modify-parameter-title удалён: его смысл
инвертировался (теперь проверял бы нормализацию, а не сохранение),
а часть про многострочный xmlns уже покрыта preserve-xmlns-multiline.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 16:51:04 +03:00
Nick Shirokov 98ebb478ee fix(skd-compile): drop unneeded " → &quot; — matches Designer style
Конфигуратор внутри текстового контента <query>/<expression> оставляет " сырыми
(проверено на ERP DCS: 1504 raw " против 0 &quot;). Убираем .Replace('"','&quot;')
из esc_xml — теперь round-trip diff против типовых остаётся чистым.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 16:50:55 +03:00
Nick Shirokov fb67b1b80d fix(skd-edit): realistic multilang fixture (ERP-style appearance block)
multilang-base/Template.xml содержал <editFormat xsi:type="v8:LocalStringType">
на <field xsi:type="DataSetFieldField">, что нелегально по XDTO-схеме DCS —
1С Designer падал с "Исключение XDTO" при загрузке через
LoadExternalDataProcessorOrReportFromFiles. Snapshot-тесты этого не ловили
(только byte-equality), а platform-verify (tests/skills/verify-snapshots.mjs)
ронялся на трёх кейсах с этой фикстурой.

Заменил <editFormat> на реалистичный <appearance> блок с вложенным
<dcscor:item xsi:type="dcsset:SettingsParameterValue"> и многоязычным
<dcscor:value> (ru + en) — структура взята из типовой ERP-выгрузки. Это
даёт более правильный test для preserve-unknown-children: <appearance>
содержит вложенный multi-lang xsi:type-узел, который точно прошёл бы
через DOM round-trip с искажениями, если бы _unknownChildren не работал.

preserve-unknown-children-modify-field: shorthand изменён с
"@ignoreNullsInGroups" на "@dimension" (no-op по составу role, но
триггерит rebuild). Прежний @ignoreNullsInGroups без @dimension давал
комбинацию, которую Designer отвергает (ignoreNullsInGroups валиден
только в контексте resource-роли).

39/39 snapshot suite (PS+PY) + 39/39 platform verify через erf-build →
Designer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 15:19:13 +03:00
Nick Shirokov 79db5de6ee fix(skd-edit): preserve multi-lang title + unknown children in modify-*
В типовых конфигурациях (ERP, БП, ЗУП и т.д.) у полей и параметров обычно
есть мульти-язык title (ru + en, иногда + локализация). До этого modify-field /
modify-parameter / modify-dataParameter, перестраивая элемент через
Build-MLTextXml, оставляли только последнее найденное <v8:content> в ru —
en/uk/kk siblings молча терялись, и при следующей выгрузке Designer
ломал миграцию.

Read-FieldProperties сохраняет полный OuterXml <title> в _rawTitle и
коллекционирует OuterXml неизвестных дочерних элементов
(<editFormat>, <appearance>, кастомные расширения) в _unknownChildren.
Build-FieldFragment эмитит:
* _rawTitle как есть, если user не задал новый title;
* Patch-MLTextRu(_rawTitle, newRu) если user задал ru-override — патчит
  только <v8:content> в <v8:lang>ru</v8:lang>, остальные языки сохраняет;
* _unknownChildren в конце поля (после valueType).

modify-parameter аналогично: при title-override проверяет multi-lang
(>1 <v8:item>) и патчит ru через Patch-MLTextRu, иначе ребилдит ru-only.

set-field-role сохраняет нестандартные подэлементы <role> (например
<dcscom:addition>, <dcscom:groupFields>), не входящие в фиксированный
known-children set и не указанные через kv в shorthand.

xmlns-стрип на захваченных OuterXml — лишние декларации (которые сериализаторы
добавляют для standalone-фрагментов) убираются.

PY: lxml etree.tostring по умолчанию включает .tail (whitespace после
закрывающего тега), что приводило к non-idempotent ростy whitespace при
повторных прогонах. Везде добавлен with_tail=False.

Новые тесты с idempotent: true:
* preserve-multilang-modify-field (ru-override на multi-lang title);
* preserve-multilang-modify-parameter (то же для параметра);
* preserve-unknown-children-modify-field (role flag, проверяем что
  <editFormat> и en title не теряются).

Общая fixture: multilang-base/Template.xml с полем и параметром,
у каждого ru + en title; поле также имеет <editFormat>.

39/39 PS + 39/39 PY. skd-edit v1.20 -> v1.21.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 15:18:07 +03:00
Nick Shirokov 23d2cb42de fix(skd-edit): preserve <valueType>, detect line endings, drop CRLF leak
Targeted follow-ups к round-trip фиксу:

* modify-field больше не теряет <valueType> при перестройке поля —
  Read-FieldProperties сохраняет полный OuterXml элемента (StringQualifiers,
  NumberQualifiers, DateQualifiers и т.п.), Build-FieldFragment отдаёт его
  обратно. Лишние xmlns-декларации, добавляемые сериализатором при
  выгрузке поддерева, стрипаются регексом.
* Line-ending convention теперь определяется при load (CRLF vs LF) и
  единообразно применяется в финале save. Раньше CreateWhitespace и
  Build-*Fragment везде использовали CRLF, что приводило к смешанным
  переносам в LF-исходниках (и наоборот) и к non-idempotent выходу
  modify-parameter title (run 1 → \n\t\t<title>\r\n... → run 2 →
  \r\n\t\t<title>\r\n...).
* PS Insert-BeforeElement переведён на LF; все -join "`r`n" → "`n";
  py "\r\n".join → "\n". Конечная нормализация переносов делается в
  save в соответствии со script:LineEnding.
* preserve-entities-modify-parameter-title.json теперь idempotent: true
  (после фикса CRLF leak'а двойной прогон byte-identical).

На реальной схеме diff после modify-field составил 30 строк: целевая
вставка title плюс полезная одноразовая коррекция ранее повреждённых
&quot; в text-content <dcsat:expression>. modify-field идемпотентен.

skd-edit v1.19 -> v1.20.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 15:18:07 +03:00
Nick Shirokov 511bfe7fdf fix(skd-edit): NO-OP skip + format-preserve post-process (round-trip)
XmlDocument round-trip искажал Template.xml даже при отсутствии правок:
декодировал &quot; в <query>/<expression>, схлопывал многострочный xmlns
корня, добавлял пробел перед /> и записывал файл при [WARN] not found.

Дирти-флаг ($script:Dirty / dirty) ставится только на успешной мутации;
финальный save пропускается с [INFO] No changes -- file untouched, если
ни одна операция в batch ничего не изменила. Post-process после OuterXml
восстанавливает raw-форматирование корневого xmlns из исходного файла,
re-escape `"` в текстах <query>/<expression> с anchored regex (не задевая
xsi:type="..."), и нормализует <foo .../> к <foo.../>.

Замеры на реальной схеме после modify-field: diff упал с 423 строк до 37
(94% шума устранено), повторный прогон byte-identical.

В runner.mjs добавлен caseData.idempotent: re-run + byte-equality на всех
файлах workDir. Три новых кейса (NO-OP, entity-preserve, xmlns-multiline)
+ общий fixture roundtrip-base. Все 33 ранее существовавших snapshot
перегенерированы под корректное форматирование (восстанавливают то, что
старый skd-edit ломал).

skd-edit v1.18 -> v1.19. PS и PY порты синхронизированы.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 15:17:42 +03:00
Nick Shirokov 7fa279c354 feat(skd-edit): clear-conditionalAppearance + multiline patch-query (доки)
- Новая операция clear-conditionalAppearance в стиле clear-selection/
  order/filter. Закрывает потребность "заменить набор правил оформления"
  через clear + re-add.
- patch-query: многострочные подстроки уже работали (string.Replace
  корректно обрабатывает \n). Зафиксировано в SKILL.md.
- add-total: shorthand-шаблон с тремя случаями (Func, Func(expr),
  identity-выражение) — после fix Bug 6 поведение нужно явно объяснить.
- Косметика: убрана утечка XML-внутренностей в комментарии примера
  set-field-role @period.
- Пример patch-query @once заменён на более типовой случай уникальной
  подстроки (КАК ВТ_СтароеИмя вместо ЛЕВОЕ СОЕДИНЕНИЕ).

Регресс: 33/33 PS, 33/33 PY, 33/33 платформенный verify.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 17:39:24 +03:00
Nick Shirokov 28a2a34c84 fix(skd-edit): add-total identity expression для не-аггрегатных функций
Раньше "DataPath: X" всегда заворачивалось в X(DataPath). Если X не
аггрегатная функция (например, имя другого ресурса или сам DataPath),
получалось некорректное выражение типа Проверка(Проверка).

Зеркалю логику из skd-compile: whitelist аггрегатных функций
(Сумма, Количество, Минимум, Максимум, Среднее + EN-варианты).
Для остального — identity (использовать funcPart как есть).

Сообщение [OK] теперь показывает фактически записанный expression.

Регресс: 32/32 PS, 32/32 PY, 32/32 платформенный verify.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 16:16:27 +03:00
Nick Shirokov f0f1e88aaa feat(skd-edit): patch-query @once — assert ровно одно вхождение
Защищает от случайных замен в комментариях/совпадениях имён:

  "ЛЕВОЕ СОЕДИНЕНИЕ => ВНУТРЕННЕЕ СОЕДИНЕНИЕ @once"
  # fail, если в запросе 0 или 2+ вхождений

Без флага default — replace-all (как раньше, обратная совместимость).

При успехе сообщение содержит фактическое число вхождений
"(N occurrence(s))", помогает заметить неожиданную множественность
без явного @once.

Регресс: 31/31 PS, 31/31 PY, 31/31 платформенный verify.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 16:00:55 +03:00
Nick Shirokov e7cbf306a0 feat(skd-edit): availableValue — список с replace-семантикой и в add-parameter
- Единый list-синтаксис: availableValue=v1[: p1], v2[: p2], ...
  Элементы через запятую, представление после двоеточия.
- Запятые/двоеточия внутри значений и представлений — в одинарных кавычках:
  availableValue=Окр1: 'руб., коп.', Окр1000: руб.
- add-parameter теперь принимает availableValue= и создаёт начальный список
  в одном вызове (раньше требовался последующий modify-parameter).
- modify-parameter availableValue=... ЗАМЕНЯЕТ весь список (раньше
  append). Согласуется с остальными modify-* для одиночных свойств.
- SKILL.md: добавлен shorthand-шаблон для modify-parameter,
  расширен для add-parameter [availableValue=список].

Существующие тесты мигрированы со старого ;;-batch на новый list-синтаксис.
Снапшоты сохранились (тесты стартовали с пустого списка — semantics
совпадает для greenfield).

Регресс: 29/29 PS, 29/29 PY, 29/29 платформенный verify.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 15:37:56 +03:00
Nick Shirokov 5090deb5bc feat(skd-edit): set-field-role — управление ролями поля
Новая операция: полная замена <role>-блока поля dataSet.

- Shorthand: "<dataPath> [@флаги] [kv=значение]"
- Флаги (зеркало skd-compile): @balance, @dimension, @account, @period,
  @required, @autoOrder, @ignoreNullValues
- KV: balanceGroupName, balanceType, parentDimension, accountTypeExpression,
  orderType, expression, periodNumber, periodType
- Пустой spec (только dataPath) — снимает роль целиком
- Поддерживает пакетный режим

Закрывает потребность временного toggle off/on роли при отладке
(было: ручной Edit XML), а также корректировку balance/dimension
после add-total.

Регресс: 27/27 PS, 27/27 PY, 27/27 платформенный verify.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 14:53:55 +03:00
Nick Shirokov 8b0bcf0194 feat(skd-edit): флаги @hidden и @always для параметров
- @hidden — скрывает параметр от пользовательских настроек
  (useRestriction=true + availableAsField=false). Для констант-параметров.
- @always — параметр всегда подставляется в запрос (use=Always).
  Используется самостоятельно для видимых обязательных параметров.
- Композируются: @hidden @always одной строкой даёт типовой паттерн
  "скрытая константа всегда применяется".
- Поддержка в add-parameter и modify-parameter, идемпотентны.

Регресс: 25/25 PS, 25/25 PY, 25/25 платформенный verify.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 14:14:19 +03:00
Nick Shirokov 529a5cacae feat(skd-edit): modify-structure + фиксы set-structure/parameter/patch-query
- modify-structure: новая операция, меняет groupItems группы по @name=,
  сохраняя Selection/order/filter/conditionalAppearance (Bug 1)
- set-structure: shorthand поддерживает запятую для нескольких полей
  в одном уровне группировки (Bug 2)
- set-structure: @name= с обрамляющими кавычками (двойными/одинарными)
  снимает их при записи в <dcsset:name> (Bug 3)
- add-parameter: ссылочные типы (CatalogRef, ChartOfAccountsRef, …)
  пишут <value xsi:type="dcscor:DesignTimeValue">, не xs:string (Bug 4a)
- modify-parameter: namespace-aware lookup существующих свойств
  — обновляет inplace, не плодит дубли (Bug 4b)
- modify-parameter value=…: пересборка <value> с корректным xsi:type
  из <valueType> (попутно лечит ранее битый XML)
- patch-query: батч ;;-сегментов триммится по краям (Bug 5)
- skd-compile: симметричный фикс ссылочных типов в emit_value

Регресс: 23/23 PS, 23/23 PY (skd-edit), 21/21 PS+PY (skd-compile),
23/23 платформенный verify-snapshots.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 13:40:49 +03:00
Nick Shirokov 8b0f55f1cc feat(form-validate): silent-skip числовых и UUID-DataPath в Check 5
В реальных выгрузках ERP/БП встречаются непрозрачные платформенные
DataPath, которые невозможно проверить из одного Form.xml:
- bare numeric ("10", "1000003") — внутренние индексы платформы
- "N/M:<uuid>" — ссылка на метаданные по UUID

Раньше Check 5 ругался на них "attribute not found". Теперь такие
пути пропускаются без счёта в paths checked и без ошибки.

Реалистичные пользовательские опечатки (кириллица в имени атрибута)
продолжают ловиться обычной проверкой attrMap.

Добавлен тест-кейс datapath-opaque-refs, версия v1.5 → v1.6.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 11:40:27 +03:00
Nick Shirokov 54cbc69a59 feat(form-validate): резолв Items.<Table>.CurrentData.* и ~<Attr>.* в DataPath
В Check 5 раньше брался первый сегмент DataPath и искался в attrMap,
из-за чего ложно ругались реальные формы ERP/БП с путями вида
Items.<TableName>.CurrentData.<Field> (подвалы, инфо-панели) и
~<DynamicListAttr>.<Field> (текущая строка списка).

Теперь:
- ведущий ~ стрипается перед разбором сегментов;
- для Items.<Table>.CurrentData.* находим элемент-таблицу по name,
  берём её <DataPath> (атрибут DynamicList/TableSection) и проверяем
  его в attrMap. Если таблицы нет — Error; если третий сегмент не
  CurrentData — Warn.

Добавлен тест-кейс datapath-currentdata, версия скриптов v1.4 → v1.5.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 11:38:56 +03:00
Nick Shirokov 32bf9c1a3f feat(form-compile): textEdit key for InputField (TextEdit=false)
v1.20 → v1.21 (ps1 + py).

Добавлен ключ DSL `textEdit` для элемента input. Эмитит
`<TextEdit>false</TextEdit>` после AutoMarkIncomplete (значение
true — дефолт платформы, не эмитируется). Закрывает блокер для
03-fillfields/direct-edit-form в синтетике web-test: поле с
запрещённым ручным вводом → выбор только через pick-кнопку/F4.

Snapshot-тест: tests/skills/cases/form-compile/text-edit-flag.json
(2 поля, проверяет наличие TextEdit только на втором). 30/30
form-compile зелёные обоих runtime'ов.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 12:56:35 +03:00
Nick Shirokov 71309d2bc2 fix(tests): make cf-edit/set-home-page case platform-loadable
Кейс ссылался на CommonForm.* и DataProcessor.Поиск.Form.ФормаПоиска,
которых не было в workDir — verify-snapshots падал на db-load-xml,
а cf-validate Check 9 (валидация HP form refs) ловил это только под
--with-validation, поэтому в обычной регрессии проблема была не видна.

Поскольку CommonForm пока не умеет создавать ни meta-compile, ни form-add
(он привязывается к существующему объекту-владельцу), заменил ссылки
на формы Catalog/DataProcessor — DSL-покрытие сохранено целиком:
template, string-ref, height, visibility, русский синтаксис типа,
короткая и полная форма roles. Добавлен preRun из 10 шагов
(meta-compile + form-add + role-compile) для синтеза всех ссылок.

Поддержка CommonForm в meta-compile/form-add — отдельная задача.

verify-snapshots: 1/1 ✓ (db-load-xml, db-update проходят).
Полная регрессия: 349/349 ✓.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 13:57:30 +03:00
Nick Shirokov e1f81a0cde chore(tests): refresh snapshots after meta-compile QuickChoice + form-compile AutoTitle defaults
- QuickChoice<true→false> для Catalog (07b2ec3 «дефолты QuickChoice по реальным
  конфигам» — часть снапшотов уже обновили в dc0382c, эти были пропущены)
- автоген <Title>/<AutoTitle>/<TitleLocation>/<SavedData> в формах
  (76800fc «автоген Title из имени» и серия фич form-compile)
- column-group/ — новый снапшот для кейса из 4f9d9ae (был не закоммичен)

Все 349 unit-тестов и 6 integration-тестов зелёные. verify-snapshots
(платформенная загрузка) — 201/202; отдельный pre-existing fail
cf-edit/set-home-page (Check 9 не валидирует HP form refs) разбираем
отдельно, в дифф этой регенерации не входит.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 13:45:47 +03:00
Nick Shirokov 4f9d9aee97 feat(form-compile): группировка колонок таблицы (ColumnGroup)
Новый DSL-ключ columnGroup со значением-ориентацией horizontal/vertical/inCell
для элемента <ColumnGroup> внутри columns таблицы. Поддерживает вложение,
showTitle/showInHeader/width, тихие синонимы ColumnGroup и ГруппаКолонок.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 11:48:35 +03:00
Nick Shirokov 6c60398406 feat(form-compile): авто-вид кнопки по контексту АКП
Кнопки внутри cmdBar/autoCmdBar/popup автоматически получают
CommandBarButton (или CommandBarHyperlink при type="hyperlink") —
указывать вид вручную не нужно. Резолвер прощающий: принимает и
короткие DSL-формы, и XML-имена в любом контексте.

Пример «Диалог загрузки файла» в SKILL.md и тест-кейс file-dialog
переведены на нативный паттерн с autoCmdBar вместо отдельной
горизонтальной группы кнопок внизу формы.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 19:41:43 +03:00
Nick Shirokov dc0382cc06 chore(tests): обновлены снапшоты после meta-compile QuickChoice defaults
Снапшоты ссылочных реквизитов теперь содержат QuickChoice=false
в соответствии с дефолтами по реальным конфигам (см. 07b2ec3).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 18:43:33 +03:00
Nick Shirokov b1e29253d5 feat(form-compile): RadioButtonField и словарь синонимов типов элементов
Поле переключателя с RadioButtonType (Auto/RadioButtons/Tumbler) и
ChoiceList (массив value+presentation). Толерантно к написанию модели:
русские имена тегов (ПолеПереключателя, RadioButtonField),
ВидПереключателя по-русски (Авто/Переключатель/Тумблер),
Перечисление.X.Y без EnumValue, синоним title для presentation,
автогенерация презентации из имени значения.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 18:43:26 +03:00
Nick Shirokov 07b2ec36af feat(meta-compile): дефолты QuickChoice по реальным конфигам
Catalog/CCT/CoA/CoCT/ExchangePlan: дефолт false (раньше true). Enum: дефолт true (теперь параметризовано). Цифры из acc_8.3.27 + erp_8.3.24 — у Catalog ~95% объектов QuickChoice=false, у Enum ~99% true.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 17:34:16 +03:00
Nick Shirokov b4514dc350 feat(form-compile): AutoMaxWidth=false по умолчанию для multiLine InputField
В реальных формах ERP/БП у ~60% многострочных полей ввода явно стоит
АвтоМаксимальнаяШирина=Ложь. Теперь form-compile проставляет это
автоматически при multiLine: true, если пользователь не задал
autoMaxWidth явно.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 19:05:50 +03:00
Nick Shirokov 8ad5d80f7f feat(form-compile): автоподстановка RowPictureDataPath для DynamicList с MainTable
Document/InformationRegister/AccumulationRegister List-генераторы теперь
прописывают `Список.DefaultPicture` (как делает ERP/БП в 594/600 форм
списка документов). Плюс fallback в эвристике DynamicList-таблицы:
если у главного реквизита есть `settings.mainTable`, поле
подставляется автоматически и для ручного DSL.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 18:39:29 +03:00
Nick Shirokov 76800fc92b feat(form-compile): автоген Title из имени для узлов без источника синонима
Реквизиты формы, команды, страницы, попапы и декорации теперь получают Title,
сгенерированный из CamelCase-имени, если в DSL он не задан явно. Поля с path
и кнопки с command по-прежнему опускают Title — синоним подхватится платформой.
Главные реквизиты (Объект/Список/Запись с main=true) исключены.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 18:17:19 +03:00
Nick Shirokov 36cd63d8bb fix(form-compile): AutoTitle=false по умолчанию при заданном Title формы
Когда у формы задан Title (через defn.title или properties.title), эмитим
AutoTitle=false если пользователь явно его не указал. Иначе платформа
добавляет суффикс синонима и получается двойной заголовок (Номенклатура:
Номенклатура). В выгрузках ERP так делает ~95% форм с form-level Title.

Снапшоты form-compile/form-compile-from-object обновлены под новое поведение.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 17:22:48 +03:00
Nick Shirokov e216db5734 fix(form-compile): default TitleLocation=Right для CheckBoxField
Платформенный default TitleLocation для CheckBoxField — Left, что почти
никогда не соответствует UX-ожиданиям. В acc 8.3.27 для CheckBoxField:
Right (явно): 811, без тега (=Left): 406, None: 140, Left: 14, Top: 3 —
доминирующий паттерн «заголовок справа от флажка».

Эмитим <TitleLocation>Right</TitleLocation> по умолчанию для check.
Переопределяется через titleLocation: 'Left' / 'None' / 'Top' / 'Bottom'.

v1.11. Обновил 5 snapshot'ов.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 16:59:31 +03:00
Nick Shirokov a59be4b914 fix(form-compile): SavedData=true для object/RecordManager главного реквизита
Без <SavedData>true</SavedData> платформа не маркирует форму как modified
при изменении главного реквизита — confirmation dialog при Esc не появляется,
canonical flow «изменил → Esc → Да» сломан.

Правило выведено из реальной выгрузки acc 8.3.27: SavedData ставится только
для редактируемых форм с типом *Object.X (Catalog/Document/ChartOf…/
ExchangePlan/BusinessProcess/Task) или *RecordManager.X. DynamicList/Report/
DataProcessor/ConstantsSet/RecordSet — не трогаем, отдаём решение DSL через
явный savedData: true.

Поднял версию до v1.10. Обновил 5 snapshot'ов (формы элементов/документа).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 16:51:43 +03:00
Nick Shirokov 4b8d3b67dc fix(tests): platform-verifiable form-info DSL + external setup в verify-snapshots
- form-info/{rich-form,simple-form}: тип реквизита Объект исправлен
  с ExternalDataProcessorObject на DataProcessorObject — preRun создаёт
  обычную обработку, и платформа отвергала несоответствие XDTO-исключением.
- verify-snapshots.mjs: поддержка setup="external:<path>" — копирует
  внешний дамп (выгрузку ERP/БП) в workDir, пропускает cf-init и
  авто-регистрацию объектов через cf-edit. Платформенная загрузка
  целой вендорской конфы скипается — кейсы real-acc-form-* проверяют
  скрипт против реального XML, а не пригодность всей БП к чистой базе.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 14:31:18 +03:00
Nick Shirokov 6b63177687 feat(form-compile): не эмитить HorizontalAlign по умолчанию + чистка SKILL.md
- HorizontalAlign не эмитится, если не задан явно через autoCmdBar.horizontalAlign.
  Раньше был хардкод Right; платформенный дефолт — Left, эталонные формы
  типовых (Бригады/ФормаСписка) тег вообще не содержат.
- horizontalAlign принимает Left/Center/Right.
- SKILL.md: убран раздел «Эвристики компилятора» (внутренняя кухня скрипта),
  сжато описание autoCmdBar и main — модель пишет DSL явно, помощь
  компилятора видна в [INFO]/[WARN]-логе.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 20:54:57 +03:00
Nick Shirokov 13174b63b1 feat(form-compile): нативная AutoCommandBar формы + autoCmdBar DSL
- Эвристика главной АКП: без cmdBar/autoCmdBar остаётся Autofill=true
  (как в Конфигураторе), с cmdBar — Autofill=false (обратная совместимость).
- Новый элемент autoCmdBar для наполнения главной АКП кастомными кнопками.
- Тихие синонимы commandBar↔cmdBar, autoCommandBar↔autoCmdBar.
- Инференс main-реквизита по типу (*Object.*, *RecordSet.*, DynamicList,
  ConstantsSet) — единственный кандидат проставляется молча с [INFO].
- Эвристика DynamicList → таблица: tableAutofill=false +
  commandBarLocation=None для привязанной таблицы (соответствие ERP).
- Косметика: <Autofill>true</Autofill> не эмитится явно.

Snapshot'ы form-* также обновлены до актуального состояния cf-init
(Ext/ClientApplicationInterface.xml).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 20:46:23 +03:00
Nick Shirokov 42b96bbd21 feat(cf-*): set-home-page + drill-down -Section home-page + form-ref валидация
- cf-edit: новая операция set-home-page перезаписывает Ext/HomePageWorkArea.xml.
  DSL принимает template (OneColumn/TwoColumnsEqualWidth/TwoColumnsVariableWidth),
  left/right с записями форм (строка или объект form/height/visibility/roles).
  Тихая нормализация ссылок: русские типы, 3-сегмент → авто-Form, файловые пути
- cf-info: краткая HP-сводка (template + счётчики) в overview/full, детальный
  вид через -Section home-page (alias -Name) с раскладкой и переопределениями ролей
- cf-validate: Check 9 — валидация ссылок на формы из HomePageWorkArea и
  Default*Form свойств; битая ссылка → error
- reference.md: убран реализационный шум (canonical sort, авто-нормализация форм,
  panelDef detail, секция авто-валидации); путь src/ в примерах вместо репо-специфичных

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 19:13:18 +03:00
Nick Shirokov 336dade274 feat(cf-edit): операция set-panels для раскладки панелей
JSON-DSL уровня имён: алиасы sections/open/favorites/history/functions
для платформенных uuid, объект {group:[...]} для стека (даёт <group>-
вложенность как у Конфигуратора), несколько записей в одной стороне =
соседние теги (рядом). Файл Ext/ClientApplicationInterface.xml
перезаписывается полностью; panelDef для всех 5 панелей пишется всегда.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 17:03:57 +03:00
Nick Shirokov 3c3ed2ff46 feat(cf-init): генерить Ext/ClientApplicationInterface.xml с ERP-дефолтом
Без этого файла веб-клиент 1С рендерит секции icon-only (без подписей),
а web-test их не видит. Дефолтная раскладка как в типовых ERP/БП ≥ 8.3.24:
панель открытых сверху, панель разделов слева; функций/избранного/истории
объявлены через panelDef но не размещены.

Расширил docs/1c-configuration-spec.md § 4.2 моделью раскладки и таблицей
UUID 5 платформенных панелей. Обновил снапшоты cf-init под новый файл.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 16:43:39 +03:00
Nick Shirokov 576f6dda8a feat(skd-compile): многоязычный title/presentation (объектная форма)
Везде, где DSL принимает title/presentation, теперь поддерживается
объектная форма с языками: "title": { "ru": "...", "en": "..." }.
Строка по-прежнему работает как ru-only.

Покрыто: field title, calculatedField title, parameter title/presentation,
settingsVariant title/presentation (root и в structure-items),
availableValue title/presentation, userSettingPresentation в filter/dataParameter,
mltext-значения в conditionalAppearance.appearance (ключи Текст/Заголовок/Формат).

Реализация:
- Хелпер emit_mltext / Emit-MLText расширен — принимает string|dict и
  итерирует по языкам.
- 8 inline-блоков LocalStringType в каждом скрипте заменены на вызовы
  хелпера (унификация — побочный эффект, бенефит на будущее).
- На входе сняты str()/"$()" коэрции для title/presentation, чтобы dict
  доходил до хелпера живым.

- SKILL.md: одна строка про объектную форму title.
- tests: новый snapshot-кейс multi-lang-title (5 узлов с ru+en).
- Версия v1.21.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 18:30:37 +03:00
Nick Shirokov 1a5b788305 feat(skd-compile): составной тип поля valueType (массив типов)
В объектной форме поля DataSet ключ "type" теперь принимает массив:
"type": ["CatalogRef.A", "CatalogRef.B"] — генерирует несколько <v8:Type>
внутри одного <valueType>. Типичный паттерн в ERP для полей-расшифровок
с составным ссылочным типом.

Shorthand остаётся одно-типовым (без перегрузки). Квалификаторы
((N)/(D,F)) применяются к каждому элементу массива независимо.

- skd-compile.ps1/py: Emit-ValueType/emit_value_type диспатчат на
  Emit-SingleValueType при строке или итерируют при массиве; field-парсер
  сохраняет массив, не приводя к строке. Версия v1.20.
- SKILL.md: один абзац после описания типов.
- tests: новый snapshot-кейс field-multi-type на 3 ссылочных типа.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 18:04:49 +03:00
Nick Shirokov b39da27d20 docs(skd-compile): описать presentationExpression и appearance на поле
В DSL skd-compile уже поддерживались ключи presentationExpression и
appearance в объектной форме поля DataSet, но в SKILL.md они не были
задокументированы — фичи существовали де-факто, но обнаружить их можно
было только чтением скрипта.

Заодно зафиксирован детерминизм порядка ключей appearance: PS5.1
hashtable не сохраняет порядок вставки, из-за чего PS- и PY-рантаймы
давали разный XML на одном входе. Заменено на [ordered]@{}.

- SKILL.md: новый блок «Дополнительные ключи объектной формы» в разделе «Поля»
- skd-compile.ps1/py: appearance = [ordered]@{} вместо @{}, версия v1.19
- tests: новый snapshot-кейс field-appearance-and-presentation,
  проходит на обоих рантаймах

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 17:57:04 +03:00
Nick Shirokov eda7279de0 fix(skd-info): -Mode full на схеме без DataSetQuery
Show-Query/show_query при отсутствии DataSetQuery делал exit 1, что
обрывало full режим после Show-Overview — секции fields/resources/
params/variant пользователь не видел. Теперь в full проверяем наличие
Query-набора и при отсутствии печатаем "(no query datasets)" и
продолжаем. Прямой -Mode query сохраняет прежнее поведение.

Воспроизводилось на схемах-приёмниках с одним DataSetObject
(например, ЖурналОшибок в ERP).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 16:38:57 +03:00
Nick Shirokov b7fbede819 fix(tests): починить pre-existing фейлы integration и skd-* snapshots
- build-config/build-epf: заменить runtime-тип FormDataStructure на корректный *Object.XXX
- platform-cfe/config/epf: form-compile принимает -OutputPath (путь до Form.xml), не -FormPath
- skd-edit/info/validate: перегенерированы snapshots после feat(skd-compile) denyIncompleteValues=true (3729b63)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 15:48:23 +03:00
Nick Shirokov bdc38caffa refactor(form-add): объединить с epf-add-form, удалить специфичный навык
form-add теперь покрывает и объекты конфигурации, и standalone EPF/ERF
source tree (тип определяется из корневого XML, маппинг типов уже был).

Изменения form-add scaffold:
- Module.bsl: пустые регионы вместо скелета процедуры ПриСозданииНаСервере
- Form.xml: убран <Events> (раньше привязывал OnCreateAtServer к процедуре)
- Form.xml: <SavedData>true</SavedData> теперь условный — ставится для
  Catalog/Document/etc (стандарт ERP, 99% форм), не ставится для
  DataProcessor/Report/External* (где у объекта нет состояния)

Это согласуется с workflow: form-compile перегенерирует Form.xml целиком,
поэтому привязки в scaffold могут стать orphan; пустые регионы +
без Events — корректная стартовая точка, которую form-edit/form-compile
наполняют атомарно.

Удалён навык epf-add-form (директория + тесты), вызовы заменены на
form-add в integration-тестах, в кейсах epf-validate/help-add, в
description epf-init/epf-bsp-init, в docs и README.

Перегенерированы snapshot'ы 5 навыков (form-add, form-compile,
form-edit, form-info, form-validate). Платформенная верификация в 1С 8.3.24
прошла для всех 9 кейсов form-add.

Bump form-add v1.3 → v1.4.
2026-04-25 15:26:54 +03:00
Nick Shirokov 3729b63b89 feat(skd-compile): @autoDates — дефолты use=Always + denyIncompleteValues=true
Производные &НачалоПериода/&КонецПериода требуют заполненный период,
поэтому сам параметр теперь по умолчанию получает use=Always и
denyIncompleteValues=true. В объектной форме явные значения перекрывают.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 12:24:22 +03:00
Nick Shirokov 54d47aadad feat(skd-compile): dataParameters auto — копирование value всех типов (ЕРП-паттерн)
Раньше "auto" копировал только variant для StandardPeriod, остальные типы
теряли значение по умолчанию. Теперь:

- value задан (не-Custom для StandardPeriod) → value + use=true (implicit),
  правильный xsi:type: boolean/decimal/dateTime/string, DesignTimeValue для
  ссылочных типов.
- value отсутствует или StandardPeriod=Custom → <use>false</use>
  + <value xsi:nil="true"/>.

Соответствует тому, как 1С Designer и ЕРП-отчёты персистят
SettingsParameterValue. Тест auto-data-parameters расширен покрытием
decimal/string/ref/nil.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 16:13:04 +03:00
Nick Shirokov 3f23be8219 feat(skd-compile): @autoDates — НачалоПериода/КонецПериода вместо ДатаНачала/ДатаОкончания
Канонический паттерн БСП в Титан/ЕРП-отчётах использует имена
НачалоПериода/КонецПериода (~10:1 по частоте). Выражения
&Период.ДатаНачала/&Период.ДатаОкончания сохранены — это обращение
к внутренним полям StandardPeriod.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 15:51:22 +03:00
Nick Shirokov f5dd677ac8 fix(tests): cf-info/config-with-objects — preRun через meta-compile
Тест сломался с 0d5d345 (ужесточение cf-edit add-childObject: теперь требует, чтобы файл объекта существовал на диске). Там были пофикшены 4 теста cf-edit, но этот кейс cf-info с тем же паттерном в preRun пропустили.

Заменил cf-edit add-childObject на три meta-compile (Catalog.Товары, Document.Заказ, Enum.Статусы) — те сами регистрируют объекты в Configuration.xml и создают файлы. Snapshot перегенерирован.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 14:08:37 +03:00
Nick Shirokov be74d224be feat(skd-compile): dataParameters auto — наследовать variant для StandardPeriod
Для параметров типа StandardPeriod в режиме "dataParameters": "auto" эмитируется <dcscor:value> с variant из дефолта параметра (Custom, если не задан) — как это делает 1C Designer при сохранении SettingsParameterValue для периодов.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 21:00:58 +03:00
Nick Shirokov 1b46eb4d85 feat(skd-compile): parameters — title и presentation как синонимы
- parameter принимает presentation как синоним title (1C UI показывает
  подпись параметра как "Представление" — модель по аналогии пишет presentation)
- availableValues[] принимает title как синоним presentation (обратная
  ошибка: модель пишет title по аналогии с самим параметром)

Обе формы пишутся в один и тот же XML-узел. Версии: skd-compile v1.13 → v1.14.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 20:37:00 +03:00