From 704fbc9f284843049bda928d7f112907d529d80e Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Sun, 26 Apr 2026 16:59:06 +0300 Subject: [PATCH] =?UTF-8?q?feat(verify-snapshots):=20=D0=BF=D0=BB=D0=B0?= =?UTF-8?q?=D1=82=D1=84=D0=BE=D1=80=D0=BC=D0=B5=D0=BD=D0=BD=D0=B0=D1=8F=20?= =?UTF-8?q?=D0=B2=D0=B5=D1=80=D0=B8=D1=84=D0=B8=D0=BA=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D1=8F=20mxl-compile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Готовый Template.xml оборачивается в исходники EPF: epf-init создаёт скелет, template-add регистрирует SpreadsheetDocument-макет, MXL копируется поверх дефолтного, далее epf-build реально проверяет, что платформа принимает разметку. mxl-compile убран из STANDALONE_SKILLS. Co-Authored-By: Claude Opus 4.7 (1M context) --- tests/skills/verify-snapshots.mjs | 57 ++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/tests/skills/verify-snapshots.mjs b/tests/skills/verify-snapshots.mjs index 8da1b742..8dfc78aa 100644 --- a/tests/skills/verify-snapshots.mjs +++ b/tests/skills/verify-snapshots.mjs @@ -317,7 +317,7 @@ function runPreSteps(preRun, workDir, runtime, log) { // Standalone file skills — produce files (not configs), platform load = just run script const STANDALONE_SKILLS = new Set([ 'skd-compile', 'skd-edit', 'skd-info', 'skd-validate', - 'mxl-compile', 'mxl-decompile', 'mxl-info', 'mxl-validate', + 'mxl-decompile', 'mxl-info', 'mxl-validate', ]); // Standalone skills that CAN be platform-verified by wrapping their output in @@ -325,6 +325,10 @@ const STANDALONE_SKILLS = new Set([ // schema and we know if it's accepted. const SKD_PLATFORM_VERIFY = new Set(['skd-compile', 'skd-edit']); +// MXL: wrap produced Template.xml as a SpreadsheetDocument template inside +// an EPF source and run epf-build — platform parses the macro layout. +const MXL_PLATFORM_VERIFY = new Set(['mxl-compile']); + // EPF/ERF skills — verified by epf-build on the produced source. // Map skill -> output extension (.epf/.erf). const EPF_SKILLS = new Map([ @@ -567,6 +571,57 @@ async function verifyCase(skillName, caseName, skillConfig, caseData, opts) { return result; } + if (MXL_PLATFORM_VERIFY.has(skillName)) { + const tplName = caseData.params?.outputPath || 'Template.xml'; + const tplPath = join(workDir, tplName); + if (!existsSync(tplPath)) { + result.errors.push(`Output not produced at ${tplPath}`); + return result; + } + const epfDir = join(workDir, 'epf-src'); + const epfOutDir = join(workDir, 'epf-build'); + mkdirSync(epfOutDir, { recursive: true }); + try { + execSkill(opts.runtime, 'epf-init/scripts/init', ['-Name', 'TestProc', '-SrcDir', epfDir]); + log('epf-init', true); + } catch (e) { + const detail = (e.stderr || e.stdout || e.message).trim(); + log('epf-init', false, detail); + result.errors.push(`epf-init failed: ${detail.substring(0, 500)}`); + return result; + } + try { + execSkill(opts.runtime, 'template-add/scripts/add-template', [ + '-ObjectName', 'TestProc', + '-TemplateName', 'Макет', + '-TemplateType', 'SpreadsheetDocument', + '-SrcDir', epfDir, + ]); + log('template-add', true); + } catch (e) { + const detail = (e.stderr || e.stdout || e.message).trim(); + log('template-add', false, detail); + result.errors.push(`template-add failed: ${detail.substring(0, 500)}`); + return result; + } + const tplDest = join(epfDir, 'TestProc', 'Templates', 'Макет', 'Ext', 'Template.xml'); + cpSync(tplPath, tplDest, { force: true }); + try { + execSkill(opts.runtime, 'epf-build/scripts/epf-build', [ + '-V8Path', opts.v8ctx.v8path, + '-SourceFile', join(epfDir, 'TestProc.xml'), + '-OutputFile', join(epfOutDir, 'TestProc.epf'), + ], 180_000); + log('epf-build', true, 'platform accepted MXL'); + result.passed = true; + } catch (e) { + const detail = (e.stderr || e.stdout || e.message).trim(); + log('epf-build', false, detail); + result.errors.push(`epf-build rejected MXL: ${detail.substring(0, 1000)}`); + } + return result; + } + if (isStandalone) { result.passed = true; log('platform-load', true, 'skipped (standalone file, not a config)');