Spaces:
Running
Running
| // Trace records: the day's surfaced decisions + how the user reacted, | |
| // snapshotted with the fairy/taste/bias state that produced them. | |
| // This is the molt's training data β exported at Night Bloom, appended | |
| // to server/data/traces.jsonl by the daemon. | |
| import { sourceBias } from "./learning"; | |
| import type { FairyState, FeedItem, Profile, SurfaceOutcome, Taste } from "./types"; | |
| export interface TraceRecord { | |
| v: 1; | |
| ts: string; | |
| event: Pick<FeedItem, "id" | "source" | "say" | "tier" | "decision"> & { | |
| channel: FeedItem["channel"] | null; | |
| }; | |
| /** the dials that shaped this decision, at export time */ | |
| fairy: Pick<FairyState, "mischief" | "protectiveness" | "chattiness" | "curiosity" | "energy">; | |
| taste: Taste; | |
| sourceBias: number; | |
| outcome: SurfaceOutcome | null; | |
| } | |
| /** Snapshot the day's feed as training traces. Pure β caller decides when/where to ship. */ | |
| export function buildTraces( | |
| feed: FeedItem[], | |
| fs: FairyState, | |
| taste: Taste, | |
| profile: Profile, | |
| now: Date = new Date(), | |
| ): TraceRecord[] { | |
| const ts = now.toISOString(); | |
| const fairy = { | |
| mischief: fs.mischief, | |
| protectiveness: fs.protectiveness, | |
| chattiness: fs.chattiness, | |
| curiosity: fs.curiosity, | |
| energy: fs.energy, | |
| }; | |
| return feed.map((e) => ({ | |
| v: 1 as const, | |
| ts, | |
| event: { | |
| id: e.id, | |
| source: e.source, | |
| say: e.say, | |
| tier: e.tier, | |
| decision: e.decision, | |
| channel: e.channel ?? null, | |
| }, | |
| fairy, | |
| taste, | |
| sourceBias: sourceBias(profile, e.source), | |
| outcome: e.outcome ?? null, | |
| })); | |
| } | |