fix(support-guard): не блокировать автономные внешние обработки/отчёты (#39)

При поиске корня конфигурации guard поднимался по дереву вверх и «проскакивал»
собственный корень автономной внешней обработки/отчёта (ExternalDataProcessor /
ExternalReport), лежащей внутри дерева выгрузки конфигурации. Если у охватывающей
конфигурации выключена возможность изменения (G=1), внешний объект ложно
блокировался как «объект типовой конфигурации на поддержке», а info-навыки
выводили нерелевантную строку «Поддержка: конфигурация read-only».

Теперь climb останавливается на границе автономного объекта: если целевой файл или
встреченный по пути <каталог>.xml имеет корень ExternalDataProcessor/ExternalReport,
подъём прекращается и объект не привязывается к конфигурации. Корень внешнего объекта
всегда глубже Configuration.xml, поэтому встречается первым — регрессии для обычных
объектов конфигурации нет.

Синхронно во всех копиях guard-а (навыки автономны): хук support-state.mjs
(decideSupport + findConfigRoot), 16 мутаторов (Assert-EditAllowed), 5 info-навыков
и meta-info (Get-SupportStatusForPath / Get-ObjectSupportStatus) — ps1 и py. Для
info-навыков строка «Поддержка:» для внешнего объекта опускается.

Тесты: hooks/test/run.mjs — секция внешней границы (G=1 + встроенная EPF);
tests/skills — кейсы mxl-compile (guard пропускает) и mxl-info (строка опущена).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-07-17 19:46:54 +03:00
co-authored by Claude Opus 4.8
parent e7b5df4d50
commit ddc1641176
64 changed files with 1400 additions and 58 deletions
+19 -2
View File
@@ -1,4 +1,4 @@
# meta-info v1.3 — Compact summary of 1C metadata object (Python port)
# meta-info v1.4 — Compact summary of 1C metadata object (Python port)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import os
@@ -472,8 +472,23 @@ def get_ws_operations(child_objs):
# ── Support status of this object (Ext/ParentConfigurations.bin) ──
# See docs/1c-support-state-spec.md. Walks up to the config root, decodes the
# object's support rule. Never throws — degrades to "не на поддержке".
def _meta_is_external_root(xml_path):
if not os.path.isfile(xml_path):
return False
try:
mx = etree.parse(xml_path).getroot()
for child in mx:
if isinstance(child.tag, str):
return child.tag.split("}")[-1] in ("ExternalDataProcessor", "ExternalReport")
except Exception:
return False
return False
def get_object_support_status(obj_uuid):
try:
if _meta_is_external_root(object_path):
return None
d = os.path.dirname(object_path)
bin_path = None
for _ in range(8):
@@ -703,7 +718,9 @@ if not drill_done:
header += f' \u2014 "{synonym}"'
header += " ==="
out(header)
out(f"Поддержка: {get_object_support_status(type_node.get('uuid', ''))}")
_support = get_object_support_status(type_node.get('uuid', ''))
if _support is not None:
out(f"Поддержка: {_support}")
# Type presentation (ref objects)
if is_ref_object: