From 6327864f9130db7e38cac3e12c94052566607733 Mon Sep 17 00:00:00 2001 From: Christian Scherkl Date: Sun, 24 May 2026 17:14:42 +0200 Subject: [PATCH] test: guard metrics runtime package files --- bin/utils/validate-publish.js | 21 +++++++++++++++++++++ tests/cli/validate-publish.test.js | 8 ++++++++ 2 files changed, 29 insertions(+) diff --git a/bin/utils/validate-publish.js b/bin/utils/validate-publish.js index 6b03783a10..cc0f219606 100644 --- a/bin/utils/validate-publish.js +++ b/bin/utils/validate-publish.js @@ -21,6 +21,11 @@ const { execSync, execFileSync } = require('child_process'); const PROJECT_ROOT = path.join(__dirname, '..', '..'); const MIN_FILE_COUNT = 50; const PRO_PATH_PATTERN = /^pro(?:\/|$)/; +const REQUIRED_PUBLIC_FILES = [ + '.aiox-core/quality/metrics-collector.js', + '.aiox-core/quality/seed-metrics.js', + '.aiox-core/quality/schemas/quality-metrics.schema.json', +]; const DEFAULT_PACK_TIMEOUT_MS = 300000; const parsedPackTimeoutMs = Number.parseInt( process.env.AIOX_VALIDATE_PUBLISH_PACK_TIMEOUT_MS || '', @@ -105,6 +110,22 @@ try { } else { console.log('PASS: Public package excludes pro/ content'); } + + const missingRequiredFiles = REQUIRED_PUBLIC_FILES.filter( + (filePath) => !packedFiles.includes(filePath), + ); + if (missingRequiredFiles.length > 0) { + console.error( + `FAIL: Public package is missing ${missingRequiredFiles.length} required runtime file(s).`, + ); + console.error(' Metrics CLI commands require these files at boot.'); + for (const filePath of missingRequiredFiles) { + console.error(` - ${filePath}`); + } + passed = false; + } else { + console.log('PASS: Public package includes metrics runtime files'); + } } catch (err) { console.error(`FAIL: npm pack --dry-run failed: ${err.message}`); passed = false; diff --git a/tests/cli/validate-publish.test.js b/tests/cli/validate-publish.test.js index 683a319450..c74fb8685f 100644 --- a/tests/cli/validate-publish.test.js +++ b/tests/cli/validate-publish.test.js @@ -30,6 +30,13 @@ describe('Publish Safety Gate (Story INS-4.10 / PRO-13.5)', () => { expect(scriptSource).toContain('Public package excludes pro/ content'); }); + test('script requires metrics runtime files in npm pack output', () => { + expect(scriptSource).toContain('REQUIRED_PUBLIC_FILES'); + expect(scriptSource).toContain('.aiox-core/quality/metrics-collector.js'); + expect(scriptSource).toContain('.aiox-core/quality/seed-metrics.js'); + expect(scriptSource).toContain('Public package includes metrics runtime files'); + }); + test('legacy npm notice parser strips size prefixes before path checks', () => { expect(scriptSource).toContain('npm notice\\s+[\\d.]+[kMG]?B?\\s+(.+)'); }); @@ -116,6 +123,7 @@ describe('Publish Safety Gate (Story INS-4.10 / PRO-13.5)', () => { }); expect(result).toContain('PUBLISH SAFETY GATE: PASS'); expect(result).toContain('PASS: Public package excludes pro/ content'); + expect(result).toContain('PASS: Public package includes metrics runtime files'); }); test('script produces human-readable output with pass/fail indicators', () => {