diff --git a/.code-health-baseline.json b/.code-health-baseline.json index 42767133617..44ef7792d1d 100644 --- a/.code-health-baseline.json +++ b/.code-health-baseline.json @@ -1,7 +1,5 @@ { "version": 1, - "generated": "2026-08-24T09:15:32.266Z", - "totalViolations": 184, "violations": { "packages/@n8n/ai-workflow-builder.ee/package.json": [ { diff --git a/packages/testing/janitor/src/core/baseline.test.ts b/packages/testing/janitor/src/core/baseline.test.ts index cf4edb4f2c5..28d35ebe762 100644 --- a/packages/testing/janitor/src/core/baseline.test.ts +++ b/packages/testing/janitor/src/core/baseline.test.ts @@ -90,8 +90,6 @@ describe('baseline', () => { it('round-trips baseline to disk', () => { const baseline: BaselineFile = { version: 1, - generated: '2024-01-01T00:00:00Z', - totalViolations: 2, violations: { 'pages/TestPage.ts': [ { rule: 'dead-code', line: 10, message: 'Unused method', hash: 'abc123' }, @@ -104,7 +102,6 @@ describe('baseline', () => { expect(loaded).not.toBeNull(); expect(loaded!.version).toBe(1); - expect(loaded!.totalViolations).toBe(2); expect(loaded!.violations['pages/TestPage.ts']).toHaveLength(1); }); @@ -117,8 +114,6 @@ describe('baseline', () => { describe('filterNewViolations', () => { const baseline: BaselineFile = { version: 1, - generated: '2024-01-01T00:00:00Z', - totalViolations: 1, violations: { 'pages/TestPage.ts': [ { diff --git a/packages/testing/janitor/src/core/baseline.ts b/packages/testing/janitor/src/core/baseline.ts index ee8ed3a3945..899201523db 100644 --- a/packages/testing/janitor/src/core/baseline.ts +++ b/packages/testing/janitor/src/core/baseline.ts @@ -53,5 +53,9 @@ export function filterReportByBaseline( export function formatBaselineInfo(baseline: BaselineFile): string { const fileCount = Object.keys(baseline.violations).length; - return `Baseline loaded (${baseline.totalViolations} known violations from ${baseline.generated})\n Files with violations: ${fileCount}`; + const totalViolations = Object.values(baseline.violations).reduce( + (sum, entries) => sum + entries.length, + 0, + ); + return `Baseline loaded (${totalViolations} known violations)\n Files with violations: ${fileCount}`; } diff --git a/packages/testing/janitor/src/core/tcr-executor.test.ts b/packages/testing/janitor/src/core/tcr-executor.test.ts index e15e9fee4d7..2d31891300b 100644 --- a/packages/testing/janitor/src/core/tcr-executor.test.ts +++ b/packages/testing/janitor/src/core/tcr-executor.test.ts @@ -349,8 +349,6 @@ describe('TcrExecutor', () => { // Create and commit a baseline file first const baseline: BaselineFile = { version: 1, - generated: new Date().toISOString(), - totalViolations: 0, violations: {}, }; saveBaseline(baseline, tempDir); @@ -376,8 +374,6 @@ describe('TcrExecutor', () => { // Create and commit a baseline file const baseline: BaselineFile = { version: 1, - generated: new Date().toISOString(), - totalViolations: 0, violations: {}, }; saveBaseline(baseline, tempDir); @@ -407,8 +403,6 @@ describe('TcrExecutor', () => { // Create baseline with this violation const baseline: BaselineFile = { version: 1, - generated: new Date().toISOString(), - totalViolations: 1, violations: { 'pages/PageA.ts': [ { diff --git a/packages/testing/rules-engine/src/baseline.test.ts b/packages/testing/rules-engine/src/baseline.test.ts index f9ed83810df..a60148cf8fa 100644 --- a/packages/testing/rules-engine/src/baseline.test.ts +++ b/packages/testing/rules-engine/src/baseline.test.ts @@ -78,7 +78,25 @@ describe('baseline', () => { const loaded = loadBaseline(filePath); expect(loaded).not.toBeNull(); - expect(loaded!.totalViolations).toBe(1); + expect(loaded!.version).toBe(1); + expect(loaded!.violations['src/a.ts']).toHaveLength(1); + expect(loaded!.violations['src/a.ts'][0].hash).toBe(baseline.violations['src/a.ts'][0].hash); + }); + + // These sat at the top of the file, so two branches that both refreshed the baseline + // conflicted there on every merge even when their entries merged cleanly. + it('does not persist the derived timestamp and total', () => { + const report = makeReport([ + { file: '/root/src/a.ts', rule: 'test-rule', message: 'bad thing' }, + ]); + const baseline = generateBaseline(report, '/root'); + const filePath = path.join(tmpDir, 'baseline.json'); + + saveBaseline(baseline, filePath); + + const persisted = fs.readFileSync(filePath, 'utf-8'); + expect(persisted).not.toContain('"generated"'); + expect(persisted).not.toContain('"totalViolations"'); }); it('returns null for missing baseline', () => { diff --git a/packages/testing/rules-engine/src/baseline.ts b/packages/testing/rules-engine/src/baseline.ts index 98fb406f8eb..3a81e771c2c 100644 --- a/packages/testing/rules-engine/src/baseline.ts +++ b/packages/testing/rules-engine/src/baseline.ts @@ -15,9 +15,9 @@ export interface BaselineEntry { export interface BaselineFile { version: number; - generated: string; - totalViolations: number; violations: Record; + /** Size of the merged set, for the CLI summary. Not persisted — see `saveBaseline`. */ + totalViolations?: number; } function hashViolation(violation: Violation, rootDir: string): string { @@ -87,16 +87,17 @@ export function generateBaseline( } } - return { - version: BASELINE_VERSION, - generated: new Date().toISOString(), - totalViolations: seen.size, - violations, - }; + return { version: BASELINE_VERSION, totalViolations: seen.size, violations }; } +/** + * Persist only the fields that are read back. A write timestamp and a running total are + * derived data, but they sit at the top of the file, so two branches that both refreshed + * the baseline conflict there on every merge even when their entries merge cleanly. + */ export function saveBaseline(baseline: BaselineFile, filePath: string): void { - fs.writeFileSync(filePath, JSON.stringify(baseline, null, '\t') + '\n'); + const { version, violations } = baseline; + fs.writeFileSync(filePath, JSON.stringify({ version, violations }, null, '\t') + '\n'); } function isInBaseline(violation: Violation, baseline: BaselineFile, rootDir: string): boolean {