Найдено через новый debug-tool debug/skd-decompile/verify-roundtrip.ps1
(XML→decompile→compile→diff на сэмпле 30 ERP).
1. Emit-CalcFields appearance: третий дубликат-emitter с тем же
multilang-багом как был в Emit-AppearanceValue для field/cond. Унифи-
цирован через Emit-AppearanceValue. (compile.ps1+py)
2. Emit-SelectionItem: lwsTitle для folder + field-with-title
эмитили "$($item.folder)" — для hashtable получали "@{ru=X; en=Y}".
Унифицирован через Emit-MLText с новой опцией -NoXsiType
(lwsTitle в оригинале без xsi:type, в отличие от <title> в fields).
(compile.ps1+py)
3. Build-Parameter hidden detection: combo availableAsField=false +
useRestriction=true. Только availableAsField=false (без
useRestriction) → object form `availableAsField: false`.
На сэмпле 30 ERP roundtrip-diff: ADDED <content> 667 → 129
(multilang-потери в selection закрыты). Остаточные LOST <item> ~10k —
другие потери (attributeUseRestriction и проч.) — отдельная задача.
Versions: compile v1.35→v1.36, decompile v0.20→v0.21.
1. Внешний .sql теперь именуется <outputBasename>-<datasetName>.sql
(раньше просто <datasetName>.sql). Защищает от коллизий при
batch-decompile нескольких отчётов в одну папку: имена dataset'ов
часто совпадают ("НаборДанных1" — почти везде).
В JSON: "query": "@<outputBasename>-<datasetName>.sql".
2. ConvertTo-CompactJson: Try-InlineJson — пытается сериализовать
container на одну строку. Если результат + текущий indent ≤120
chars → inline; иначе multi-line. Применяется и к объектам и к
массивам (включая массивы из примитивов — раньше они всегда были
inline, что давало гигантские строки на длинных fields).
Примеры inline (объекты ≤120 chars):
- { "value": "B", "style": "header" }
- { "name": "Имя", "expression": "Имя" }
Длинные объекты и массивы — multi-line как раньше.
v0.19 → v0.20.
Заменил ConvertTo-Json (PS5.1) на собственный ConvertTo-CompactJson:
- 2-пробельный indent (вместо 4 + выравнивание keys по длине)
- Массивы примитивов (string/number/bool/null) — inline `[a, b, c]`
- Массивы с объектами/nested arrays — multi-line как раньше
- Кириллица в UTF-8 (без \uXXXX-escapes)
- Корректный escape строк (\\", \\, \n, \r, \t, \uXXXX для control chars)
Build-TotalField: shorthand "name: expr" для любого однострочного
expression. Раньше object form применялась когда expression не Func(arg).
Теперь — только когда есть group или expression многострочный.
Compile принимает любой shorthand вида "dataPath: expression" (Parse-
TotalShorthand делает split по первому ":").
Save-UserStyles тоже использует новый сериализатор.
Все 16 декомпиляционных snapshot'ов обновлены (косметика — JSON
структурно тот же, тесты round-trip проходят).
На реальном отчёте (целевой корпус): 405 → 264 строк (-35%).
v0.18 → v0.19.
Закрывает категорию B полностью на ERP-корпусе:
- selection.folder теперь рекурсивный: внутри items могут быть string,
{field, title}, или ещё одна {folder, items: [...]}. Compile/decompile
обходят дерево рекурсивно (Emit-SelectionItem / Build-SelectionItem).
- structure: новая ветка type=nestedObject с {objectID, settings:
{selection, filter, order, conditionalAppearance, outputParameters}}.
- groupFields теперь объектная форма {field, groupType?, periodAdditionType?}
когда не дефолт (Items / None). Compile уже принимал; decompile перестаёт
ставить warning GroupItemDetails. Try-StructureShorthand игнорирует
object-form поля при сворачивании в строку.
- Refactor: Build-Structure для StructureItemGroup теперь использует
общий Get-GroupFields вместо дублированного inline-кода.
В SKILL.md не добавляем (формы редкие/сложные, модель не пишет с нуля).
Новый тест structure-nested-and-folder покрывает все три случая bit-perfect.
Versions: compile v1.30→v1.31, decompile v0.12→v0.13.
На сэмпле 30 ERP-отчётов: 754 → 32 sentinel'ов (-96%), clean 4 → 24/30.
Остаточные 32 — все TemplateStyleMismatch (категория C, диагностика).