feat(form-decompile,form-compile): частичная/минимальная форма ListSettings (дескриптор settings.listSettings)

Раундтрип TOTAL 21→0, match 153→156. Компилятор всегда эмитил ПОЛНЫЙ каноничный
скелет <ListSettings> (filter+order+conditionalAppearance+itemsViewMode+
itemsUserSettingID), а ~7% форм имеют частичный (напр. только <filter> с
userSettingID) → лишние контейнеры = ADDED.

- Декомпилятор: Get-ListSettingsShape фиксирует «форму» скелета в
  settings.listSettings (ordered-карта present top-level: filter/order/
  conditionalAppearance → блок-мета 'v'/'u'/'vu'/''; itemsViewMode/
  itemsUserSettingID → true). Дескриптор пишется ТОЛЬКО для не-каноничных форм
  ($null для полного канона и неподдержанных top-level item/dataParameters/…).
- Компилятор: при наличии дескриптора эмитит ТОЛЬКО указанные части (контент из
  settings.filter/order/CA, блок-мета из дескриптора); иначе — полный канон
  (без изменений). Аддитивно, дескриптор-gated → 93% канон-форм не затронуты.

Зеркало py. Формы ОстаткиАлкогольнойПродукцииЕГАИС (filter-only) и
ОстаткиПартийЗЕРНО (filter+order) → ListSettings бит-в-бит. Регресс 39/39
(канон-путь). Партиал-путь — harness + provenance (подмножество канона).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-06-09 16:51:14 +03:00
co-authored by Claude Opus 4.8
parent cc8b283f1b
commit 1ed23b2a08
4 changed files with 83 additions and 14 deletions
@@ -1,4 +1,4 @@
# form-decompile v0.69 — Decompile 1C managed Form.xml to JSON DSL (draft)
# form-decompile v0.70 — Decompile 1C managed Form.xml to JSON DSL (draft)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью.
param(
@@ -113,6 +113,31 @@ function Test-ListSettingsHasContent {
return $false
}
# Форма ListSettings: ordered-карта present top-level элементов (filter/order/conditionalAppearance →
# блок-мета 'v'/'u'/'vu'/''; itemsViewMode/itemsUserSettingID → $true). Возвращает $null, если форма ==
# полному каноничному скелету (компилятор регенерит сам) ИЛИ содержит неподдержанные top-level элементы
# (item/dataParameters/viewMode/userSettingID/… → fallback на канон). Иначе — дескриптор для компилятора.
function Get-ListSettingsShape {
param($lsNode)
if (-not $lsNode) { return $null }
$shape = [ordered]@{}
foreach ($child in $lsNode.ChildNodes) {
if ($child.NodeType -ne [System.Xml.XmlNodeType]::Element) { continue }
$tag = $child.LocalName
if ($tag -in @('filter','order','conditionalAppearance')) {
$hasVM = $null -ne $child.SelectSingleNode("dcsset:viewMode", $ns)
$hasUS = $null -ne $child.SelectSingleNode("dcsset:userSettingID", $ns)
$shape[$tag] = "$(if ($hasVM) {'v'})$(if ($hasUS) {'u'})"
} elseif ($tag -eq 'itemsViewMode') { $shape['itemsViewMode'] = $true }
elseif ($tag -eq 'itemsUserSettingID') { $shape['itemsUserSettingID'] = $true }
else { return $null } # item/dataParameters/itemsUserSettingPresentation/… → канон-fallback
}
# Полный каноничный скелет → опускаем (компилятор регенерит)
if ($shape.Count -eq 5 -and $shape['filter'] -eq 'vu' -and $shape['order'] -eq 'vu' -and `
$shape['conditionalAppearance'] -eq 'vu' -and $shape['itemsViewMode'] -eq $true -and $shape['itemsUserSettingID'] -eq $true) { return $null }
return $shape
}
# --- 1b. Ring-3 scan: конструкции вне зоны поддержки (draft list) ---
function Fail-Ring3 {
param([string]$kind, [string]$loc)
@@ -1955,6 +1980,10 @@ if ($attrsNode) {
$ca = Build-ConditionalAppearance -caNode $caNode -loc "settings/conditionalAppearance"
if (@($ca).Count -gt 0) { $so['conditionalAppearance'] = @($ca) }
}
# Форма скелета ListSettings: дескриптор только для НЕ-каноничных форм (частичные/минимальные).
# Канон → $null (компилятор регенерит полный скелет, как раньше).
$lsShape = Get-ListSettingsShape $lsNode
if ($null -ne $lsShape) { $so['listSettings'] = $lsShape }
}
if ($so.Count -gt 0) { $ao['settings'] = $so }
}