puck / frontend /src /engine /traces.ts
vu1n's picture
Puck β€” desktop fairy familiar (HF Build Small)
3c124f3
Raw
History Blame Contribute Delete
1.57 kB
// 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,
}));
}