Fas 2 steg 3: Household Trust Score (admin + i18n status i appen)

This commit is contained in:
Sven (AAMOS AI)
2026-08-06 23:45:28 +07:00
parent bcf932d2ff
commit 4385fe5125
21 changed files with 396 additions and 23 deletions
+57 -1
View File
@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest";
import { applyDecay, computeTrust, worstTrustState } from "../src/trust.js";
import { applyDecay, computeTrust, householdTrustScore, worstTrustState } from "../src/trust.js";
const PINNED = new Date("2026-08-06T12:00:00.000Z");
@@ -96,6 +96,62 @@ describe("computeTrust", () => {
});
});
describe("householdTrustScore", () => {
it("returns 100 / up_to_date for empty inventory", () => {
const result = householdTrustScore({ items: [], correctionCount30d: 0, transactionCount30d: 0 }, PINNED);
expect(result.score).toBe(100);
expect(result.status).toBe("up_to_date");
});
it("scores high when all items are verified and recent", () => {
const result = householdTrustScore(
{
items: [
{ confidence: 1, verifiedByUser: true, lastVerifiedAt: PINNED, quantity: 2, updatedAt: PINNED },
{ confidence: 1, verifiedByUser: true, lastVerifiedAt: PINNED, quantity: 3, updatedAt: PINNED },
],
correctionCount30d: 0,
transactionCount30d: 0,
},
PINNED,
);
expect(result.score).toBeGreaterThanOrEqual(80);
expect(result.status).toBe("up_to_date");
});
it("drops to uncertain when items are old and unverified", () => {
const old = new Date(PINNED.getTime() - 60 * 86_400_000);
const result = householdTrustScore(
{
items: [
{ confidence: 0.3, verifiedByUser: false, lastVerifiedAt: null, quantity: 0.1, updatedAt: old },
],
correctionCount30d: 5,
transactionCount30d: 10,
},
PINNED,
);
expect(result.status).toBe("uncertain");
expect(result.score).toBeLessThan(50);
});
it("flags needs_check for partly verified household", () => {
const weekAgo = new Date(PINNED.getTime() - 7 * 86_400_000);
const result = householdTrustScore(
{
items: [
{ confidence: 0.8, verifiedByUser: true, lastVerifiedAt: weekAgo, quantity: 1, updatedAt: weekAgo },
{ confidence: 0.5, verifiedByUser: false, lastVerifiedAt: null, quantity: 1, updatedAt: weekAgo },
],
correctionCount30d: 1,
transactionCount30d: 5,
},
PINNED,
);
expect(result.status).toBe("needs_check");
});
});
describe("worstTrustState", () => {
it("returns stale if present", () => {
expect(worstTrustState(["trusted", "stale", "decaying"])).toBe("stale");