diff --git a/.claude/skills/skd-compile/scripts/skd-compile.ps1 b/.claude/skills/skd-compile/scripts/skd-compile.ps1
index ed5824f6..a23ac423 100644
--- a/.claude/skills/skd-compile/scripts/skd-compile.ps1
+++ b/.claude/skills/skd-compile/scripts/skd-compile.ps1
@@ -886,6 +886,33 @@ function Emit-SingleParam {
X "`t`ttrue"
}
+ # AvailableValues
+ if ($p -isnot [string] -and $p.availableValues) {
+ foreach ($av in $p.availableValues) {
+ $avVal = "$($av.value)"
+ $avType = "xs:string"
+ if ($avVal -match '^(Перечисление|Справочник|ПланСчетов|Документ|ПланВидовХарактеристик|ПланВидовРасчета)\.') {
+ $avType = "dcscor:DesignTimeValue"
+ }
+ X "`t`t"
+ X "`t`t`t$(Esc-Xml $avVal)"
+ if ($av.presentation) {
+ X "`t`t`t"
+ X "`t`t`t`t"
+ X "`t`t`t`t`tru"
+ X "`t`t`t`t`t$(Esc-Xml "$($av.presentation)")"
+ X "`t`t`t`t"
+ X "`t`t`t"
+ }
+ X "`t`t"
+ }
+ }
+
+ # DenyIncompleteValues
+ if ($p -isnot [string] -and $p.denyIncompleteValues -eq $true) {
+ X "`t`ttrue"
+ }
+
# Use
if ($p -isnot [string] -and $p.use) {
X "`t`t"
diff --git a/.claude/skills/skd-compile/scripts/skd-compile.py b/.claude/skills/skd-compile/scripts/skd-compile.py
index 624ee429..cf7e3441 100644
--- a/.claude/skills/skd-compile/scripts/skd-compile.py
+++ b/.claude/skills/skd-compile/scripts/skd-compile.py
@@ -754,6 +754,28 @@ def emit_single_param(lines, p, parsed):
if parsed.get('valueListAllowed'):
lines.append('\t\ttrue')
+ # AvailableValues
+ if p is not None and not isinstance(p, str) and p.get('availableValues'):
+ for av in p['availableValues']:
+ av_val = str(av.get('value', ''))
+ av_type = 'xs:string'
+ if re.match(r'^(Перечисление|Справочник|ПланСчетов|Документ|ПланВидовХарактеристик|ПланВидовРасчета)\.', av_val):
+ av_type = 'dcscor:DesignTimeValue'
+ lines.append('\t\t')
+ lines.append(f'\t\t\t{esc_xml(av_val)}')
+ if av.get('presentation'):
+ lines.append('\t\t\t')
+ lines.append('\t\t\t\t')
+ lines.append('\t\t\t\t\tru')
+ lines.append(f'\t\t\t\t\t{esc_xml(str(av["presentation"]))}')
+ lines.append('\t\t\t\t')
+ lines.append('\t\t\t')
+ lines.append('\t\t')
+
+ # DenyIncompleteValues
+ if p is not None and not isinstance(p, str) and p.get('denyIncompleteValues') is True:
+ lines.append('\t\ttrue')
+
# Use
if p is not None and not isinstance(p, str) and p.get('use'):
lines.append(f'\t\t')
diff --git a/.claude/skills/skd-edit/scripts/skd-edit.ps1 b/.claude/skills/skd-edit/scripts/skd-edit.ps1
index 1c5beb19..abc9c1ca 100644
--- a/.claude/skills/skd-edit/scripts/skd-edit.ps1
+++ b/.claude/skills/skd-edit/scripts/skd-edit.ps1
@@ -10,7 +10,7 @@ param(
"add-dataParameter","add-order","add-selection","add-dataSetLink",
"add-dataSet","add-variant","add-conditionalAppearance",
"set-query","patch-query","set-outputParameter","set-structure",
- "modify-field","modify-filter","modify-dataParameter",
+ "modify-field","modify-filter","modify-dataParameter","modify-parameter",
"clear-selection","clear-order","clear-filter",
"remove-field","remove-total","remove-calculated-field","remove-parameter","remove-filter")]
[string]$Operation,
@@ -1655,6 +1655,109 @@ switch ($Operation) {
}
}
+ "modify-parameter" {
+ foreach ($val in $values) {
+ # Parse: "ParamName key=value key=value"
+ $parts = $val -split '\s+', 2
+ $paramName = $parts[0].Trim()
+ $rest = if ($parts.Count -gt 1) { $parts[1].Trim() } else { "" }
+
+ # Find parameter element
+ $paramEl = Find-ElementByChildValue $xmlDoc.DocumentElement "parameter" "name" $paramName $schNs
+ if (-not $paramEl) {
+ Write-Host "[WARN] Parameter `"$paramName`" not found — skipped"
+ continue
+ }
+
+ $childIndent = Get-ChildIndent $paramEl
+
+ # Parse key=value pairs (special handling for availableValue)
+ if ($rest -match '^availableValue=(.+)') {
+ $avRest = $rest -replace '^availableValue=', ''
+ # Parse: "Перечисление...X presentation=текст"
+ $avParts = $avRest -split '\s+presentation=', 2
+ $avValue = $avParts[0].Trim()
+ $avPresentation = if ($avParts.Count -gt 1) { $avParts[1].Trim() } else { "" }
+
+ # Detect value type
+ $avType = "xs:string"
+ if ($avValue -match '^(Перечисление|Справочник|ПланСчетов|Документ|ПланВидовХарактеристик|ПланВидовРасчета)\.') {
+ $avType = "dcscor:DesignTimeValue"
+ }
+
+ $avLines = @()
+ $avLines += "$childIndent"
+ $avLines += "$childIndent`t$(Esc-Xml $avValue)"
+ if ($avPresentation) {
+ $avLines += "$childIndent`t"
+ $avLines += "$childIndent`t`t"
+ $avLines += "$childIndent`t`t`tru"
+ $avLines += "$childIndent`t`t`t$(Esc-Xml $avPresentation)"
+ $avLines += "$childIndent`t`t"
+ $avLines += "$childIndent`t"
+ }
+ $avLines += "$childIndent"
+ $fragXml = $avLines -join "`r`n"
+
+ # Insert before denyIncompleteValues/use or at end
+ $refNode = $null
+ foreach ($tag in @("denyIncompleteValues","use")) {
+ $found = $paramEl.SelectSingleNode($tag)
+ if ($found) { $refNode = $found; break }
+ }
+ $nodes = Import-Fragment $xmlDoc $fragXml
+ foreach ($node in $nodes) {
+ Insert-BeforeElement $paramEl $node $refNode $childIndent
+ }
+ Write-Host "[OK] Parameter `"$paramName`": availableValue added"
+ } else {
+ # Simple key=value pairs: use=Always, denyIncompleteValues=true
+ $kvPairs = [regex]::Matches($rest, '(\w+)=(\S+)')
+ foreach ($kv in $kvPairs) {
+ $key = $kv.Groups[1].Value
+ $value = $kv.Groups[2].Value
+
+ $existing = $paramEl.SelectSingleNode($key)
+ if ($existing) {
+ $existing.InnerText = $value
+ Write-Host "[OK] Parameter `"$paramName`": $key updated to $value"
+ } else {
+ # Determine insertion order
+ $afterTags = switch ($key) {
+ "denyIncompleteValues" { @("availableValue","useRestriction","availableAsField","expression","value","valueType","title","name") }
+ "use" { @("denyIncompleteValues","availableValue","useRestriction","availableAsField","expression","value","valueType","title","name") }
+ default { @("name") }
+ }
+ $refNode = $null
+ foreach ($tag in @("denyIncompleteValues","use")) {
+ if ($tag -eq $key) { continue }
+ $found = $paramEl.SelectSingleNode($tag)
+ if ($found -and ($afterTags -contains $tag -eq $false)) {
+ $refNode = $found; break
+ }
+ }
+
+ $fragXml = "$childIndent<$key>$(Esc-Xml $value)$key>"
+ $nodes = Import-Fragment $xmlDoc $fragXml
+ foreach ($node in $nodes) {
+ # Append before closing tag (last whitespace child)
+ $lastChild = $paramEl.LastChild
+ if ($lastChild.NodeType -eq 'Whitespace' -or $lastChild.NodeType -eq 'SignificantWhitespace') {
+ $paramEl.InsertBefore($node, $lastChild) | Out-Null
+ } else {
+ $paramEl.AppendChild($node) | Out-Null
+ }
+ }
+ # Add trailing whitespace
+ $ws = $xmlDoc.CreateWhitespace("`r`n$($childIndent -replace '`t$','')")
+ $paramEl.AppendChild($ws) | Out-Null
+ Write-Host "[OK] Parameter `"$paramName`": $key=$value added"
+ }
+ }
+ }
+ }
+ }
+
"add-filter" {
$settings = Resolve-VariantSettings
$varName = Get-VariantName
diff --git a/.claude/skills/skd-edit/scripts/skd-edit.py b/.claude/skills/skd-edit/scripts/skd-edit.py
index 2c596f3e..27123fac 100644
--- a/.claude/skills/skd-edit/scripts/skd-edit.py
+++ b/.claude/skills/skd-edit/scripts/skd-edit.py
@@ -18,7 +18,7 @@ VALID_OPS = [
"add-dataParameter", "add-order", "add-selection", "add-dataSetLink",
"add-dataSet", "add-variant", "add-conditionalAppearance",
"set-query", "patch-query", "set-outputParameter", "set-structure",
- "modify-field", "modify-filter", "modify-dataParameter",
+ "modify-field", "modify-filter", "modify-dataParameter", "modify-parameter",
"clear-selection", "clear-order", "clear-filter",
"remove-field", "remove-total", "remove-calculated-field", "remove-parameter", "remove-filter",
]
@@ -1435,6 +1435,68 @@ elif operation == "add-parameter":
if parsed.get("autoDates"):
print('[OK] Auto-parameters "\u0414\u0430\u0442\u0430\u041d\u0430\u0447\u0430\u043b\u0430", "\u0414\u0430\u0442\u0430\u041e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f" added')
+elif operation == "modify-parameter":
+ for val in values:
+ parts = val.split(None, 1)
+ param_name = parts[0].strip()
+ rest = parts[1].strip() if len(parts) > 1 else ""
+
+ param_el = find_element_by_child_value(xml_doc, "parameter", "name", param_name, SCH_NS)
+ if param_el is None:
+ print(f'[WARN] Parameter "{param_name}" not found -- skipped')
+ continue
+
+ child_indent = get_child_indent(param_el)
+
+ if rest.startswith("availableValue="):
+ av_rest = rest[len("availableValue="):]
+ av_parts = av_rest.split(" presentation=", 1)
+ av_value = av_parts[0].strip()
+ av_presentation = av_parts[1].strip() if len(av_parts) > 1 else ""
+
+ av_type = "xs:string"
+ if re.match(r'^(Перечисление|Справочник|ПланСчетов|Документ|ПланВидовХарактеристик|ПланВидовРасчета)\.', av_value):
+ av_type = "dcscor:DesignTimeValue"
+
+ av_lines = [f"{child_indent}"]
+ av_lines.append(f'{child_indent}\t{esc_xml(av_value)}')
+ if av_presentation:
+ av_lines.append(f'{child_indent}\t')
+ av_lines.append(f"{child_indent}\t\t")
+ av_lines.append(f"{child_indent}\t\t\tru")
+ av_lines.append(f"{child_indent}\t\t\t{esc_xml(av_presentation)}")
+ av_lines.append(f"{child_indent}\t\t")
+ av_lines.append(f"{child_indent}\t")
+ av_lines.append(f"{child_indent}")
+ frag_xml = "\r\n".join(av_lines)
+
+ ref_node = None
+ for tag in ["denyIncompleteValues", "use"]:
+ found = param_el.find(tag)
+ if found is not None:
+ ref_node = found
+ break
+ nodes = import_fragment(xml_doc, frag_xml)
+ for node in nodes:
+ insert_before_element(param_el, node, ref_node, child_indent)
+ print(f'[OK] Parameter "{param_name}": availableValue added')
+ else:
+ for m in re.finditer(r'(\w+)=(\S+)', rest):
+ key, value = m.group(1), m.group(2)
+ existing = param_el.find(key)
+ if existing is not None:
+ existing.text = value
+ print(f'[OK] Parameter "{param_name}": {key} updated to {value}')
+ else:
+ frag_xml = f"{child_indent}<{key}>{esc_xml(value)}{key}>"
+ nodes = import_fragment(xml_doc, frag_xml)
+ for node in nodes:
+ last_child = list(param_el)[-1] if len(param_el) else None
+ if last_child is not None:
+ last_child.tail = (last_child.tail or "") + "\r\n" + child_indent
+ param_el.append(node)
+ print(f'[OK] Parameter "{param_name}": {key}={value} added')
+
elif operation == "add-filter":
settings = resolve_variant_settings()
var_name = get_variant_name()