Spaces:
Running
Running
| import { describe, expect, it } from "vitest"; | |
| import { defaultProfile, rateSource } from "./learning"; | |
| import { defaultState, defaultTaste } from "./state"; | |
| import { buildTraces } from "./traces"; | |
| import type { FeedItem } from "./types"; | |
| const item = (over: Partial<FeedItem>): FeedItem => ({ | |
| uid: "u1", | |
| id: "claude_done", | |
| source: "Claude", | |
| say: "The goblin rests.", | |
| tier: "playful", | |
| tags: ["useful", "warm"], | |
| decision: "notify", | |
| time: "12:00", | |
| rating: null, | |
| ...over, | |
| }); | |
| describe("buildTraces", () => { | |
| const fs = defaultState(); | |
| const taste = defaultTaste(); | |
| const now = new Date("2026-06-06T12:00:00Z"); | |
| it("snapshots event, fairy dials, taste, and per-source bias", () => { | |
| let profile = defaultProfile(); | |
| profile = rateSource(profile, "Discord", "annoying"); // seed -8 β -20 | |
| const [t] = buildTraces([item({ source: "Discord", id: "discord_noise" })], fs, taste, profile, now); | |
| expect(t.v).toBe(1); | |
| expect(t.ts).toBe("2026-06-06T12:00:00.000Z"); | |
| expect(t.event).toMatchObject({ id: "discord_noise", source: "Discord", decision: "notify" }); | |
| expect(t.sourceBias).toBe(-20); | |
| expect(t.fairy.mischief).toBe(fs.mischief); | |
| expect(t.taste).toEqual(taste); | |
| }); | |
| it("carries channel and outcome when present, null when absent", () => { | |
| const outcome = { type: "dismissed" as const, rating: null, latencyMs: 420, visible: true }; | |
| const [a, b] = buildTraces( | |
| [item({ channel: "toast", outcome }), item({ uid: "u2" })], | |
| fs, | |
| taste, | |
| defaultProfile(), | |
| now, | |
| ); | |
| expect(a.event.channel).toBe("toast"); | |
| expect(a.outcome).toEqual(outcome); | |
| expect(b.event.channel).toBeNull(); | |
| expect(b.outcome).toBeNull(); | |
| }); | |
| it("includes silent decisions too β ignore/scroll distributions matter for the notify head", () => { | |
| const [t] = buildTraces( | |
| [item({ decision: "ignore", channel: "feed" })], | |
| fs, | |
| taste, | |
| defaultProfile(), | |
| now, | |
| ); | |
| expect(t.event.decision).toBe("ignore"); | |
| expect(t.outcome).toBeNull(); | |
| }); | |
| }); | |