/** * Debug Trace Recorder (O-005) * * Records comprehensive debug traces for browsing operations to enable * failure reproduction and debugging. Traces are persisted to disk and * can be queried, exported, and replayed. * * Key features: * - Persistent storage with automatic retention policy * - Comprehensive trace data (tiers, selectors, network, errors) * - Query by domain, time range, error type * - Export for sharing/replay * - Enable/disable per domain or globally */ import type { DecisionTrace, TierAttempt, SelectorAttempt, TitleAttempt } from '../types/decision-trace.js'; import type { RenderTier, NetworkRequest } from '../types/index.js'; /** * Error information captured in a trace */ export interface TraceError { /** Error type classification */ type: 'timeout' | 'network' | 'selector' | 'validation' | 'bot_challenge' | 'rate_limit' | 'auth' | 'unknown'; /** Error message */ message: string; /** Stack trace if available */ stack?: string; /** Whether recovery was attempted */ recoveryAttempted: boolean; /** Whether recovery succeeded */ recoverySucceeded?: boolean; /** Timestamp when error occurred */ timestamp: number; } /** * Validation result captured in a trace */ export interface TraceValidation { /** Whether content passed validation */ valid: boolean; /** Reasons for validation result */ reasons: string[]; /** Validators that were applied */ validatorsApplied: string[]; /** Content length at validation time */ contentLength: number; } /** * Network activity captured in a trace */ export interface TraceNetwork { /** Total requests made */ requestCount: number; /** API requests discovered */ apiRequests: Array<{ url: string; method: string; status?: number; duration?: number; }>; /** Failed requests */ failedRequests: Array<{ url: string; status?: number; error?: string; }>; /** Total bytes transferred */ bytesTransferred?: number; } /** * Complete debug trace for a browse operation */ export interface DebugTrace { /** Unique trace ID */ id: string; /** Timestamp when trace was created */ timestamp: number; /** Target URL */ url: string; /** Domain extracted from URL */ domain: string; /** Final URL after redirects */ finalUrl: string; /** Total operation duration in ms */ durationMs: number; /** Whether the operation succeeded */ success: boolean; /** Rendering tier decisions */ tiers: { /** All tiers attempted */ attempts: TierAttempt[]; /** Final tier used */ finalTier: RenderTier; /** Whether fallback occurred */ fellBack: boolean; /** Budget constraints applied */ budget?: { maxLatencyMs?: number; maxCostTier?: RenderTier; latencyExceeded: boolean; tiersSkipped: RenderTier[]; }; }; /** Selector extraction decisions */ selectors: { /** All selectors tried */ attempts: SelectorAttempt[]; /** Final selector used */ finalSelector: string; /** Whether fallback to body was used */ fallbackUsed: boolean; }; /** Title extraction decisions */ title: { /** All title sources tried */ attempts: TitleAttempt[]; /** Final title value */ value?: string; /** Source of final title */ source: string; }; /** Validation results */ validation?: TraceValidation; /** Network activity */ network?: TraceNetwork; /** Errors encountered */ errors: TraceError[]; /** Content extraction results */ content: { /** Length of extracted text */ textLength: number; /** Length of markdown */ markdownLength: number; /** Number of tables extracted */ tableCount: number; /** Number of APIs discovered */ apiCount: number; }; /** Skill/procedural memory info */ skills?: { /** Skills that matched */ matched: string[]; /** Skill that was applied */ applied?: string; /** Whether trajectory was recorded */ trajectoryRecorded: boolean; }; /** Anomaly detection results */ anomaly?: { /** Type of anomaly detected */ type: string; /** Suggested action */ action: string; /** Detection confidence */ confidence: number; }; /** Additional metadata */ metadata: { /** User agent used */ userAgent?: string; /** Session profile used */ sessionProfile?: string; /** Whether session was loaded */ sessionLoaded: boolean; /** Options passed to browse */ options: Record; }; } /** * Query filter for searching traces */ export interface TraceQuery { /** Filter by domain */ domain?: string; /** Filter by URL pattern (regex) */ urlPattern?: string; /** Filter by time range (start) */ startTime?: number; /** Filter by time range (end) */ endTime?: number; /** Filter by success/failure */ success?: boolean; /** Filter by error type */ errorType?: TraceError['type']; /** Filter by tier used */ tier?: RenderTier; /** Maximum results to return */ limit?: number; /** Offset for pagination */ offset?: number; } /** * Recording configuration */ export interface RecordingConfig { /** Whether recording is enabled globally */ enabled: boolean; /** Domains to always record (even if disabled globally) */ alwaysRecordDomains: string[]; /** Domains to never record (even if enabled globally) */ neverRecordDomains: string[]; /** Only record failures */ onlyRecordFailures: boolean; /** Maximum traces to retain */ maxTraces: number; /** Maximum age of traces in hours */ maxAgeHours: number; /** Maximum storage size in bytes */ maxStorageBytes: number; } /** * Trace storage statistics */ export interface TraceStats { /** Total traces stored */ totalTraces: number; /** Traces by domain */ byDomain: Record; /** Traces by tier */ byTier: Record; /** Success vs failure counts */ successCount: number; failureCount: number; /** Storage size in bytes */ storageSizeBytes: number; /** Oldest trace timestamp */ oldestTrace?: number; /** Newest trace timestamp */ newestTrace?: number; } /** * Default recording configuration */ export declare const DEFAULT_RECORDING_CONFIG: RecordingConfig; /** * DebugTraceRecorder - Records and manages debug traces */ export declare class DebugTraceRecorder { private traceDir; private config; private traceIndex; private initialized; constructor(traceDir?: string, config?: Partial); /** * Initialize the recorder (load index from disk) */ initialize(): Promise; /** * Check if recording should occur for a given domain and success state */ shouldRecord(domain: string, success: boolean): boolean; /** * Record a debug trace */ record(trace: DebugTrace): Promise; /** * Get a trace by ID */ getTrace(id: string): Promise; /** * Query traces with filters */ query(filter?: TraceQuery): Promise; /** * Get trace statistics */ getStats(): Promise; /** * Delete a trace by ID */ deleteTrace(id: string): Promise; /** * Clear all traces */ clearAll(): Promise; /** * Export traces for sharing/replay */ exportTraces(ids: string[]): Promise<{ traces: DebugTrace[]; exportedAt: number; }>; /** * Update recording configuration */ updateConfig(config: Partial): void; /** * Get current recording configuration */ getConfig(): RecordingConfig; /** * Enable recording globally */ enable(): void; /** * Disable recording globally */ disable(): void; /** * Add domain to always-record list */ alwaysRecord(domain: string): void; /** * Add domain to never-record list */ neverRecord(domain: string): void; private getTracePath; private loadIndex; private enforceRetention; } /** * Create a debug trace from browse operation data */ export declare function createDebugTrace(url: string, finalUrl: string, success: boolean, durationMs: number, data: { decisionTrace?: DecisionTrace; network?: NetworkRequest[]; errors?: Array<{ type: string; message: string; stack?: string; }>; validation?: { valid: boolean; reasons: string[]; }; content?: { text: string; markdown: string; tables: number; apis: number; }; skills?: { matched: string[]; applied?: string; trajectoryRecorded: boolean; }; anomaly?: { type: string; action: string; confidence: number; }; options?: Record; sessionProfile?: string; sessionLoaded?: boolean; tier?: RenderTier; fellBack?: boolean; tiersAttempted?: RenderTier[]; budget?: { maxLatencyMs?: number; maxCostTier?: RenderTier; latencyExceeded: boolean; tiersSkipped: RenderTier[]; }; }): DebugTrace; /** * Get or create the global debug trace recorder */ export declare function getDebugTraceRecorder(traceDir?: string): DebugTraceRecorder; /** * Reset the global recorder (for testing) */ export declare function resetDebugTraceRecorder(): void; //# sourceMappingURL=debug-trace-recorder.d.ts.map