/** * * `peaks code context-audit` (Slice A, same day) already reports WHAT fills * the window, but only when someone remembers to run it. The Step 0.8 * PreToolUse gate (`peaks code gate-step-08`) runs before every Bash call, so * it is the natural place to surface the single largest consumer — provided * that costs nothing measurable. * * Cost contract (the whole point of this module): * - The ratio probe is the cheap, adapter-driven `readContextPercent` * (env-var → statusline file read; the transcript fallback is a * bounded backwards scan, never a whole-file read). * - The expensive part — the transcript scan inside `auditContext` — runs * at most ONCE per TTL window. Its result is cached under * `.peaks/_runtime//context-audit-hint.json`; a fresh entry * short-circuits the scan entirely. * - Every failure is fail-soft: a missing/corrupt cache, an unavailable * transcript, an adapter that cannot locate one — all yield `null` * (emit nothing). The gate never blocks and never gains more than ONE * line. * * The cache deliberately records FAILED audits too (with `available:false`), * so a broken transcript cannot turn every Bash call back into a scan. */ import { type ContextAuditInput, type ContextAuditResult } from './context-audit.js'; /** Only surface a hint once the window is this full. */ export declare const CONTEXT_HINT_RATIO_THRESHOLD = 0.7; /** Minimum cache TTL — a fresh entry must skip the transcript scan. */ export declare const CONTEXT_HINT_CACHE_TTL_MS: number; /** Per-session cache file name (under `.peaks/_runtime//`). */ export declare const CONTEXT_HINT_CACHE_FILE_NAME = "context-audit-hint.json"; /** Cached top-consumer snapshot — one audit result, no transcript content. */ export interface ContextHintCacheEntry { /** Epoch ms when the audit ran (TTL anchor). */ readonly cachedAt: number; /** False when the audit could not read the transcript. */ readonly available: boolean; /** Ratio observed when the audit ran (informational). */ readonly ratio: number; readonly tool: string | null; readonly key: string | null; readonly bytes: number; readonly pctOfTotal: number; readonly count: number; } export interface ContextAuditHintInput { readonly projectRoot: string; readonly sessionId: string; readonly outerSessionId?: string | null | undefined; readonly env?: NodeJS.ProcessEnv | undefined; /** Clock override (test seam). */ readonly nowMs?: number | undefined; /** Cache path override (test seam; default is per-session under `_runtime`). */ readonly cachePath?: string | undefined; /** Ratio probe override (test seam). Returns null when unknown. */ readonly probeRatio?: (() => number | null) | undefined; /** Audit runner override (test seam; lets a test count scans). */ readonly runAudit?: ((input: ContextAuditInput) => ContextAuditResult) | undefined; } /** * `/.peaks/_runtime//context/context-audit-hint.json` * (gitignored). The `context/` bucket mirrors the existing `/txt/` * convention so session-id artifacts stay under `.peaks/_runtime//`. */ export declare function contextHintCachePath(projectRoot: string, sessionId: string): string; /** * The single line the gate may append. Names ONE consumer — the largest by * tool-result bytes — plus the share and call count that justify the number. */ export declare function formatContextHintLine(entry: ContextHintCacheEntry): string; /** * Build the ONE optional hint line for the Step 0.8 gate. * * Returns `null` when: the ratio is unknown or below 0.70, the cache (fresh) * says the audit was unavailable, the fresh audit found no groups, or * anything throws. Never throws, never blocks. */ export declare function buildContextAuditHint(input: ContextAuditHintInput): string | null;