Commit Graph
100 Commits
Author SHA1 Message Date
Nick ShirokovandClaude Opus 4.7 cd3e50c408 docs(skd-guide): добавить /skd-decompile и сценарий «по образцу»
Дополняем гайд группы skd-*:
- В таблицу навыков добавлена строка /skd-decompile с пометкой об
  отключённом автоподборе моделью.
- В блок «Рабочий цикл» нарисована обратная стрелка Template.xml →
  /skd-decompile → JSON DSL.
- Новый под-раздел «Когда /skd-decompile, а когда /skd-edit» с явным
  предупреждением о неполноте преобразования и тихих потерях.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 14:37:11 +03:00
Nick Shirokov da6ac2bab8 Merge branch 'skd-decompile' into dev 2026-05-25 13:08:37 +03:00
Nick ShirokovandClaude Opus 4.7 7a7d03dcff docs(skd-decompile): причёсываем SKILL.md перед merge
- description короче и с явным «не для точечных правок»
- унифицируем терминологию (sentinel-узлы)
- расширяем «Когда не использовать» — почему /skd-edit лучше для адресных правок
- в критичные конструкции добавляем вложенные схемы

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 13:07:53 +03:00
Nick ShirokovandClaude Opus 4.7 20a243143a fix(skd-decompile): убрать падения на ERP-отчётах с dataSetLink и StandardPeriod без companions
Два бага PS-версии, незаметно роняли 9/30 отчётов sample30 в decompile-fail:

1. Get-Text без xpath → SelectSingleNode("", $ns) с .NET XPathException
   "Результатом выражения должен быть NodeSet". Шесть call-sites в
   dataSetLinks (sourceDataSet/destinationDataSet/sourceExpression/...)
   передавали уже-выбранный узел без второго аргумента; [string]$xpath
   дефолтился в "". Фикс: Get-Text возвращает $node.InnerText, если
   xpath пустой.

2. $paramByName[$startMatch] при $startMatch=$null → "индекс массива
   вычислен как NULL". Возникает на StandardPeriod-параметре, для
   которого в отчёте нет companion expressions. Фикс: guard через if.

Python-порт #2 уже был защищён .get(); по #1 в py был обходной костыль
inline-через-inner_text — заменён на единый get_text(node) после
обновления сигнатуры до get_text(node, xpath=None).

verify-roundtrip sample30: 9 bit-perfect + 20 with-diff + 1 ring3 = 30
(до фикса 9 silently падали как decompile-fail, сумма не сходилась).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 12:29:06 +03:00
Nick ShirokovandClaude Opus 4.7 fea2f37ba6 feat(skd-decompile): Python-порт зеркалом PS v0.88
Зеркало skd-decompile.ps1 v0.88 (~3022 строки) → skd-decompile.py v0.88
(~3140 строк). По образцу пары skd-compile.ps1 ↔ skd-compile.py.

- runner.mjs --filter skd-decompile --runtime python: 16/16 зелёные
- runner.mjs --filter skd-decompile (PS, регрессия): 16/16
- runner.mjs --filter skd-compile --runtime python (регрессия): 23/23
- verify-roundtrip на titan2-subset (13 отчётов): PS ≡ Py байт-в-байт
- verify-roundtrip на sample30 (20 общих отчётов): тот же распред
  8 BP + 12 diff, у Py чуть меньше diff-строк на edge-кейсах empty
  multilang content

Нетривиальные места порта:
- ET в Python не понимает prefix-aware XPath → тонкая обёртка XNode +
  ручной _xpath_steps/_all/_single для PS-style путей
- ET.Element (C-impl) не позволяет навешивать атрибуты → per-element
  nsmap хранится во внешнем _NSMAP_BY_ID[id(el)], заполняется через
  iterparse + start-ns
- JSON-сериализатор (convert_to_compact_json, try_inline_json,
  lineLimit=400, inline-when-fits) портирован 1-в-1

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 12:15:19 +03:00
Nick Shirokov d8457bb307 docs(skd-dsl-spec): актуализация под session-фичи
- value параметра может быть массивом (для valueListAllowed)
- расшифровка namespace-ов цветов: style: (палитра темы), web: (web-имена),
  win: (Windows-системные)
2026-05-24 21:28:30 +03:00
Nick Shirokov daa7716f24 fix(skd-decompile): не сохранять valueType для известных outputParameters keys
Compile имеет map outputParamTypes — для известных ключей (Заголовок,
ВыводитьПараметрыДанных, РасположениеИтогов и др.) тип эмитится
автоматически по имени параметра. Decompile же всегда оборачивал в
wrapper {value, valueType} для не-xs:* типов — лишний шум.

Зеркалирован тот же map в decompile (15 keys), при чтении проверяем
совпадение fullType с map → если auto-detect compile вернёт тот же
тип, валидируем как простое значение.

JSON outputParameters стал заметно компактнее. Эффект на diff
нейтральный (compile эмитит то же).
2026-05-24 21:25:34 +03:00
Nick Shirokov bbed308c85 fix(skd-decompile): не сохранять valueType если auto-detect compile даст тот же тип
Для filter right values с типом dcscor:DesignTimeValue, чьё значение
соответствует ref-pattern (Перечисление.X.Y / Справочник.X.Y / ПланСчетов.X.Y
и др.), compile auto-detect-ит DesignTimeValue из значения. Раньше
decompile всё равно сохранял valueType явно — лишний шум в DSL.

Применено к single-right и multi-right. Эффект на diff нулевой (compile
эмитит то же самое), но decompiled JSON становится компактнее и читабельнее.
2026-05-24 21:17:03 +03:00
Nick Shirokov 11ddc2b5a2 fix(skd-compile): single-line эмиссия <DataCompositionSchema xmlns=...>
Раньше эмитили шапку схемы в 8 строк (каждый xmlns на отдельной строке).
Оригинал платформы пишет всё в одну строку. Был с самого начала
существования skd-compile — не регрессия, но косметика на каждый отчёт
давала 9 строк diff (1 LOST + 8 ADDED).

