test(verify-snapshots): убрать маскирующий hostEdit — верификатор не правит проверяемый объект

Верификатор для плана счетов с субконто без extDimensionTypes сам выдумывал стаб-ПВХ И патчил
план через meta-edit (modify-property ExtDimensionTypes=…). Это маскировка: в 1С грузилась
изменённая версия, а не та, что выдал meta-compile — байт-снэпшот (пустой <ExtDimensionTypes/>)
расходился с загружаемым артефактом. К тому же для главного объекта правка не работала вовсе
(hostEdit в Step 3.5 бил по объекту до его компиляции в Step 4 → «object not found»).

Убран весь механизм hostEdits (единственный источник — ветка ChartOfAccounts в getStructuralDeps).
Теперь верификатор создаёт только стабы ЗАВИСИМОСТЕЙ (объектов, на которые вход РЕАЛЬНО ссылается,
через extractTypeRefs); postEdit правит стабы-зависимости (легитимно), но не проверяемый объект.

Следствие: план с ext-dim обязан сам нести extDimensionTypes. Кейсы form-compile-from-object
(chartofaccounts-item/list) переведены на самодостаточный паттерн — реальный ПВХ ВидыСубконто
в preRun (типизированные предопределённые) + явный extDimensionTypes. Фикстура ПС теперь несёт
<ExtDimensionTypes>ChartOfCharacteristicTypes.ВидыСубконто (консистентно с загрузкой); Form.xml
не изменился. Байт 12/12, 1С-cert обоих ✓. Прочие ссылки на ПС (accounting-register) не затронуты —
makeStubDSL даёт maxExtDimensionCount:0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-07-05 21:06:55 +03:00
co-authored by Claude Opus 4.8
parent 2c50030789
commit faec6e6f19
13 changed files with 258 additions and 48 deletions
+6 -46
View File
@@ -135,9 +135,8 @@ function extractTypeRefs(input) {
function getStructuralDeps(input) {
const deps = [];
const hostEdits = []; // edits applied to the host (the input that triggered the dep)
const inputs = Array.isArray(input) ? input : [input];
if (!inputs[0] || !inputs[0].type) return { deps, hostEdits };
if (!inputs[0] || !inputs[0].type) return deps;
for (const inp of inputs) {
const regTypePrefix = {
@@ -178,28 +177,9 @@ function getStructuralDeps(input) {
}
}
break;
case 'ChartOfAccounts': {
// ExtDimensionTypes (виды субконто) link is required when the chart uses
// any ExtDimension at all — otherwise platform rejects forms that bind to
// Объект.ExtDimensionTypes.*.
const usesExtDim = (inp.maxExtDimensionCount && inp.maxExtDimensionCount > 0)
|| (Array.isArray(inp.extDimensionAccountingFlags) && inp.extDimensionAccountingFlags.length > 0);
if (usesExtDim && !inp.extDimensionTypes) {
const stubName = `ВидыСубконтоСтаб${inp.name}`;
deps.push({
type: 'ChartOfCharacteristicTypes', name: stubName,
dsl: { type: 'ChartOfCharacteristicTypes', name: stubName, codeLength: 9, descriptionLength: 100 },
});
hostEdits.push({
hostType: 'ChartOfAccounts', hostName: inp.name,
op: 'modify-property', val: `ExtDimensionTypes=ChartOfCharacteristicTypes.${stubName}`,
});
}
break;
}
}
}
return { deps, hostEdits };
return deps;
}
// ─── Stub creation ──────────────────────────────────────────────────────────
@@ -483,10 +463,10 @@ async function verifyCase(skillName, caseName, skillConfig, caseData, opts) {
if (configDir && allInputs.length > 0) {
const mainNames = new Set(allInputs.map(i => `${i.type}.${i.name}`));
// Structural deps (scanned across both main input and preRun inputs)
const { deps: structDeps, hostEdits: structHostEdits } = getStructuralDeps(allInputs);
// Stash host edits on the result so we can apply them after preRun.
result._structHostEdits = structHostEdits;
// Structural deps (scanned across both main input and preRun inputs).
// NB: только зависимости (стабы объектов, на которые ССЫЛАЕТСЯ вход). Верификатор НЕ правит сам
// проверяемый объект — иначе в 1С грузится не то, что выдал компилятор (маскировка дефекта DSL).
const structDeps = getStructuralDeps(allInputs);
const structDSLs = new Map();
const structPostEdits = new Map();
for (const dep of structDeps) {
@@ -550,26 +530,6 @@ async function verifyCase(skillName, caseName, skillConfig, caseData, opts) {
return result;
}
// ── Step 3.5: host-level structural edits (apply to objects created in preRun) ──
if (configDir && result._structHostEdits?.length) {
for (const he of result._structHostEdits) {
const dir = TYPE_TO_DIR[he.hostType];
const objPath = dir ? join(configDir, dir, he.hostName) : null;
if (!objPath || !existsSync(objPath)) {
result.warnings.push(`HostEdit skipped (object not found): ${he.hostType}.${he.hostName}`);
continue;
}
try {
execSkill(opts.runtime, 'meta-edit/scripts/meta-edit',
['-ObjectPath', objPath, '-Operation', he.op, '-Value', he.val]);
log(`hostEdit: ${he.hostType}.${he.hostName}`, true, `${he.op} ${he.val}`);
} catch (e) {
log(`hostEdit: ${he.hostType}.${he.hostName}`, false, e.stderr || e.message);
result.warnings.push(`HostEdit failed: ${he.hostType}.${he.hostName}`);
}
}
}
// ── Step 4: Main skill script ──
let inputFile = null;
if (caseData.input !== undefined) {