feat(p7): FakeInference deterministic provider + golden eval registry
Task 7.2: FakeInference implements the InferencePort with keyword vocabulary mirroring the P6 RuleEngine; deterministic (no clock/random) so AI artifacts are replayable. Golden fixtures (AI_GOLDEN) + inference.spec.ts assert byte-identical replay, abstention, and Scenario-7 (EVENT never exceeds DISCUSSION certainty). Controls: abstain()/deny()/setCost(). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { makeFakeInference, AI_GOLDEN } from '@insignia/iios-testkit';
|
||||
import type { AiJobType } from '@insignia/iios-contracts';
|
||||
|
||||
const run = (jobType: AiJobType, text: string) =>
|
||||
makeFakeInference().infer({ jobType, text, purpose: `ai_${jobType.toLowerCase()}`, scopeId: 'scope1', interactionId: 'int1' });
|
||||
|
||||
describe('FakeInference — deterministic golden provider (P7)', () => {
|
||||
it('is replayable: every golden case yields byte-identical output twice', async () => {
|
||||
for (const c of AI_GOLDEN) {
|
||||
const a = await run(c.jobType, c.text);
|
||||
const b = await run(c.jobType, c.text);
|
||||
expect(JSON.stringify(a)).toEqual(JSON.stringify(b));
|
||||
}
|
||||
});
|
||||
|
||||
it('matches golden expectations (artifact type, claims, abstention)', async () => {
|
||||
for (const c of AI_GOLDEN) {
|
||||
const r = await run(c.jobType, c.text);
|
||||
expect(r.artifactType).toBe(c.expect.artifactType);
|
||||
expect(r.claims.map((x) => x.claimType).sort()).toEqual([...c.expect.claimTypes].sort());
|
||||
expect(!!r.abstentionReason).toBe(c.expect.abstained);
|
||||
}
|
||||
});
|
||||
|
||||
it('never asserts an event beyond DISCUSSION certainty (Scenario 7)', async () => {
|
||||
for (const c of AI_GOLDEN.filter((g) => g.expect.maxCertainty)) {
|
||||
const r = await run(c.jobType, c.text);
|
||||
const event = r.claims.find((x) => x.claimType === 'EVENT');
|
||||
expect(event?.claimJson.certainty).toBe('DISCUSSION');
|
||||
}
|
||||
});
|
||||
|
||||
it('abstain control forces no claims + a reason', async () => {
|
||||
const r = await makeFakeInference().abstain().infer({ jobType: 'EXTRACT', text: 'party at 9 pm', purpose: 'x', scopeId: 's' });
|
||||
expect(r.claims).toHaveLength(0);
|
||||
expect(r.abstentionReason).toBeTruthy();
|
||||
});
|
||||
|
||||
it('emits a positive integer cost (budget governor input)', async () => {
|
||||
const r = await run('SUMMARIZE', 'hello world this is a message');
|
||||
expect(Number.isInteger(r.modelRun.costUnits)).toBe(true);
|
||||
expect(r.modelRun.costUnits).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user