puck / frontend /src /engine /scoring.ts
vu1n's picture
Puck — desktop fairy familiar (HF Build Small)
3c124f3
Raw
History Blame Contribute Delete
1.42 kB
import type { Decision, EventDef, EventScores, FairyState, PuckMode } from "./types";
import { clamp } from "./util";
/** Personality bends the raw event scores before the decision bands see them. */
export function score(ev: EventDef, fs: FairyState): EventScores {
const s = { ...ev.base };
// protectiveness raises the bar for annoyance; mischief lowers Puck's filter
s.annoyance = clamp(s.annoyance + (fs.protectiveness - 50) * 0.25 - (fs.mischief - 50) * 0.15);
s.interest = clamp(s.interest + (fs.curiosity - 50) * 0.2 + (fs.mischief - 50) * 0.15);
s.relevance = clamp(s.relevance + (fs.protectiveness - 50) * 0.1);
return s;
}
/** Decision bands → rungs of the interruption ladder. */
export function decide(s: EventScores): Decision {
const worth = s.relevance + s.urgency + s.interest - s.annoyance;
if (s.urgency >= 80 && s.relevance >= 80) return "interrupt";
if (s.relevance < 35 && s.annoyance > 60) return "ignore";
if (worth > 180) return "notify";
if (worth > 120) return "glow";
if (worth > 70) return "scroll";
return "ignore";
}
/** Mode overrides applied after scoring + learned bias (mirrors applyBias). */
export function applyMode(decision: Decision, mode: PuckMode): Decision {
if (mode === "silent" && (decision === "notify" || decision === "interrupt")) return "scroll";
if (mode === "goblin" && decision === "glow") return "notify";
return decision;
}