import { describe, expect, it } from 'vitest' import { overall, validateReport } from '@extant2000/evidence-record' import { formatRanking, rank, toReport, type CapabilityStanding } from '../src/index.js' // An example portfolio of four services, scored 0-100. const suite: CapabilityStanding[] = [ { name: 'docs', score: 90, effort: 'small', bindingConstraint: 'none material', where: 'quarterly scorecard' }, { name: 'gateway', score: 85, effort: 'small', bindingConstraint: 'retry fix written but unmerged', nextAction: 'merge the retry fix', where: 'quarterly scorecard' }, { name: 'reports', score: 60, effort: 'large', bindingConstraint: 'scheduled exports promised, nothing runs them', nextAction: 'build the scheduler', where: 'quarterly scorecard' }, { name: 'billing', score: 80, effort: 'trivial', bindingConstraint: 'debug logging left on', nextAction: 'turn off debug logging', where: 'quarterly scorecard' }, ] describe('unassessed is not the bottom of the list', () => { it('ranks unassessed capabilities separately, never interleaved', () => { // "Nobody looked at this" and "we looked and it is weak" are opposite // situations. One ordered list cannot hold both. const r = rank([...suite, { name: 'newservice', score: null }]) expect(r.ranked.map(c => c.name)).not.toContain('newservice') expect(r.unassessed.map(c => c.name)).toEqual(['newservice']) }) it('reports an unassessed capability as not-assessed and says why it is unranked', () => { const r = toReport([...suite, { name: 'newservice', score: null }]) const f = r.findings.find(x => x.id === 'newservice')! expect(f.determination).toBe('not-assessed') expect(f.detail).toContain('backwards, as advice') // The roll-up is `fail`, not `not-assessed`: a real shortfall takes // precedence over an unknown, which is the standard's defined order. expect(overall(r)).toBe('fail') }) it('rolls up to not-assessed when the ONLY entries are unassessed', () => { expect(overall(toReport([{ name: 'newservice', score: null }]))).toBe('not-assessed') }) it('does not let a null score sort as zero', () => { const r = rank([{ name: 'unknown', score: null }, { name: 'weak', score: 10, effort: 'small' }]) expect(r.ranked[0]!.name).toBe('weak') expect(r.ranked).toHaveLength(1) }) }) describe('leverage, not score', () => { it('prefers a cheap fix on a mid capability over an expensive one on a weak capability', () => { // billing: (100-80)/1 = 20. reports: (100-60)/8 = 5. // Ordering by score alone would recommend the rewrite. const r = rank(suite) expect(r.ranked[0]!.name).toBe('billing') expect(r.ranked[0]!.leverage).toBeGreaterThan(r.ranked.find(c => c.name === 'reports')!.leverage!) }) it('scales by strategic weight', () => { const r = rank([ { name: 'minor', score: 50, effort: 'small', weight: 1 }, { name: 'major', score: 50, effort: 'small', weight: 3 }, ]) expect(r.ranked[0]!.name).toBe('major') }) it('treats unknown effort as medium, not as free', () => { // An unestimated task is not a cheap one. Defaulting optimistically is // how an unscoped item reaches the top of a plan. const r = rank([ { name: 'unscoped', score: 50 }, { name: 'trivial-known', score: 50, effort: 'trivial' }, ]) expect(r.ranked[0]!.name).toBe('trivial-known') }) it('gives a near-finished capability little leverage however cheap the work', () => { const r = rank([ { name: 'nearly-done', score: 98, effort: 'trivial' }, { name: 'midway', score: 60, effort: 'medium' }, ]) expect(r.ranked[0]!.name).toBe('midway') }) }) describe('a rank without a constraint is not advice', () => { it('names the binding constraint and next action on each entry', () => { const text = formatRanking(suite) expect(text).toContain('debug logging left on') expect(text).toContain('turn off debug logging') expect(text).toContain('best next move: billing') }) it('says so when no constraint was recorded', () => { const f = toReport([{ name: 'x', score: 50 }]).findings[0]! expect(f.detail).toContain('a position, not advice') }) it('only a genuinely finished capability passes', () => { expect(toReport([{ name: 'done', score: 95, effort: 'trivial' }]).findings[0]!.determination).toBe('pass') expect(toReport([{ name: 'nearly', score: 89, effort: 'trivial' }]).findings[0]!.determination).toBe('fail') }) }) describe('conformance with the evidence-record standard', () => { it('an empty portfolio is not-assessed, never clean', () => { expect(overall(toReport([]))).toBe('not-assessed') }) it('every conclusion carries a citation', () => { expect(validateReport(toReport(suite))).toEqual([]) }) it('carries the score into the citation as a measurement', () => { const text = formatRanking(suite, { evidence: 'inline' }) expect(text).toContain('billing readiness = 80') }) }) describe('the ranking prints in rank order', () => { it('shows #1 first, even when a lower-ranked entry is more severe', () => { // The shared renderer sorts worst-first, which is right for findings and // wrong for a ranking. A ranking whose display order contradicts its own // numbering is worse than no numbering. const text = formatRanking(suite) const table = text.split('\n\n')[0]! expect(table.indexOf('#1')).toBeLessThan(table.indexOf('#2')) expect(table.indexOf('#2')).toBeLessThan(table.indexOf('#3')) expect(table.split('\n')[0]).toContain('billing') }) it('lists unassessed capabilities under the ranked ones, without a number', () => { const table = formatRanking([...suite, { name: 'newservice', score: null }]).split('\n\n')[0]! expect(table).toContain('newservice') expect(table).toContain('no score to rank from') expect(table.indexOf('#1')).toBeLessThan(table.indexOf('newservice')) }) })