import { describe, expect, it } from 'vitest'; import { DEFAULT_RISK_THRESHOLD, evaluateRiskFloor, type ReviewSurface } from './risk-floor.js'; describe('evaluateRiskFloor', () => { it('returns a no-review "none" verdict for an empty diff', () => { const v = evaluateRiskFloor({ filesChanged: [] }); expect(v).toEqual({ needs_review: false, score: 0, surface: 'none', reason: 'no files changed', }); }); it('ignores empty/non-string entries', () => { const v = evaluateRiskFloor({ filesChanged: ['', ' ' as unknown as string].filter(Boolean) }); // only the whitespace string survives the Boolean filter; it classifies to none expect(v.surface).toBe('none'); expect(v.needs_review).toBe(false); }); it.each<[string, string, ReviewSurface, boolean]>([ ['auth', 'apps/api/src/auth/session.guard.ts', 'auth', true], ['data', 'packages/db/migrations/0007_add_users.sql', 'data', true], ['infra', '.woodpecker/deploy.yml', 'infra', true], ['build', 'packages/types/tsconfig.json', 'build', true], ['ui', 'apps/web/src/components/Button.tsx', 'ui', false], ['test', 'packages/macp/src/risk-floor.spec.ts', 'test', false], ['docs', 'docs/plans/agent-reflection-loop-PRD.md', 'docs', false], ['none', 'README', 'none', false], ])( 'classifies a single %s file → surface=%s needs_review=%s', (_label, file, surface, needsReview) => { const v = evaluateRiskFloor({ filesChanged: [file] }); expect(v.surface).toBe(surface); expect(v.needs_review).toBe(needsReview); expect(v.reason).toContain( file === 'README' ? 'no sensitive surface' : surface === 'none' ? '' : surface, ); }, ); it('lets the highest-risk surface dominate a mixed diff', () => { const v = evaluateRiskFloor({ filesChanged: [ 'docs/readme.md', 'apps/web/src/components/Nav.tsx', 'apps/api/src/auth/token.service.ts', ], }); expect(v.surface).toBe('auth'); expect(v.score).toBe(1.0); expect(v.needs_review).toBe(true); expect(v.reason).toContain('token.service.ts'); expect(v.reason).not.toContain('readme.md'); }); it('names every file that ties at the dominant surface', () => { const v = evaluateRiskFloor({ filesChanged: ['src/login.ts', 'src/permission-check.ts'], }); expect(v.surface).toBe('auth'); expect(v.reason).toContain('src/login.ts'); expect(v.reason).toContain('src/permission-check.ts'); }); it('treats docs+test-only diffs as below the floor', () => { const v = evaluateRiskFloor({ filesChanged: ['docs/guide.md', 'packages/x/src/x.test.ts'], }); expect(v.needs_review).toBe(false); expect(v.surface).toBe('test'); // higher weight than docs }); it('honors a custom threshold', () => { const docsOnly = { filesChanged: ['docs/guide.md'] }; expect(evaluateRiskFloor(docsOnly, 0.05).needs_review).toBe(true); expect(evaluateRiskFloor(docsOnly, DEFAULT_RISK_THRESHOLD).needs_review).toBe(false); }); it('is deterministic across call order', () => { const a = evaluateRiskFloor({ filesChanged: ['a.md', 'auth/x.ts', 'b.tsx'] }); const b = evaluateRiskFloor({ filesChanged: ['b.tsx', 'a.md', 'auth/x.ts'] }); expect(a).toEqual(b); }); });