Files
DevRunbook-Public/packages/application/src/quality/static-quality-evaluation.test.ts
T
DevRunbook release export cfd2804e27
Managed validation / full (push) Successful in 3m18s
Publish DevRunbook source
2026-09-03 04:09:17 +02:00

317 lines
9.0 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import {
assessLifecycleEvidence,
compareVersionEvaluations,
createQualityFinding,
createQualityMatrix,
evaluateStaticCase,
evaluationFreshness,
QUALITY_DIMENSIONS,
type LifecycleEvidence,
type StaticEvaluationCase,
type StaticEvaluationObservation,
type StaticEvaluationResult,
} from './static-quality-evaluation'
const target = { id: 'playbook', version: '1.0.0', digest: 'a'.repeat(64) }
const fixture = {
id: 'fixture',
version: '2.0.0',
digest: 'b'.repeat(64),
environmentDigest: 'c'.repeat(64),
}
const evaluationCase: StaticEvaluationCase = {
id: 'safe-change.static',
version: '1.0.0',
target,
fixture,
expectedHeadings: ['# Mission'],
requiredText: ['Do not modify protected paths.'],
prohibitedText: ['Authorization: Bearer'],
deterministic: true,
expectedLintStatus: 'ready',
}
const observation: StaticEvaluationObservation = {
target,
fixture,
renderedPrompt: '# Mission\n\nDo not modify protected paths.',
renderedPromptDigest: 'd'.repeat(64),
repeatedRenderDigest: 'd'.repeat(64),
lintStatus: 'ready',
evaluatedAt: '2026-07-27T10:00:00.000Z',
}
function result(
overrides: Partial<StaticEvaluationResult> = {},
): StaticEvaluationResult {
return { ...evaluateStaticCase(evaluationCase, observation), ...overrides }
}
function evidence(
overrides: Partial<LifecycleEvidence> = {},
): LifecycleEvidence {
return {
schemaAndSemanticValidationPassed: true,
blockingLintFindingCount: 0,
humanEditorialReviewCompleted: true,
limitationsDocumented: true,
evaluationResults: [result()],
currentEvaluationContext: { target, fixture },
unresolvedSafetyRegression: false,
realWorldRunCount: 20,
realWorldFailureCount: 1,
unaddressedSevereIncidentCount: 0,
latestRealWorldEvidenceAt: '2026-07-20T10:00:00.000Z',
...overrides,
}
}
const policy = {
requiredEvaluationCaseIds: [evaluationCase.id],
minimumRealWorldRuns: 10,
maximumFailureRate: 0.1,
maximumEvidenceAgeDays: 30,
}
describe('quality findings and dimensions', () => {
it('keeps every dimension visible without inventing an aggregate score', () => {
const matrix = createQualityMatrix([
{
dimension: 'safety',
rating: 'strong',
rationale: 'Protected paths are explicit.',
provenance: [{ kind: 'static-evaluation', source: 'case-1' }],
},
])
expect(Object.keys(matrix)).toEqual(QUALITY_DIMENSIONS)
expect(matrix.safety.rating).toBe('strong')
expect(matrix.reporting.rating).toBe('not-assessed')
expect(matrix).not.toHaveProperty('score')
})
it('creates structured PB/PR/SA/VA findings and rejects unknown families', () => {
const finding = createQualityFinding({
ruleId: 'SA002',
severity: 'error',
path: 'spec.scope.paths[0]',
message: 'Protected path is mutable.',
rationale: 'The scope conflicts with repository policy.',
remediation: 'Exclude the protected path.',
provenance: { kind: 'static-analysis', source: 'prompt-linter' },
})
expect(finding.family).toBe('SA')
expect(() => createQualityFinding({ ...finding, ruleId: 'XX001' })).toThrow(
/PB, PR, SA or VA/,
)
})
})
describe('static evaluation', () => {
it('passes literal expectations tied to exact identities', () => {
const assessed = evaluateStaticCase(evaluationCase, observation)
expect(assessed.status).toBe('passed')
expect(assessed.checks).toHaveLength(7)
expect(assessed.target).toEqual(target)
expect(assessed.fixture).toEqual(fixture)
})
it('treats supplied pattern syntax as literal text, never as a regex', () => {
const assessed = evaluateStaticCase(
{
...evaluationCase,
requiredText: ['(a+)+$'],
prohibitedText: ['.*secret.*'],
},
{ ...observation, renderedPrompt: '# Mission\n(a+)+$' },
)
expect(
assessed.checks.find((check) => check.kind === 'required-text')?.passed,
).toBe(true)
expect(
assessed.checks.find((check) => check.kind === 'prohibited-text')?.passed,
).toBe(true)
})
it('fails changed playbook identity and a mismatched repeated digest', () => {
const assessed = evaluateStaticCase(evaluationCase, {
...observation,
target: { ...target, version: '1.0.1' },
repeatedRenderDigest: 'e'.repeat(64),
})
expect(assessed.status).toBe('failed')
expect(
assessed.checks
.filter((check) => !check.passed)
.map((check) => check.kind),
).toEqual(['identity', 'determinism'])
})
it('detects stale playbook, fixture and environment evidence independently', () => {
expect(
evaluationFreshness(result(), {
target: { ...target, digest: 'x'.repeat(64) },
fixture: {
...fixture,
version: '2.1.0',
environmentDigest: 'y'.repeat(64),
},
}),
).toEqual({
stale: true,
reasons: [
'playbook-digest-changed',
'fixture-version-changed',
'environment-changed',
],
})
})
})
describe('lifecycle evidence policy', () => {
it('allows draft without presenting it as evidence-backed', () => {
expect(
assessLifecycleEvidence(
'draft',
evidence({ evaluationResults: [] }),
policy,
new Date(),
),
).toMatchObject({ eligible: true, requirements: [], findings: [] })
})
it('blocks reviewed when editorial requirements are missing', () => {
const assessed = assessLifecycleEvidence(
'reviewed',
evidence({ humanEditorialReviewCompleted: false }),
policy,
new Date('2026-07-27T10:00:00.000Z'),
)
expect(assessed.eligible).toBe(false)
expect(assessed.findings[0]).toMatchObject({
ruleId: 'PB009',
family: 'PB',
})
})
it('blocks validated when required evidence is stale', () => {
const assessed = assessLifecycleEvidence(
'validated',
evidence({
currentEvaluationContext: {
target: { ...target, version: '1.1.0' },
fixture,
},
}),
policy,
new Date('2026-07-27T10:00:00.000Z'),
)
expect(assessed.eligible).toBe(false)
expect(
assessed.requirements.find((item) => item.id.startsWith('evaluation:')),
).toMatchObject({
satisfied: false,
})
})
it('requires real-world volume, failure rate, incident and recency evidence for battle-tested', () => {
const accepted = assessLifecycleEvidence(
'battle-tested',
evidence(),
policy,
new Date('2026-07-27T10:00:00.000Z'),
)
expect(accepted.eligible).toBe(true)
const rejected = assessLifecycleEvidence(
'battle-tested',
evidence({
realWorldRunCount: 2,
realWorldFailureCount: 1,
unaddressedSevereIncidentCount: 1,
latestRealWorldEvidenceAt: '2025-01-01T00:00:00.000Z',
}),
policy,
new Date('2026-07-27T10:00:00.000Z'),
)
expect(
rejected.requirements
.filter((item) => !item.satisfied)
.map((item) => item.id),
).toEqual([
'real-world-runs',
'failure-rate',
'severe-incidents',
'evidence-recency',
])
})
it('requires a rationale or replacement for deprecated lifecycle', () => {
expect(
assessLifecycleEvidence('deprecated', evidence(), policy, new Date())
.eligible,
).toBe(false)
expect(
assessLifecycleEvidence(
'deprecated',
evidence({ replacementPlaybookId: 'safe-change-v2' }),
policy,
new Date(),
).eligible,
).toBe(true)
})
})
describe('version comparison', () => {
it('compares common exact cases and reports dimension changes separately', () => {
const previous = result({
status: 'failed',
dimensions: createQualityMatrix([
{
dimension: 'verification',
rating: 'weak',
rationale: 'Missing evidence.',
provenance: [],
},
]),
})
const current = result({
target: { ...target, version: '1.1.0', digest: 'f'.repeat(64) },
dimensions: createQualityMatrix([
{
dimension: 'verification',
rating: 'strong',
rationale: 'Evidence is explicit.',
provenance: [
{ kind: 'static-evaluation', source: evaluationCase.id },
],
},
]),
})
expect(compareVersionEvaluations([previous], [current])).toEqual({
newlyPassingCaseIds: [evaluationCase.id],
newlyFailingCaseIds: [],
unchangedCaseIds: [],
dimensionChanges: [
{
caseId: evaluationCase.id,
dimension: 'verification',
previous: 'weak',
current: 'strong',
},
],
})
})
it('does not compare results from a changed fixture', () => {
const changedFixture = result({ fixture: { ...fixture, version: '3.0.0' } })
expect(compareVersionEvaluations([result()], [changedFixture])).toEqual({
newlyPassingCaseIds: [],
newlyFailingCaseIds: [],
unchangedCaseIds: [],
dimensionChanges: [],
})
})
})