From cd74afa5e093a789dcc915699d02ee011445d3f6 Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Sun, 26 Apr 2026 16:42:00 +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=20template-add=20=D0=B8=20help-add?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit После main-скрипта определяется тип артефакта в workDir: Configuration.xml → обычная загрузка конфигурации, иначе по корню *.xml выбирается ветка epf-build (.epf для ExternalDataProcessor, .erf для ExternalReport). Для кейсов с cf-init теперь configDir переустанавливается на workDir, так что конфиг действительно грузится в БД, а не пропускается. Co-Authored-By: Claude Opus 4.7 (1M context) --- tests/skills/verify-snapshots.mjs | 35 ++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/tests/skills/verify-snapshots.mjs b/tests/skills/verify-snapshots.mjs index bf30a01f..8da1b742 100644 --- a/tests/skills/verify-snapshots.mjs +++ b/tests/skills/verify-snapshots.mjs @@ -332,6 +332,10 @@ const EPF_SKILLS = new Map([ ['erf-init', '.erf'], ]); +// Skills that produce either an EPF/ERF source or a full Configuration — +// route is auto-detected after the main script runs. +const EPF_OR_CONFIG_SKILLS = new Set(['template-add', 'help-add']); + // CFE skills — two-stage load: base config → extension const CFE_SKILLS = new Set([ 'cfe-init', 'cfe-borrow', 'cfe-patch-method', @@ -362,13 +366,13 @@ async function verifyCase(skillName, caseName, skillConfig, caseData, opts) { // Determine config dir const setupType = skillConfig.setup || 'empty-config'; const isStandalone = STANDALONE_SKILLS.has(skillName); - const epfExt = EPF_SKILLS.get(skillName); - const isEpf = !!epfExt; + let epfExt = EPF_SKILLS.get(skillName); + let isEpf = !!epfExt; const isCfInit = CONFIG_INIT_SKILLS.has(skillName); // For 'empty-config': workDir is the config (setup creates it) // For cf-init: workDir becomes the config after the script runs // For 'none' + non-special: no config (standalone/EPF) - const configDir = (setupType === 'empty-config' || isCfInit) ? workDir : null; + let configDir = (setupType === 'empty-config' || isCfInit) ? workDir : null; try { // ── Step 0: Case-level fixture copy (runner.mjs compatibility) ── @@ -569,10 +573,31 @@ async function verifyCase(skillName, caseName, skillConfig, caseData, opts) { return result; } + // Auto-detect: skills like template-add/help-add can target either an + // EPF/ERF source or a full configuration. If Configuration.xml is absent + // but a *.xml source for the named object is, route via epf-build. + if (!isEpf && EPF_OR_CONFIG_SKILLS.has(skillName)) { + const hasConfig = existsSync(join(workDir, 'Configuration.xml')); + if (hasConfig) { + configDir = workDir; + } else { + const epfName = caseData.params?.objectName || caseData.params?.name; + if (epfName) { + const xmlPath = join(workDir, `${epfName}.xml`); + if (existsSync(xmlPath)) { + const xml = readFileSync(xmlPath, 'utf8'); + if (/]/.test(xml)) epfExt = '.epf'; + else if (/]/.test(xml)) epfExt = '.erf'; + isEpf = !!epfExt; + } + } + } + } + if (isEpf) { - const name = caseData.params?.name; + const name = caseData.params?.name || caseData.params?.objectName; if (!name) { - result.errors.push(`EPF/ERF verify requires params.name`); + result.errors.push(`EPF/ERF verify requires params.name or params.objectName`); return result; } const sourceFile = join(workDir, `${name}.xml`);