/** * Advisor co-pilot tip — ADR-316. A periodic, consent-gated, budget-capped * suggestion generated by ruflo's existing Fable Advisor Harness * (services/fable-harness.ts, ADR-172), surfaced in the local insight * ticker (insights.ts) alongside the CVE/uncommitted/power-saver signals. * * This is the ONE insight source that spends real money and makes a real * network call — every other source in insights.ts is synchronous, local, * $0 by construction. Three hard gates keep that safe: * 1. consent: 'advisor-tips' domain (types.ts/consent.ts), never bundled * with anything else, off by default. * 2. cooldown: at most once per ADVISOR_REFRESH_TTL_MS regardless of how * many sessions run in that window — a file-based TTL checked BEFORE * spawning, not a per-call budget hope. * 3. budget: FableHarness's own --max-budget-usd hard cap, passed through * to the underlying `claude -p` call. * * The snapshot sent to the model is built ONLY from the same structural * signals insights.ts already uses (funnel/local-signals.ts) — never raw * prompts, commands, or file contents. Matches ADR-309's "no raw content, * ever" bar even though ADR-309 is about telemetry and this is a different, * separately-consented data flow (an opt-in advisor query, not analytics). * * Cheapness/latency discipline for the CALLER (never this module itself): * refreshAdvisorTipIfStale performs a real network-bound `claude -p` spawn * when stale — callers MUST run it from a properly-awaited, DETACHED * background process (mirroring the funnel-cache fix's * spawnDetachedFunnelRefresh pattern), never inline in a statusline render. */ import { FableHarness, type CoPilotSnapshot } from '../services/fable-harness.js'; /** At most one real spend per real day, regardless of session count. */ export declare const ADVISOR_REFRESH_TTL_MS: number; /** Conservative default — one adviseCoPilotTip call is a single, unbatched * item, so the ~$0.34 clean-cwd anchor (not the $0.02 batched anchor) * applies. Override via RUFLO_ADVISOR_MAX_BUDGET_USD for advanced users. */ export declare const ADVISOR_DEFAULT_BUDGET_USD = 0.4; export interface CachedAdvisorTip { headline: string; detail: string; } /** Synchronous, $0, no network — safe to call from the insight ticker's hot path. */ export declare function readAdvisorTip(now?: Date): CachedAdvisorTip | null; export interface AdvisorRefreshResult { refreshed: boolean; reason?: 'not-consented' | 'fresh' | 'no-tip' | 'error'; } /** * Refresh the cached advisor tip if consent is granted AND the cache is * stale. Spends real money via FableHarness exactly once per call site, * gated by the TTL check above — callers get to decide cadence (e.g. * "call this on every session-restore"; the TTL makes repeated calls cheap * no-ops within the same window). */ export declare function refreshAdvisorTipIfStale(snapshot: CoPilotSnapshot, opts?: { now?: Date; harness?: FableHarness; }): Promise; //# sourceMappingURL=advisor-tip.d.ts.map