Sample30 total: 458 → 238 строк diff.
2026-05-24 21:09:34 +03:00
Nick Shirokov e59c3281fd feat(skd): различать 3 namespace цветов (style/web/win)
Раньше decompile Normalize-Color сворачивал любой dN: префикс в style:
независимо от URI. Compile Emit-ColorValue знал только style: → один xmlns
(http://v8.1c.ru/8.1/data/ui/style). Цвета web:GhostWhite и win:Highlight
терялись/искажались.

URI mapping:
- http://v8.1c.ru/8.1/data/ui/style          → style:
- http://v8.1c.ru/8.1/data/ui/colors/web     → web:
- http://v8.1c.ru/8.1/data/ui/colors/windows → win:

decompile: резолвим prefix через GetNamespaceOfPrefix.
compile (PS+Py): Emit-ColorValue для template cells — long form с
локальным xmlns. Emit-AppearanceValue (внутри settings) — short form,
т.к. <dcsset:settings> уже объявляет xmlns:style/web/win/sys на корне.

См. upload/erf/ЦветаВМакете — образец с 4 формами цвета.
2026-05-24 20:57:12 +03:00
Nick Shirokov 609698b00d feat(skd): multi-value параметры (valueListAllowed список значений по умолчанию)
Параметр с valueListAllowed=true может иметь несколько <value> элементов
подряд — список значений по умолчанию (например список счетов плана).
Раньше decompile читал только первый (SelectSingleNode), compile эмитил
один <value> → терялись все остальные значения.

DSL: value в параметре может быть массивом строк (или native bool/int/double).

decompile: SelectNodes("r:value") → если >1 элемент, value = array.
compile (PS+Py): если value — array, эмитим каждый отдельным <value>
через Emit-ParamValue.

Альт-indent корпус: 18009 → 17946 строк diff.
2026-05-24 20:38:10 +03:00
Nick Shirokov ceaaa8bc55 fix(skd-decompile): не сворачивать @autoDates companions с availableAsField=false
Companions НачалоПериода/КонецПериода имеют canonical имена/expression в
некоторых корпусах, но дополнительно несут availableAsField=false
(поле-ограничение, не участвует в выборе). Наш @autoDates auto-generator
не передаёт этот атрибут — для совместимости с другими корпусами без него.

Решение в decompile: не сворачивать в @autoDates если хотя бы один
companion имеет availableAsField=false → companions остаются явными
параметрами, compile эмитит их со всеми атрибутами через стандартный
path.

Sample30: 607 → 458 строк diff (-149).
2026-05-24 20:27:21 +03:00
Nick Shirokov 61cc8f3b9a fix(skd-decompile): сохранять useRestriction=true на не-hidden/не-autoDates параметрах
Раньше параметр с useRestriction=true (без hidden/autoDates/expression/
других object-form-триггеров) сохранялся как shorthand string —
useRestriction в shorthand не выражается, и compile эмитил default
useRestriction=false, теряя ограничение.

Render-Parameter: добавлен тригер object form для случая
useRestriction=true. Объект уже корректно эмитил это поле.
2026-05-24 20:07:07 +03:00
Nick Shirokov 4630af463f feat(skd-decompile): fail-fast (Ring 3) для отчётов без dataSet
Служебные отчёты-обёртки содержат только settingsVariant с outputParameters
(МакетОформления и подобное) и используются для динамического заполнения
из кода. Compile требует ≥1 dataSet, и весь DSL заточен под data-driven
отчёты — раньше decompile проходил, но compile падал с exit 1.

Теперь decompile fail-fast (exit 3, ring3 skip) — это правильнее
классифицирует такие отчёты в verify-roundtrip как "не поддерживается"
вместо "compile сломался".

См. C:/WS/projects/titan/src/cfe/Титан2/Reports/
ккСправкаРасчетРезервыПоСомнительнымДолгам.
2026-05-24 19:12:11 +03:00
Nick Shirokov dd02dcf3c4 feat(skd): TypeSet (композитный тип-набор) в valueType параметра
Параметры типа «исключаемые документы» имеют valueType с
<v8:TypeSet xmlns:dN="...">dN:DocumentRef</v8:TypeSet> — указывает на
все ссылки указанного класса конфигурации, а не на конкретный объект.

Раньше теряли целиком: decompile читал только <v8:Type>, compile
эмитил голое имя как <v8:Type>DocumentRef</v8:Type> (что не валидно).

DSL — голое имя ref-класса без точки (CatalogRef, DocumentRef, EnumRef,
ChartOfAccountsRef, ChartOfCharacteristicTypesRef, ChartOfCalculationTypesRef,
BusinessProcessRef, TaskRef, ExchangePlanRef, InformationRegisterRef,
AnyRef) → TypeSet. С точкой (DocumentRef.X) — конкретный Ref как было.

decompile: Get-ValueTypeShorthand читает v8:TypeSet и сохраняет
local-name (после prefix:).
compile (PS+Py): Emit-SingleValueType распознаёт голое имя из набора и
эмитит <v8:TypeSet xmlns:d5p1=...>d5p1:NAME</v8:TypeSet>.

Sample30 total: 618 → 607 строк diff.
2026-05-24 18:51:46 +03:00
Nick Shirokov e2e3e02a1b fix(skd): сохранять явные startDate/endDate в top-level StandardPeriod parameter
Параметр типа StandardPeriod с variant=Custom может иметь явные даты,
отличающиеся от default 0001-01-01T00:00:00 (например endDate=23:59:59).
См. АнализПричинБлокировкиВычетаНДС @941.

Раньше decompile сохранял variant только если ≠Custom (для Custom —
ничего), и compile эмитил захардкоженные 0001-01-01T00:00:00 для обеих
дат. Теряли явное время.

decompile: для StandardPeriod с явными датами (любая ≠00:00:00) →
object form {variant: Custom, startDate, endDate}.
compile (PS+Py): Emit-ParamValue принимает dict val с variant/startDate/
endDate; для Custom без явных дат сохраняется текущий fallback на
0001-01-01T00:00:00.

Sample30 total: 620 → 618 строк diff.
2026-05-24 18:42:58 +03:00
Nick Shirokov 9b331aa41d feat(skd): user-settings + axis-viewMode + use=false на StructureItemTable/Chart
Раньше для StructureItemTable читали только viewMode/userSettingID/
userSettingPresentation/itemsViewMode, а для StructureItemChart — вовсе
ничего из user-settings. Также не поддерживали axis-level режим
доступности секций (columnsViewMode/rowsViewMode/pointsViewMode/
seriesViewMode) и use=false на самих table/chart.

Расширено:
- table: + use=false, + columnsViewMode, + rowsViewMode
- chart: + use=false, + viewMode, + userSettingID, + userSettingPresentation,
         + itemsViewMode, + pointsViewMode, + seriesViewMode

Все эти атрибуты эмитятся платформой как direct children самой item-ноды
после rows/columns (table) или points/series (chart). DSL — простые поля
прямо на table/chart-объекте (как у table уже было для viewMode/etc).

Sample30 total: 729 → 620 строк diff (-109).
2026-05-24 18:23:36 +03:00
Nick Shirokov 91ef1d07eb feat(skd): v8ui:Line + nested side-styles в appearance
conditionalAppearance может содержать СтильГраницы со сложным value:
<dcscor:value xsi:type="v8ui:Line" width="0" gap="false">
  <v8ui:style xsi:type="v8ui:SpreadsheetDocumentCellLineType">None</v8ui:style>
</dcscor:value>
+ nested <dcscor:item> для side-стилей (СтильГраницы.Сверху/.Снизу/.Слева/.Справа),
каждый со своим v8ui:Line value и опц. <dcscor:use>false</dcscor:use>.

Раньше теряли всю структуру и эмитили <value xsi:type="xs:string">None</value>.

DSL form B (выбранный пользователем) — Line как top-level плоский объект:
"СтильГраницы": {
  "@type": "Line", "width": 0, "gap": false, "style": "None",
  "items": {
    "СтильГраницы.Сверху": {
      "value": { "@type": "Line", "width": 1, "gap": false, "style": "Solid" },
      "use": false
    }
  }
}

Nested items — универсальный wrapper {value, use?, items?} (как у outputParameters).
Эмитятся как siblings <dcscor:item> внутри родительского <dcscor:item> (после
закрытия родительского <dcscor:value>).

decompile: Read-AppearanceValueNode распознаёт Line и возвращает inline объект;
Get-SettingsAppearance читает nested dcscor:item children и собирает их в items.
compile (PS+Py): emit_appearance_value расширен — Line ветка + рекурсивный
вызов для items siblings.

Sample30 total: 767 → 729 строк diff (-38).
2026-05-24 18:10:25 +03:00
Nick Shirokov 8cb7309ee5 fix(skd-decompile): сохранять <selection>Auto</selection> на StructureItemChart
Раньше пропускали top-level selection в chart если она содержит только
SelectedItemAuto (считая дефолтом). Но оригинал платформы всегда эмитит
блок явно — для bit-perfect нужно сохранять presence (по аналогии с
table axis и structure-group, где selection presence уже сохраняется).

Sample30 total: 782 → 767 строк diff.
2026-05-24 17:53:11 +03:00
Nick Shirokov 0425b79a87 fix(skd-compile): не эмитить пустую <dcsat:appearance/> для cells без атрибутов
Cells со style "none" (без цветов/шрифтов/границ) и без width/merge
получали пустой блок <dcsat:appearance></dcsat:appearance>. Оригинал
платформы для таких cells appearance не пишет вовсе.

Добавлен ранний return в Emit-CellAppearance если все атрибуты пустые.

PS + Py синхронизированы. Sample30 total: 794 → 782 строки.
2026-05-24 17:49:30 +03:00
Nick Shirokov c8cba6f7ce feat(skd): локальный xmlns + use=false на nested sub-items outputParameters
В chart-параметрах типа ТипДиаграммы.СоединениеЗначенийПоСериям platform
эмитит nested SettingsParameterValue с:
- <dcscor:use>false</dcscor:use> (sub-параметр отключён)
- <dcscor:value xmlns:dN="http://v8.1c.ru/8.2/data/chart" xsi:type="dN:X">
  (локальный xmlns на value — префикс не объявлен в корне схемы)

Раньше теряли оба:
- decompile не читал sub.use и не резолвил xmlns кастомного xsi:type
- compile эмитил value без xmlns и без use=false

decompile: читаем dcscor:use на sub-item, резолвим prefix→URI через
GetNamespaceOfPrefix; если URI не из стандартных корневых xmlns —
сохраняем valueType как объект {uri, name}.
compile (PS+Py): новый helper Emit-OutputParametersSubItem; если
valueType — объект, эмитим xmlns:dN=<uri> + xsi:type=dN:<name>;
+ <dcscor:use>false</dcscor:use> если sub.use === false.

Sample30 total: 809 → 794 строк diff.
2026-05-24 17:41:44 +03:00
Nick Shirokov f34303f9ed docs(skd-dsl-spec): актуализация под фичи текущей сессии
Откатываем расширение SKILL.md (детальные формы расшифровки —
редкая необходимость) и переносим документацию в spec:

- selection folder placement (Horizontally/Vertically/...)
- groupBy field object-form: periodAdditionType +
  periodAdditionBegin/End (auto-detect xs:dateTime vs dcscor:Field)
- chart multi-series/multi-points (points/series как массив)
- template parameters drilldown форма A/B/C
- cell object-form { value, drilldown } override
- fieldTemplates секция
- choiceParameters values native bool/int/double/string
- filter valueType работает и для массива value
- dataParameters valueType=xs:string как nil-placeholder для use=false
2026-05-24 17:33:33 +03:00
Nick Shirokov c230142bf1 feat(skd): form C drilldown + per-cell drilldown override + fieldTemplates
Расширение DSL для area-templates под отчёты с расшифровкой через
data-параметр (типа АнализВыполненияМаршрутныхЛистов в ERP).

Раньше шорткат `drilldown: "X"` всегда генерировал
`Расшифровка_X` + `ИмяРесурса`/`DrillDown`. Появилось три формы:

- A: { name, expression }                              — без drilldown
- B: { name, expression, drilldown: "X" }              — текущий shortcut (без изменений)
- C: { name, drilldown: { field, expression, action } } — самостоятельный
                                                          DetailsAreaTemplateParameter

Per-cell override: ячейка может быть object `{ value, drilldown }` —
тогда appearance ссылается на указанный параметр расшифровки (без
префикса `Расшифровка_`). Используется когда несколько ячеек должны
указывать на один details-параметр (МаршрутныйЛист).

Новая корневая секция:
  "fieldTemplates": [{ "field": "X", "template": "Макет1" }]
— XML <fieldTemplate><field/><template/></fieldTemplate>.

compile (PS+Py): новый helper Emit-AreaTemplateParameter, ветка form C
в Emit-AreaTemplateDSL/Emit-Templates raw-mode, Emit-FieldTemplates.
Cell rendering: проверка cell.drilldown override перед drilldownMap.

decompile (PS): Build-Template переписан — собирает все
DetailsAreaTemplateParameter в map; распознаёт shortcut form B по
canonical shape (Расшифровка_<Y>/ИмяРесурса/"<Y>"/DrillDown) И наличию
cell appearance ref на этот target; не-shortcut → form C entry.
Cell wrapping: если drilldownTarget ≠ shortcut Расшифровка_Y, ячейка
оборачивается в { value, drilldown }. Plus Build-FieldTemplates.

Размер diff на sample30: 1045 → 809 строк (-22.5% за сессию).
2026-05-24 17:25:46 +03:00
Nick Shirokov d9010cd580 feat(skd): multi-series и multi-point в StructureItemChart
Диаграмма может содержать несколько <dcsset:series> (и аналогично
<dcsset:point>) — каждая со своим groupItems, filter, order, selection,
viewMode, userSettingID и userSettingPresentation. Используется для
multi-series графиков с группировкой по фильтру (например,
АнализЛояльностиКлиентовXYZ — series по СтадияОтношений: Постоянный,
Разовый, Потенциальный, Потерянный клиент).

Раньше декомпилировали только первый блок (SelectSingleNode), теряя
остальные → −113 строк diff на одном этом отчёте (134 → 21).

decompile: SelectNodes → если >1, сохраняем как массив; single → object
(backward-compat).
compile: проверяем тип points/series — array → цикл, иначе single
блок (backward-compat для существующего DSL).

PS и Py compile синхронизированы.
2026-05-24 16:18:16 +03:00
Nick Shirokov 19da4df61f feat(skd): periodAdditionBegin/End с типом dcscor:Field
GroupItemField может иметь periodAdditionBegin/End:
- xsi:type="xs:dateTime" с конкретной датой
- xsi:type="dcscor:Field" с путём к параметру/полю (например
  "ПараметрыДанных.ДатаНачала"). См. АнализДоходовРасходов @8933.

Раньше эмитили захардкоженный default xs:dateTime 0001-01-01T00:00:00,
теряя любые non-default значения.

decompile: читаем оба элемента, сохраняем как string поля
periodAdditionBegin/End в object form group field (если non-default).
compile: auto-detect типа по pattern (ISO date → xs:dateTime,
иначе → dcscor:Field).

PS и Py compile синхронизированы.
2026-05-24 16:10:15 +03:00
Nick Shirokov fe9d8500dc feat(skd): placement в SelectedItemFolder (selection)
SelectedItemFolder (группа полей с заголовком в selection) имеет
<dcsset:placement> — может быть Auto/Horizontally/Vertically/Special.
Мы захардкоженно эмитили Auto, теряя non-default значения.

decompile: читаем placement, сохраняем если ≠ Auto.
compile: эмитим из item.placement (default Auto для bit-perfect-default).

PS и Py compile синхронизированы.
2026-05-24 15:59:25 +03:00
Nick Shirokov 2ad35f484c fix(skd): empty xs:string placeholder в SettingsParameterValue use=false
Параметр типа DateTime в dataParameters внутри settings с use=false и
без значения сохраняется оригиналом как <dcscor:value xsi:type="xs:string"/>
(пустой placeholder), а не xsi:nil. См. АнализПлановыхНачислений @1506
для ОкончаниеПериода.

decompile: detect-ит empty xs:string + use=false → object form
{parameter, use:false, value:'', valueType:'xs:string'}.
compile: Emit-EmptyValue нормализует префикс xs: (xs:string → ^string),
теперь корректно эмитит пустой xs:string вместо fallback xsi:nil.

PS и Py синхронизированы.
2026-05-24 15:56:28 +03:00
Nick Shirokov abca61da66 fix(skd-decompile): сохранять xsi:type в multi-right filter values
При чтении FilterItemComparison с несколькими <right> элементами теряли
xsi:type — все значения уходили как строки, и compile эмитил DesignTimeValue
по auto-detect для строк вида "Перечисление.*". Но оригинал может хранить
эти значения как xs:string (см. АнализНачисленийИУдержаний @22718).

Теперь читаем xsi:type каждого <right>; если все одинаковые — сохраняем
в valueType. Compile уже умеет использовать переданный valueType вместо
auto-detect.
2026-05-24 15:43:41 +03:00
Nick Shirokov db6a1f2212 feat(skd): bool/numeric values в inputParameters choiceParameters
Раньше все values в <dcscor:value xsi:type="dcscor:ChoiceParameters">
эмитились как DesignTimeValue. Оригинал использует xs:boolean для bool-флагов
(пример: Отбор.ОбособленноеПодразделение=false в ChoiceParameters элементе
inputParameters поля ДанныеОрганизации).

decompile: читает тип xsi из <dcscor:value> и конвертит в JSON-native
(true/false для boolean, int/double для decimal, иначе строка).
compile: при эмите inputParameters → choiceParameters → values детектирует
тип значения и эмитит соответствующий xsi:type.

PS и Py синхронизированы.
2026-05-24 15:37:07 +03:00
Nick Shirokov 85d42ec34c docs(skd-dsl-spec): догон по фичам третьей сессии bit-perfect round-trip
Добавлено:
- outputParameters wrapper {value, valueType, use, items, viewMode, USID, USP}
- v8ui:Font в appearance — @type:Font + атрибуты
- dataParameters: valueType, nilValue
- StandardPeriod/StandardBeginningDate shape inference (без @type marker)
- selection/filter/order/CA UserSettingID на settings
- Пустые блоки SF/F/O/CA с только block-level meta
- inputParameters value valueType {uri, name} для кастомных xsi:type
- availableValues — типы значений сохраняются нативно
- itemsViewMode на column/row/table
- nilValue marker для параметров
- StructureItemGroup short form внутри table axis (платформ-паттерн)
2026-05-23 22:37:55 +03:00
Nick Shirokov a7344a1397 feat(skd): StandardBeginningDate в dataParameters через shape inference
Раньше StandardBeginningDate (используется когда top-level param имеет
тип xs:dateTime + UI выбор "Начало дня"/"Custom") декомпилировалась
через InnerText: variant+date конкатенировались в "Custom2022-10-25..."
и compile эмитил как xs:string.

Cross-reference на корпусе (671 отчёт):
  608 v8:StandardPeriod → v8:StandardPeriod
  180 xs:dateTime       → v8:StandardBeginningDate
  120 xs:dateTime       → xs:dateTime (raw)

Decompile теперь сохраняет SBD как объект {variant, date} (без @type marker).
Compile различает SP/SBD по форме value:
  {variant, date}                 → SBD
  {variant, startDate, endDate}   → SP с датами
  {variant} only                  → инференс по имени (BeginningOf* → SBD)

В корпусе ни одного ambiguous (variant=Custom без полей) не существует:
все 33 SBD/Custom имеют date, все 93 SP/Custom — startDate/endDate.

sample30: −22 строки (932 → 910).
2026-05-23 22:29:34 +03:00
Nick Shirokov f642f673d9 fix(skd-compile): не пропускать Auto-items в top-level selection/order
Platform может содержать SelectedItemAuto/OrderItemAuto в top-level
<dcsset:selection>/<dcsset:order> (рядом с явными полями) — это валидно.
Раньше compile использовал -skipAuto на top-level, теряя эти items.

Снапшоты регенерированы.

sample30: −10 строк (942 → 932).
2026-05-23 22:06:03 +03:00
Nick Shirokov fdc8c518aa fix(skd-compile): эмитить пустые selection/filter/order/CA блоки если есть block-level meta
Раньше Emit-Selection/Filter/Order/ConditionalAppearance early-return при
пустых items, даже если decompile сохранил blockViewMode/blockUserSettingID.
Caller (settingsVariant) тоже не вызывал эти функции на пустых items.

Теперь блоки эмитятся когда есть items ИЛИ block-level meta. Реальный кейс
из ERP: <dcsset:conditionalAppearance><dcsset:viewMode>Normal</dcsset:viewMode>
</dcsset:conditionalAppearance> — пустой CA блок только с viewMode.

sample30: −84 строки (1026 → 942).
2026-05-23 22:00:51 +03:00
Nick Shirokov 53536b72f5 fix(skd-compile): short form <dcsset:item> для StructureItemGroup внутри row/column
Анализ корпуса ERP (671 отчёт): items внутри dcsset:row/column/points/series
ВСЕГДА используют короткую форму <dcsset:item> без xsi:type (531 случай,
0 explicit). В остальных контекстах — explicit <dcsset:item xsi:type="dcsset:StructureItemGroup">.

Emit-StructureItem получил switch -shortGroup, который Emit-TableAxisBlock
передаёт для nested children. Флаг наследуется recursive в детей через
Emit-StructureItem рекурсию.

Снапшоты регенерированы.

sample30: −166 строк (1192 → 1026).
2026-05-23 21:46:27 +03:00
Nick Shirokov 21ae9a6d80 Revert "fix(skd-validate): принимать <dcsset:item> без xsi:type как StructureItemGroup"
This reverts commit 3ef4f44028.
2026-05-23 21:30:26 +03:00
Nick Shirokov ad99f3db0b fix(skd-compile): startDate/endDate в StandardPeriod ТОЛЬКО для variant=Custom
Анализ корпуса ERP/БСП (671 отчёт): из 635 StandardPeriod values только
93 (все Custom) имели <v8:startDate>/<v8:endDate>. Остальные 542 варианта
(ThisMonth, LastYear, Today, ThisQuarter, FromBeginningOfThisYear и т.д.)
эмитятся БЕЗ дат — это canonical platform-pattern.

Раньше compile добавлял boilerplate 0001-01-01 даты ко всем вариантам
независимо от типа. Снапшоты регенерированы.

sample30: −138 строк (1330 → 1192).
2026-05-23 21:24:42 +03:00
Nick Shirokov 3ef4f44028 fix(skd-validate): принимать <dcsset:item> без xsi:type как StructureItemGroup
Platform эмитит StructureItemGroup как короткую форму <dcsset:item> без
xsi:type (это дефолтный тип). Раньше валидатор выдавал error на любой
реальный XML с такой формой. Теперь — отсутствие xsi:type трактуется
как dcsset:StructureItemGroup (с warning только для нестандартных типов).
2026-05-23 21:16:43 +03:00
Nick Shirokov bb7696bf28 fix(skd-decompile): StandardPeriod в object-form dataParameter эмитим как {variant}
Когда dataParameter имеет viewMode/userSettingPresentation и значение —
StandardPeriod без явных дат (просто вариант "Custom"/"ThisMonth"),
decompile сохранял value как плоскую строку "Custom" + valueType=v8:StandardPeriod.
Compile, видя valueType с префиксом, эмитил <value xsi:type="v8:StandardPeriod">Custom</value>
— плоский xs:string-like тег вместо StandardPeriod-блока с <v8:variant>.

Теперь когда object-form нужен по другим причинам (viewMode/USP),
StandardPeriod-вариант сохраняется как {variant: ...}, и compile
правильно генерирует <v8:variant xsi:type="v8:StandardPeriodVariant">.

sample30: −66 строк (1396 → 1330).
2026-05-23 21:01:59 +03:00
Nick Shirokov 0466ae8fd8 feat(skd-compile): @autoDates companions использует type=dateTime (канон БСП)
Раньше @autoDates генерировал НачалоПериода/КонецПериода с type=date →
DateFractions=Date. Реальный БСП паттерн использует DateTime (платформа сама
приводит конец периода к 23:59:59 для дат без времени, но DateTime более
явное и матчит шаблоны БСП).

Снапшоты регенерированы.
2026-05-23 20:54:48 +03:00
Nick Shirokov 796403abe3 fix(skd-decompile): fold @autoDates только для канонических имён НачалоПериода/КонецПериода
Раньше любая пара companion-параметров с expression "&P.ДатаНачала"/
"&P.ДатаОкончания" сворачивалась в @autoDates, независимо от их имён.
Compile же всегда генерирует строго "НачалоПериода"/"КонецПериода" +
type=date + DateFractions=Date. Для отчётов с шаблоном "Период<X>" →
"НачалоПериода<X>"/"КонецПериода<X>" + DateFractions=DateTime
(типовой паттерн БСП — ПериодКонтрольСроков, ПериодОбязательств и т.п.)
это давало некорректный round-trip с потерей суффикса и формата дат.

Теперь fold срабатывает ТОЛЬКО для канонической пары — остальные
companion'ы остаются явными параметрами с полным сохранением имени,
type=dateTime, DateFractions=DateTime и expression.

sample30: −152 строки (1548 → 1396).
2026-05-23 20:38:33 +03:00
Nick Shirokov 639568c039 feat(skd): кастомные xsi:type с локальным xmlns в inputParameters values
Параметр ВыборГруппИЭлементов имеет значение типа FoldersAndItemsUse:
<dcscor:value xmlns:d6p1="http://v8.1c.ru/8.1/data/enterprise"
 xsi:type="d6p1:FoldersAndItemsUse">Items</dcscor:value>

Decompile теряла xsi:type → compile эмитил xs:string. Теперь сохраняем
{uri, name} в valueType wrapper'е, compile воспроизводит локальный
xmlns:dN="..." prefix и правильный xsi:type. GetNamespaceOfPrefix
извлекает URI из контекста элемента, что работает для всех 7 известных
xmlns URI (enterprise, current-config, ui/style, chart, types и т.п.).

sample30: −8 строк (1556 → 1548).
2026-05-23 20:24:46 +03:00
Nick Shirokov 9ef554a576 feat(skd): block-level userSettingID на selection/filter/order/CA + meta на StructureItemTable
Раньше теряли userSettingID, который platform пишет:
1. Прямо в блоки selection/filter/order/conditionalAppearance под
   <dcsset:settings> (рядом с block-level viewMode). Расширена цепочка
   Get-BlockUSID + новый -blockUserSettingID параметр в Emit-*.
2. На самой <dcsset:item xsi:type="dcsset:StructureItemTable"> (рядом
   с viewMode/userSettingPresentation/itemsViewMode). Build-Structure
   читает их, Emit-StructureItem (type=table) эмитит.

sample30: −46 строк (1602 → 1556).
2026-05-23 20:12:14 +03:00
Nick Shirokov 1b36aa97c8 feat(skd-decompile): useRestriction=true в object form для non-hidden/non-autoDates параметров
Параметры с явно заданным <useRestriction>true</useRestriction>, которые
не покрываются auto-emit от @hidden (где compile сам ставит true) и не
участвуют в @autoDates fold (где compile также ставит true companion'ам),
теряли это свойство. Типичный кейс: параметры-выражения вида
ПериодНачало = &Период.ДатаНачала с useRestriction=true.

Render-Parameter теперь явно эмитит useRestriction:true в object form
с защитой от двойного перекрытия hidden/autoDates.

sample30: −60 строк (1710 → 1650).
2026-05-23 19:44:58 +03:00
Nick Shirokov 573602ae65 fix(skd-decompile): сохранение кастомных xsi:type в outputParameters items
Параметры типа ВариантИспользованияГруппировки с xsi:type=
dcsset:DataCompositionGroupUseVariant теряли тип, потому что wrapper
создавался только при наличии viewMode/userSettingID/use=false. Теперь
кастомный xsi:type (не xs:* / LocalStringType / Font) сам по себе
триггерит wrapping — сохраняем valueType для bit-perfect эмиссии.

sample30: −28 строк (1738 → 1710).
2026-05-23 19:37:23 +03:00
Nick Shirokov 632c58eef1 fix(skd): сохранение xs:boolean и xs:decimal в filter values + availableValues
Get-FilterValueWithType теряла тип значения — "true"/"false" приходило как
string, и compile эмитил xs:string вместо xs:boolean. Decompile теперь
конвертирует по xsi:type → реальный [bool]/[int]/[double].

Shorthand эмиссия фильтра также фиксирована: bool теперь рендерится как
"true"/"false" (lowercase), не "True"/"False" (PS-style).

Аналогично availableValues в параметрах: bool/decimal значения теперь
сохраняются с правильным типом, а не downgrade в xs:string.

sample30: −30 строк (1768 → 1738).
2026-05-23 19:33:47 +03:00
Nick Shirokov 64c2037fe1 feat(skd): block-level viewMode/userSettingID на <dcsset:order> внутри structure group
Раньше теряли viewMode/userSettingID, которые platform пишет прямо в блок order
(не в item). Build-Structure теперь читает их как orderViewMode/orderUserSettingID,
Emit-Order принимает -blockUserSettingID параметр.

sample30: −10 строк (1778 → 1768).
2026-05-23 19:25:20 +03:00
Nick Shirokov fb9d29408c feat(skd): viewMode/userSettingPresentation на dataParameters items
Build-DataParameters не читал viewMode и userSettingPresentation на отдельных
параметрах данных — теряли 74 viewMode references только в одном крупном отчёте.
Теперь object form {parameter, value, valueType?, viewMode?, userSettingID?, ...}
с auto-конверсией bool/decimal по xsi:type.

Compile добавлен early-branch на полный xsi:type (xs:boolean, dcscor:DesignTimeValue
и т.п.) — раньше string "true" эмитился как xs:string вместо xs:boolean.

Расследование: viewmode-trace.py показал ровно 66 LOST viewMode=Normal
+ 8 Inaccessible на пути '/r:DataCompositionSchema/r:settingsVariant/
dcsset:settings/dcsset:dataParameters/dcscor:item[SettingsParameterValue]'.

sample30: −204 строки (1982 → 1778).
2026-05-23 19:19:39 +03:00
Nick Shirokov 730decf9ce feat(skd): itemsViewMode на table axis (column/row/point/series)
Build-TableAxisBlock не читал itemsViewMode на самой оси (только на
StructureItemGroup). Теперь сохраняется и эмитится — bit-perfect для
шаблонов отчётов с явно заданным itemsViewMode=Normal/Inaccessible
на колонках/строках таблицы.

sample30: −30 строк (2012 → 1982).
2026-05-23 19:04:22 +03:00
Nick Shirokov 48e2b6bd44 feat(skd): nilValue marker для параметров с xsi:nil="true"
Параметры со скалярным типом (decimal/string/dateTime) и <value xsi:nil="true"/>
теперь сохраняют значение nil через object form {nilValue:true}. Раньше compile
эмитил типизированный default (xs:decimal>0, xs:string/>, xs:dateTime>0001-01-01)
вместо nil — мismatch на bit-perfect round-trip.

sample30: −22 строки (2034 → 2012).
2026-05-23 17:51:35 +03:00
Nick Shirokov f75c71064c feat(skd): userSettingPresentation на conditionalAppearance item
Build-ConditionalAppearance не читал userSettingPresentation
(read только viewMode/userSettingID), теперь сохраняет multilang
презентацию в JSON, а Emit-ConditionalAppearance эмитит её обратно.

sample30: −80 строк (2114 → 2034).
2026-05-23 17:27:21 +03:00
Nick Shirokov 5ca8ce2b64 fix(skd-compile): widths-unwrap и indent в template cell appearance
Две bug-фиксы для шаблонов:

1. PS-quirk: \$widths = if (\$t.widths) { @(\$t.widths) } else { @() }
   разворачивал одно-элементный массив в строку, после чего \$widths[0]
   возвращал первый Char (например '1' для "15.625"), а [double][Char]'1'=49.
   Заменил if-expression на обычный if-statement.

2. Indent в <dcsat:appearance>: компайлер ставил 4 таба вместо 5
   (и 5 вместо 6 у items внутри). Поправлено в обоих рантаймах.

sample30: −552 строки (2666 → 2114).
2026-05-23 17:18:50 +03:00
Nick Shirokov 5793f91ebb feat(skd): StandardPeriod с явными datами в dataParameters
Когда v8:StandardPeriod имеет non-default startDate/endDate, decompile
выдаёт object form {parameter, value:{variant, startDate, endDate}, ...}
вместо shorthand "P = Custom". Compile использует переданные даты
вместо boilerplate 0001-01-01.

sample30: −24 строки (2690 → 2666).
2026-05-23 16:54:26 +03:00
Nick Shirokov b83bbc333f feat(skd-compile): multilang static text в ячейках шаблона
Get-CellValue теперь пропускает dict без ключа value (multilang dict
{ru, en, ...}), а главный цикл Emit-Templates эмитит для таких ячеек
<dcsat:item xsi:type="dcsat:Field"><dcsat:value xsi:type="v8:LocalStringType">
с lwsTitle-структурой. Раньше multilang-ячейки терялись (Get-CellValue
возвращал null → cell не эмитился).

sample30: −180 строк (2870 → 2690).
2026-05-23 16:48:08 +03:00
Nick Shirokov a417b76e2c feat(skd-decompile): StandardPeriod Custom + use=false на dataParameters items
Build-DataParameters раньше пропускал variant=Custom в шорткоде, теряя как
сам StandardPeriod-маркер, так и use=false (читался из dcsset:use вместо
правильного dcscor:use). Теперь Custom попадает в shorthand как "=Custom",
compile воспроизводит StandardPeriod tag + boilerplate dates корректно.

sample30: −166 строк (3036 → 2870).
2026-05-23 16:41:38 +03:00
Nick Shirokov 659451815d feat(skd): nested sub-параметры и valueType в outputParameters wrapper
Wrapper расширен полями valueType (полный xsi:type значения, для bit-perfect
неизвестных compile параметров) и items (вложенные dcscor:item, паттерн
ТипДиаграммы.ВидПодписей внутри ТипДиаграммы).

sample30: −194 строки (3230 → 3036).
2026-05-23 16:36:49 +03:00
Nick Shirokov f271a6f6ba feat(skd): viewMode/userSettingID/userSettingPresentation на outputParameters items
Wrapper {value, ...} расширен: помимо use=false поддерживает viewMode,
userSettingID, userSettingPresentation на каждом item внутри
<dcsset:outputParameters>. Также value=Font dict теперь работает в wrapper.

sample30: −92 строки (3322 → 3230).
2026-05-23 16:19:48 +03:00
Nick Shirokov 342b3f0687 feat(skd): v8ui:Font в appearance + use=false в conditionalAppearance
Font хранится как объект {@type:Font, ref, faceName, height, bold, italic,
underline, strikeout, kind, scale} — все исходные атрибуты сохраняются для
bit-perfect round-trip.

Заодно Get-SettingsAppearance теперь читает dcscor:use на conditionalAppearance
items (раньше игнорировал — терялся use=false на appearance value).

sample30: −315 строк (3637 → 3322).
2026-05-23 16:04:12 +03:00
Nick Shirokov 4b3819762c docs(skd-dsl-spec): dataSetLinks полная схема + multi-orderExpression + пустые userField expressions 2026-05-23 15:55:30 +03:00
Nick Shirokov 5e864cb05f feat(skd): пустые detail/totalExpression в userFields
В UserFieldExpression XML присутствуют все 4 элемента (detailExpression,
detailExpressionPresentation, totalExpression, totalExpressionPresentation),
даже когда они пустые (<dcsset:totalExpression/>). Раньше пустые опускались.

decompile теперь читает по присутствию узла, compile эмитит self-closing
форму для пустых строк.

sample30: −106 строк (3743 → 3637).
2026-05-23 13:03:24 +03:00
Nick Shirokov a66246095c feat(skd): multi-orderExpression на dataSet field
На одном поле может быть несколько <orderExpression> (multi-sort fallback).
decompile сохраняет массив (single → object back-compat), compile принимает оба.

sample30: −30 строк, +2 отчёта в bit-perfect (27 with-diff).
2026-05-23 12:54:53 +03:00
Nick Shirokov 9b4bb3d9b8 feat(skd): dataSetLinks с расширенными атрибутами
skd-decompile теперь извлекает блоки <dataSetLink> на уровне схемы,
skd-compile поддерживает поля parameterListAllowed/startExpression/
linkConditionExpression (раньше был только parameter).

На sample30 это даёт −1100 строк diff (4873 → 3773), один отчёт
(АнализНачисленийНДССАвансовПолученных) переходит в bit-perfect.
2026-05-23 12:47:56 +03:00
Nick ShirokovandClaude Opus 4.7 b1eb8bebe3 docs(skd-dsl-spec): догон по последним коммитам
- order item: use=false в object form
- outputParameters: wrapper {value, use: false} для отключённого параметра
- table: top-level selection/conditionalAppearance/outputParameters
  (отдельно от column/row)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 22:13:47 +03:00
Nick ShirokovandClaude Opus 4.7 87bc274346 feat(skd-decompile): top-level блоки на StructureItemTable
Build-Structure для table теперь читает selection / outputParameters /
conditionalAppearance прямо на самой <dcsset:item xsi:type="StructureItemTable">,
не только внутри row/column.

Эффект на sample30: −906 строк diff (большой эффект — многие отчёты
с таблицами имеют top-level selection и outputParameters для названия
таблицы и формата вывода).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 22:07:51 +03:00
Nick ShirokovandClaude Opus 4.7 6a8efc9538 feat(skd-compile): top-level selection/condApp/outputParameters на StructureItemTable
StructureItemTable может иметь свои selection / conditionalAppearance /
outputParameters прямо на уровне таблицы (отдельно от row/column).
Раньше Emit-StructureItem для table эмитил только columns и rows; теперь
после rows эмитятся top-level блоки.

Аналогично сделано для chart (там было раньше).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 22:07:51 +03:00
Nick ShirokovandClaude Opus 4.7 0846740db7 feat(skd-compile): пустой <dcsset:filter/> на conditionalAppearance item
Платформа эмитит <dcsset:filter/> (self-closing, без условий) на
каждом condApp item, где фильтр не задан — это нормальная форма
"правило применяется ко всем строкам без дополнительных условий".

Compile теперь эмитит пустой тег если filter отсутствует/пуст.
Decompile-side уже корректно игнорировал пустой filter (Build-CondApp
читает items только если они есть).

Эффект на sample30: −252 строки diff.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 21:51:49 +03:00
Nick ShirokovandClaude Opus 4.7 480d828c35 feat(skd-decompile): use=false на outputParameters item
Build-OutputParameters теперь читает <dcscor:use>false</dcscor:use> на
item и сохраняет значение в форме {value, use: false}.

Эффект на sample30: −198 строк diff.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 21:37:27 +03:00
Nick ShirokovandClaude Opus 4.7 8009a8150f feat(skd-compile): use=false wrapper в outputParameters
outputParameters item тоже может иметь <dcscor:use>false</dcscor:use>
(например — отключённый «Заголовок» в варианте). Emit-OutputParameters
теперь распознаёт wrapper {value, use: false} и эмитит <dcscor:use>
в начале item, как уже делал Emit-AppearanceValue.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 21:37:26 +03:00
Nick ShirokovandClaude Opus 4.7 29a9fbe950 feat(skd): use=false на OrderItemField
OrderItemField в settings может иметь <dcsset:use>false</dcsset:use>
(отключённая сортировка-пункт пользовательских настроек). Build-Order
теперь читает use=false и переводит item в object form
{field, direction, use, viewMode}. Compile эмитит <dcsset:use> в
начале item, перед <dcsset:field>.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 21:28:50 +03:00
Nick ShirokovandClaude Opus 4.7 3832952400 feat(skd-decompile): use=false на appearance value items
Get-AppearanceDict теперь читает <dcscor:use>false</dcscor:use> на
appearance items и возвращает значение в форме {value, use: false}.
Compile-side уже принимал этот wrapper.

Эффект на sample30: −21 строка diff.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 21:21:48 +03:00
Nick ShirokovandClaude Opus 4.7 10fef03681 docs(skd-dsl-spec): догон по последним расширениям DSL
- conditionalAppearance: use=false, useInDontUse массив, multilang
  presentation, userSettingPresentation, расширены auto-detect типов
  appearance (Размещение, ГориZontальноеПоложение, ЦветТекста без
  префикса, числовые строки)
- outputParameters: новые типы для placement (РасположениеИтогов,
  РасположениеГруппировки и др.), ТипМакета
- structure group: use=false, userSettingID, userSettingPresentation
- table column/row + chart axis: conditionalAppearance, children
- settings: additionalProperties (служебные key/value свойства)
- parameter: inputParameters (ФорматРедактирования и т.п.)
- filter shorthand: упомянут auto-detect dcscor:DesignTimeValue

В SKILL.md изменения не вносятся — фичи редкие, для bit-perfect
round-trip с реальных схем.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 21:14:49 +03:00
Nick ShirokovandClaude Opus 4.7 957af1c421 feat(skd-decompile): user-settings на StructureItemGroup
Build-Structure для group теперь читает userSettingID и
userSettingPresentation (multilang dict) наряду с viewMode/itemsViewMode.

Try-StructureShorthand расширена — структура не сворачивается в
shorthand при наличии любого из новых полей (use, conditionalAppearance,
outputParameters, userSettingID, userSettingPresentation).

Эффект на sample30: −462 строки diff.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 21:09:38 +03:00
Nick ShirokovandClaude Opus 4.7 616ac2a23e feat(skd-compile): userSettingID/userSettingPresentation на StructureItemGroup
StructureItemGroup может быть зарегистрирована как пункт пользовательских
настроек (например, "По сотрудникам" — позволяет включить/выключить
группировку через UI). Поля userSettingID и userSettingPresentation
эмитятся после viewMode, перед itemsViewMode (платформенный порядок).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 21:09:37 +03:00
Nick ShirokovandClaude Opus 4.7 a9deeee2d0 feat(skd-compile): auto-detect DesignTimeValue в filter right
При парсинге shorthand "Поле = Перечисление.X.Y" Parse-FilterShorthand
уже распознавал тип dcscor:DesignTimeValue. Но в auto-detect веток
Emit-FilterItem (single-right и multi-right) этой проверки не было,
поэтому ссылочные значения из object form (где valueType не сохранён)
эмитились как xs:string.

Добавлено в обе ветки: проверка regex ^(Перечисление|Справочник|...
|Catalog|Enum|...)\. → dcscor:DesignTimeValue.

Эффект на sample30: −326 строк diff.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 21:01:38 +03:00
Nick ShirokovandClaude Opus 4.7 4af51235db feat(skd-decompile): conditionalAppearance внутри table/chart axis
Build-TableAxisBlock теперь читает <dcsset:conditionalAppearance>
блока column/row/point/series. Это типовая категория для table
с условным оформлением колонок (например, разный текст для разных
групп начислений в строке таблицы).

Эффект на sample30: −1026 строк diff.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 20:52:08 +03:00
Nick ShirokovandClaude Opus 4.7 da0b326c40 feat(skd-compile): conditionalAppearance внутри table/chart axis
Колонки/строки таблицы и оси диаграммы (column/row/point/series)
могут содержать собственный <dcsset:conditionalAppearance> — правила
оформления специфичные для этой оси. Emit-TableAxisBlock теперь его
эмитит между outputParameters и nested children.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 20:52:07 +03:00
Nick ShirokovandClaude Opus 4.7 65a2b5870d feat(skd-compile): типизация appearance/outputParameters значений
Реальные платформенные значения имеют конкретные xsi:type, которые
compile терял в roundtrip:

Output параметры (расширена таблица OUTPUT_PARAM_TYPES):
- РасположениеОбщихИтогов, РасположениеИтогов → DataCompositionTotalPlacement
- РасположениеГруппировки → DataCompositionFieldGroupPlacement
- РасположениеРесурсов → DataCompositionResourcesPlacement
- ТипМакета → DataCompositionGroupTemplateType

Appearance keys (новая key-type карта в Emit-AppearanceValue):
- Размещение → DataCompositionTextPlacementType
- ГоризонтальноеПоложение/ВертикальноеПоложение → v8ui:HorizontalAlign/VerticalAlign
- ОриентацияТекста, РасположениеИтогов, ТипМакета

Auto-detect расширения:
- Числовые строки (МинимальнаяШирина=40 и др.) → xs:decimal
- ЦветТекста/ЦветФона/ЦветГраницы без префикса style:/web:/win: → v8ui:Color
  (для значений "auto", "#FFC8C8" и т.п.)

Эффект на sample30: −1122 строки diff.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 20:45:18 +03:00
Nick ShirokovandClaude Opus 4.7 cab0b4d26b feat(skd-decompile): чтение attributeUseRestriction на DataSet field
DataSet field может иметь <attributeUseRestriction> наравне с
<useRestriction> — те же 4 подэлемента (field/condition/group/order),
но ограничения применяются к атрибутам ссылочного поля (например,
"запретить выбирать атрибуты Контрагента в фильтре").

Compile-side уже принимал attrRestrict в JSON; decompile теперь его
заполняет. Item переходит в object form при наличии attrRestrict.

Эффект на sample30: −257 строк diff.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 20:32:38 +03:00
Nick ShirokovandClaude Opus 4.7 092cd8ebb4 feat(skd-decompile): чтение additionalProperties в settings
<dcsset:additionalProperties> → dict в settings.additionalProperties.
Все значения xs:string, простые key→value пары.

Эффект на sample30: −121 строка diff.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 20:22:22 +03:00
Nick ShirokovandClaude Opus 4.7 f19032594c feat(skd-compile): additionalProperties в settings
<dcsset:additionalProperties> — список <v8:Property name="X">
<v8:Value xsi:type="xs:string">Y</v8:Value></v8:Property>. Используется
платформой для служебных свойств варианта (ВариантНаименование,
КлючВарианта, Адрес — URL tempstorage).

DSL: settings.additionalProperties = { "имя": "значение", ... }
Эмит — после itemsViewMode, перед закрытием settings.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 20:22:22 +03:00
Nick ShirokovandClaude Opus 4.7 a07a105024 feat(skd-decompile): inputParameters на параметрах + multilang presentation
Три связанных закрытия:
- Build-Parameter вызывает Read-InputParameters (раньше только Field)
- Read-InputParameters читает LocalStringType value как multilang dict
  (ФорматРедактирования и т.п.)
- Build-FilterItem (FilterItemComparison) читает <dcsset:presentation>
  с поддержкой multilang (Get-MLText + fallback InnerText); item
  переходит в object form при наличии presentation.

Эффект на sample30: −533 строки diff.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 20:06:47 +03:00
Nick ShirokovandClaude Opus 4.7 f5432eb48d feat(skd-compile): inputParameters на параметрах + multilang в value
Параметр (parameters[]) может иметь свой inputParameters блок —
например <ФорматРедактирования> со значением xs:LocalStringType.
Раньше Emit-InputParameters использовался только для DataSet field;
теперь подключён и к Emit-Parameter (вывод после <use>).

emit_input_parameters value: добавлена поддержка multilang dict
({ru, en, ...} → LocalStringType). Раньше падал в xs:string.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 20:06:46 +03:00
Nick ShirokovandClaude Opus 4.7 b8a6783ccf feat(skd-decompile): чтение multilang presentation в condApp и filter group
Build-ConditionalAppearance и FilterItemGroup читали presentation через
Get-Text (теряли multilang). Теперь читают через Get-MLText с fallback
на InnerText — multilang dict {ru, en, ...} сохраняется в JSON.

Эффект на sample30: −946 строк diff.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 19:40:59 +03:00
Nick ShirokovandClaude Opus 4.7 2b8cdc40ca feat(skd-compile): multilang presentation на conditionalAppearance item
При значении-словаре {ru, en, ...} эмитим <dcsset:presentation> как
LocalStringType с <v8:item>/<v8:lang>/<v8:content>; при строке —
по-прежнему xs:string. Раньше всегда жёстко xs:string, что давало
LOST для multilang.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 19:40:59 +03:00
Nick ShirokovandClaude Opus 4.7 013d3c3a01 feat(skd-decompile): чтение useInXxx и use=false на conditionalAppearance
Build-ConditionalAppearance теперь читает:
- <dcsset:use>false</...> → use: false
- любые <dcsset:useInXxx>DontUse</...> → элемент в массиве useInDontUse
  (имена тегов: useInGroup → "group", useInFieldsHeader → "fieldsHeader",
   и т.п.)

Эффект на sample30: −187 строк diff. Существенная часть LOST <use> и
LOST <content>/<lang> (внутри useInXxx-окружения) закрыта.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 19:34:32 +03:00
Nick ShirokovandClaude Opus 4.7 eee5aaafd3 feat(skd-compile): useInXxx и use=false на conditionalAppearance item
Расширение DSL для бит-перфект roundtrip на условном оформлении:
- use: false — отключённое правило (эмитится в начале item)
- useInDontUse: array — список областей где правило НЕ применяется
  (\"group\", \"hierarchicalGroup\", \"overall\", \"fieldsHeader\",
   \"header\", \"parameters\", \"filter\", \"resourceFieldsHeader\",
   \"overallHeader\", \"overallResourceFieldsHeader\")
  Compile эмитит <dcsset:useInGroup>DontUse</...> и т.п. в платформенном
  порядке.

Семантика: \"useIn\" в платформе — это белый список применения правила;
DSL хранит инверсный список (что отключено) — короче для редких
ограничений.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 19:34:32 +03:00
Nick ShirokovandClaude Opus 4.7 32e06cbc56 fix(skd-compile): всегда эмитить useRestriction для параметра
Платформа эмитит <useRestriction>true|false</useRestriction> у каждого
параметра безусловно. Раньше compile эмитил только если =true, что
приводило к LOST <useRestriction>false</useRestriction> в roundtrip.

Эффект на sample30: −84 строки diff.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 19:27:36 +03:00
Nick ShirokovandClaude Opus 4.7 77fc0cee2f feat(skd-decompile): nested children в table axis + structure-group default
Три связанных изменения:
- Build-TableAxisBlock читает вложенные <dcsset:item> как children
  (StructureItemGroup внутри row/column/point/series)
- Build-Structure принимает <dcsset:item> без явного xsi:type как
  StructureItemGroup (реальные XML используют такую default-форму
  для вложенных групп — раньше попадало в sentinel)
- Чтение use=false на StructureItemGroup

Эффект на sample30: −3253 строки diff (массовая категория —
table row almost always содержит nested grouping).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 18:55:02 +03:00
Nick ShirokovandClaude Opus 4.7 ac72ca8a51 feat(skd-compile): nested children + use=false на StructureItemGroup
В реальных отчётах внутри table row / column / chart axis (point/series)
часто живут вложенные группы — StructureItemGroup в children, со своими
groupItems / filter / order / selection / outputParameters / nested
children глубже. До этого Emit-TableAxisBlock эмитил только axis-level
поля, без children.

Также: на самой StructureItemGroup может быть use=false (отключённая
ветка структуры в settings) — добавлено в DSL и в эмит.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 18:55:02 +03:00
Nick ShirokovandClaude Opus 4.7 6e3632e5ff revert(skd-decompile): вернуть @normal shorthand-флаг
Раньше при наличии явного <viewMode>Normal</viewMode> decompile
переводил filter item в полноценный object form. Это раздувало JSON
без причины — @normal в shorthand функционально эквивалентен
"viewMode": "Normal" в object form, и compile уже его парсит.

Теперь: object form триггерится только реальными причинами
(userSettingPresentation, value-массив, dcscor:Field валуетайп);
явный Normal сохраняется как @normal в shorthand. Object form
по-прежнему может содержать "viewMode": "Normal" — это равнозначно.

Compile-side изменений не требуется. Spec обновлён.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 18:41:57 +03:00
Nick ShirokovandClaude Opus 4.7 e843cd8997 docs(skd-dsl-spec): догон по последним расширениям DSL
- selection items: use=false (на field и Auto), пример обновлён
- filter:
  - примеры с valueType: dcscor:Field (field-to-field comparison),
    value: [a,b,c] (multi-right InList), value: [] (ValueListType placeholder)
  - явное описание форм value (скаляр / массив / пустой массив)
  - FilterItemGroup принимает user-settings (viewMode/userSettingID/...)
- table column/row + chart points/series: name на всех осях (раньше
  только row), плюс user-settings поля
- секция «Стратегия сохранения viewMode» — описана модель explicit-only
  (decompile сохраняет точное присутствие, compile эмитит только заданное)
- @normal убран из перечня shorthand-флагов (Normal — default, не
  эмитится shorthand'ом; явный Normal переводит в object form)

В SKILL.md изменения не вносятся — фичи редкие, нужны для bit-perfect
round-trip с реальных схем.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 18:33:06 +03:00
Nick ShirokovandClaude Opus 4.7 4c26e97abf feat(skd-decompile): сохранение явного valueType в filter right (dcscor:Field)
Get-FilterValueWithType возвращает xsi:type вместе со значением.
Build-FilterItem теперь сохраняет valueType в object form, если тип
не xs:* (auto-detect compile обрабатывает xs:* сам). Это закрывает
field-to-field comparison: <right xsi:type=\"dcscor:Field\">FieldB</right>
теперь корректно эмитится обратно через valueType=\"dcscor:Field\".

Item переходит в object form при наличии valueType (shorthand не выразим).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 18:28:48 +03:00
Nick ShirokovandClaude Opus 4.7 cbad0fe743 fix(skd-compile): авто-определение xs:decimal по тексту числа
Для filter right value compile уже различал bool / native-number /
dateTime, но не различал числовые строки. Реальные отчёты часто хранят
сравнения как числа: <right xsi:type=\"xs:decimal\">5</right>.

Decompile при чтении видит "5" как строку (через InnerText), и без
этого фикса compile эмитил xs:string. Теперь добавлена проверка
по regex ^-?\d+(\.\d+)?$ → xs:decimal.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 18:28:48 +03:00
Nick ShirokovandClaude Opus 4.7 03cc59d243 feat(skd-decompile): чтение multi-right и ValueListType в filter
Build-FilterItem теперь читает все <dcsset:right> элементы (раньше
только первый — терялись значения для InList с несколькими values).
Первый <right> типа v8:ValueListType трактуется как пустой list-placeholder
(`value: []` в JSON).

Item переходит в object form если value — массив (shorthand не выразим
для multi-value/empty-list).

Shorthand fallback для null/empty value теперь снова `_` (placeholder).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 18:19:20 +03:00
Nick ShirokovandClaude Opus 4.7 540af9655d feat(skd-compile): filter right поддерживает массив и пустой ValueListType
DSL: value на filter item может быть массив:
- value: []           — пустой ValueListType placeholder (для InList с
                        пользовательскими настройками — пользователь
                        заполнит значения через UI)
- value: [3, 4, 5]    — InList с несколькими конкретными значениями
                        (compile эмитит несколько <right> подряд)
- value: 3            — single value (как раньше)

Compile автоопределяет тип каждого значения (bool/decimal/dateTime/string).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 18:19:20 +03:00
Nick ShirokovandClaude Opus 4.7 a7d5c46176 feat(skd): use=false на selection items
SelectedItemField и SelectedItemAuto могут иметь <dcsset:use>false</dcsset:use>
— отключённое поле выборки. Раньше игнорировалось при roundtrip.

DSL расширения:
- selection item object form: { field, use: false, title?, viewMode? }
- новый объект для отключённого Auto: { auto: true, use: false }

Decompile переходит в object form если есть use=false (помимо title и
viewMode); compile эмитит <use>false</use> в начале item (XML-порядок).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 18:05:27 +03:00
Nick ShirokovandClaude Opus 4.7 38b5445f15 fix(skd): откат implicit viewMode=Normal — сохраняем точное присутствие
Реальные отчёты непоследовательны: одни filter/item имеют
<viewMode>Normal</viewMode> с userSettingID, другие — нет (зависит от
момента редактирования через UI). Стратегия "compile добавляет implicit
Normal когда есть userSettingID" даёт ложные ADDED строки в bit-perfect.

Меняю на корректную модель:
- decompile сохраняет viewMode даже = 'Normal' если node физически
  присутствует в XML (object form переходит автоматически)
- compile эмитит viewMode только если явно задан в JSON

Применено к: filter (item + group), dataParameters, conditionalAppearance,
selection items, order items.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 18:01:09 +03:00
Nick ShirokovandClaude Opus 4.7 9aac032ac8 feat(skd-decompile): user-settings на table/chart axis и FilterItemGroup
Build-TableAxisBlock теперь читает name на любой оси (раньше только
для row), плюс viewMode (если non-Normal), userSettingID и
userSettingPresentation на самом блоке column/row/point/series.

Build-FilterItem для FilterItemGroup теперь читает presentation,
viewMode (non-Normal), userSettingID, userSettingPresentation —
раньше группа сохраняла только items.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 17:45:16 +03:00
Nick ShirokovandClaude Opus 4.7 f9774d799c feat(skd-compile): implicit viewMode=Normal + user-settings на FilterItemGroup и axis
Платформа эмитит <viewMode>Normal</viewMode> автоматически когда у
элемента есть <userSettingID> (это сигнал пользовательской настройки).
Теперь compile делает то же:
- filter item, dataParameters item, conditionalAppearance item, table
  axis (column/row/point/series) — все эмитят Normal если userSettingID
  задан и явный viewMode не указан

Кроме того: FilterItemGroup теперь поддерживает свой viewMode /
userSettingID / presentation / userSettingPresentation (наравне с
обычными filter items).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 17:45:15 +03:00
Nick ShirokovandClaude Opus 4.7 49f17ef5fd docs(skd-dsl-spec): availableValues на полях + conditionalAppearance в group
Догнал spec за последние коммиты — описаны availableValues на DataSet
fields (по аналогии с parameters) и conditionalAppearance как
доступное поле структурного элемента group.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 17:31:33 +03:00
Nick ShirokovandClaude Opus 4.7 515c82c398 feat(skd-decompile): conditionalAppearance + outputParameters внутри structure group
Build-Structure для StructureItemGroup теперь читает локальные
conditionalAppearance и outputParameters — раньше они терялись для
вложенных групп (только для top-level settings работало).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 17:29:18 +03:00