import { describe, expect, it, vi } from 'vitest'; import { reportContext } from './context-report-fixture'; import { makeSheet } from '../../src/importers/sheet-factory'; import { loadCanonicalProjectWorkspace } from '../../src/features/project-import/load-canonical-project-workspace'; import { LocalAssessorRepository } from '../../src/persistence/local-assessor-repository'; import { reportReadPortFrom } from '../../src/reporting/report-read-port'; import { createReportRun } from '../../src/reporting/report-run'; // Only the workspace loader is synthetic, so the run reaches the projection; every read of stored // data goes to the real repository through the engine's read-only port. vi.mock('../../src/features/project-import/load-canonical-project-workspace', () => ({ loadCanonicalProjectWorkspace: vi.fn() })); // Permanent on/off invariance of the Report Engine (AGENTS.md, "Core Engine and engines"): the Core // works unchanged with the engine switched off, and switching it on - running a report - leaves // every stored ASSESSOR value and the repository revision exactly as they were. The Context Engine // carries the same check in tests/assessment-context/context-boundary.test.ts. describe('Report Engine on/off invariance', () => { it('leaves every stored ASSESSOR value and the repository revision unchanged', async () => { const sheet = makeSheet('Dummy', [['Title', 'Source: Scan'], ['Synthetic check', 'PingCastle']], '', 'dummy.csv', { isProjectSheet: true }); vi.mocked(loadCanonicalProjectWorkspace).mockResolvedValue({ models: [], assessmentIds: ['dummy-assessment'], dataset: { fileName: 'Dummy', sheets: [sheet], scanTool: 'PingCastle' } as never }); const repository = new LocalAssessorRepository(); const timestamp = '2026-10-01T08:00:00.000Z'; await repository.saveProject({ id: 'dummy-project', name: 'Dummy Customer', createdAt: timestamp, updatedAt: timestamp, attributes: {} }); await repository.saveAssessment({ id: 'dummy-assessment', projectId: 'dummy-project', name: 'Dummy', createdAt: timestamp, updatedAt: timestamp }); const off = { revision: repository.revision, data: JSON.stringify(await repository.exportProject('dummy-project')) }; const run = await createReportRun(reportReadPortFrom(repository, async () => repository.revision), { projectId: 'dummy-project', assessmentIds: ['dummy-assessment'], generatedAt: timestamp }, { readContext: async () => reportContext(repository.revision) }); // The engine really ran: both report files were rendered from the stored state. expect(run.files.management.length).toBeGreaterThan(0); expect(run.files.technical.length).toBeGreaterThan(0); expect(run.revision).toBe(off.revision); expect(repository.revision).toBe(off.revision); expect(JSON.stringify(await repository.exportProject('dummy-project'))).toBe(off.data); }); });