/** * src/decision-engine.ts — Client-side decision tree (PRD-MCP-SKILL §5.3). * * Decides whether to surface a suggestion to the user, *before* hitting brain. * This is the layer that protects users from Clippy-style spam: * * 1. Frequency limit — `userPrefs.maxPerSession` / `maxPerDay` * 2. Quiet hours — `userPrefs.quietHours` * 3. Disabled category — `userPrefs.disabledCategories[A..H]` * 4. Duplicate suggestion — same trigger key inside dedupe window * 5. Brain rule fetch — only after the above 4 pass * * Phase 0 implements 1–4 as real logic (these are 100% client invariants and * don't depend on brain). Step 5 calls BrainClient.fetchRule which currently * returns mock data — fine, the wiring is already correct. * * TODO Week 5: * - Wire real per-day counter into session-cache.db (Phase 0 only counts per * session — restart of MCP server resets the per-day counter). * - Honor `forceShow` override for high-severity expiry alerts (PRD §5.4). * - Plug A/B-test bucket id into context hash so brain can split-test rules. * - Emit OpenTelemetry span for every decision — saves debug time when * users complain "SkillFM never suggests anything". */ import { type TriggerType, type UserPreferences } from './_vendored-contracts/beacon-mcp-tools-v1.js'; import type { BrainClient } from './brain-client.js'; import type { SessionCacheHandle } from './cache.js'; export interface SuggestionDecision { /** True if the agent should surface this to the user. */ shouldSuggest: boolean; /** Human-readable reason if shouldSuggest=false. */ reason?: string; /** Domain code if shouldSuggest=false (matches SKILLFM_ERROR_CODES). */ reasonCode?: string; /** Brain-issued rule id (only present when shouldSuggest=true). */ ruleId?: string; /** Opaque rule payload for the agent to render. */ rulePayload?: Record; } export interface EvaluateOpts { triggerType: TriggerType; triggerContext: Record; userPrefs: UserPreferences; sessionCache: SessionCacheHandle; brain: BrainClient; /** ISO weekday + HH:mm for quiet-hours check; defaults to `new Date()`. */ now?: Date; } /** * Phase 0 decision tree — runs locally, calls brain only on the happy path. * Returns a `SuggestionDecision` envelope every time (never throws). */ export declare function evaluateSuggestion(opts: EvaluateOpts): Promise; //# sourceMappingURL=decision-engine.d.ts.map