// src/types.ts // SINGLE SOURCE OF TRUTH for all shared interfaces. // Every engine and tool imports from here. No duplication. // ─── STORAGE TYPES ───────────────────────────────────────────────────────── export interface Component { id: number; path: string; sha256: string; exports: string | null; // JSON array string — parse with JSON.parse() file_summary: string | null; // extracted from @fileoverview JSDoc outline: string | null; // bounded structural outline for retrieval comp_type: string; status: 'active' | 'tombstoned'; tombstoned_at:number | null; skipped_reason:string | null; // why outline/indexing was skipped captured_at: number; // unix ms git_sha: string; token_est: number; // pre-calculated: Math.ceil(content.length / 3.5) last_capture_id:number | null; } export interface Decision { id: number; title: string; rationale: string; status: 'active' | 'superseded' | 'rejected'; captured_at: number; tags: string | null; // JSON array string } export interface Snapshot { id: number; git_sha: string; summary: string; captured_at: number; token_est: number; } export interface CaptureRun { id: number; git_sha: string; status: 'pending' | 'running' | 'succeeded' | 'failed'; mode: 'full' | 'incremental' | 'hook-deferred' | 'migrated'; started_at: number; completed_at: number | null; changed_files: number; indexed_files: number; indexed_bytes: number; skipped_count: number; skipped_summary:string | null; // JSON object keyed by skip reason error_message: string | null; } // ─── E1 WATCHER ──────────────────────────────────────────────────────────── export interface CaptureResult { captured: number; // count of files processed git_sha: string; timestamp: number; // unix ms capture_id?: number; deferred?: boolean; } // ─── E2 ANCHOR ───────────────────────────────────────────────────────────── export interface StaleEntry { path: string; stored_sha: string; current_sha: string; // 'DELETED' | 'UNREADABLE' | hex sha256 } export interface DriftReport { drift_score: number; // 0–100 (rounded to 1 decimal) severity: 'LOW' | 'MED' | 'HIGH'; stale: StaleEntry[]; fresh: { path: string }[]; checked_at: number; // unix ms total_components: number; } // ─── E3 ROUTER ───────────────────────────────────────────────────────────── export interface RouterQuery { text: string; // raw query from caller — sanitised internally limit: number; // max results to return — default 25 } export interface RankedComponent { id: number; path: string; exports: string | null; file_summary: string | null; outline: string | null; comp_type: string; token_est: number; bm25_score: number; // negative — more negative = more relevant rank: number; // 1-based rank in result set } export interface RouterResult { ranked: RankedComponent[]; query_text: string; // sanitised query actually sent to MATCH fallback: boolean; // true if query matched 0 results → fell back to recency total_ranked: number; } // ─── E4 GOVERNOR ─────────────────────────────────────────────────────────── // Verified Model Context Sizes — Updated 23 July 2026 // Source: platform.claude.com/docs/en/build-with-claude/context-windows and // support.claude.com (API context-window articles), checked 2026-07-23. // Anthropic entries only were reverified this pass; GPT/Gemini entries below // are carried over unverified from the 22 March 2026 pass and may be stale — // flagged here rather than silently left as if current. export const MODEL_CONTEXT_SIZES: Record = { // Anthropic 'claude-opus-4-8': 1_000_000, 'claude-sonnet-5': 1_000_000, 'claude-fable-5': 1_000_000, 'claude-opus-4-6': 1_000_000, // GA on the API as of this pass — no longer beta-gated 'claude-sonnet-4-6': 1_000_000, // GA on the API as of this pass — no longer beta-gated 'claude-sonnet-4-5': 200_000, // not reverified this pass 'claude-haiku-4-5-20251001': 200_000, // OpenAI — not reverified this pass, carried over from 22 March 2026 'gpt-5.4': 1_050_000, 'gpt-5.4-mini': 1_050_000, 'gpt-5.4-nano': 1_050_000, 'gpt-5.4-pro': 1_050_000, 'gpt-4o': 128_000, // Google — not reverified this pass, carried over from 22 March 2026 'gemini-3.1-pro-preview': 1_000_000, 'gemini-3-flash': 1_000_000, 'gemini-2.5-pro': 1_000_000, 'gemini-2.5-flash': 1_000_000, 'gemini-2.5-flash-lite': 1_000_000, 'default': 200_000, // safe default } as const; export interface BudgetConfig { model?: string; // key into MODEL_CONTEXT_SIZES — default 'default' budget_pct?: number; // 0.01–0.20 — default 0.08 (8%) hard_ceiling?: number; // override: absolute token ceiling (ignores model+pct) } export interface BudgetResult { selected: RankedComponent[]; // subset of RouterResult.ranked that fit budget used_tokens: number; // sum of token_est for selected components budget_tokens: number; // ceiling that was applied dropped: number; // count of ranked components that did not fit model: string; // model used for budget calculation budget_pct: number; // fraction used } // ─── E5 WEAVER ───────────────────────────────────────────────────────────── export interface WeaverInput { drift: DriftReport; budget: BudgetResult; decisions: Pick[]; snapshot: Pick | undefined; projectName: string; operationalWarnings?: string[]; } export interface WeaverOutput { briefing: string; // markdown string — ready for AI agent injection used_tokens: number; // from BudgetResult budget_tokens:number; // from BudgetResult drift_score: number; // from DriftReport severity: string; // from DriftReport } export interface HealthReport { schema_version: number; search_index_version: number; db_integrity: 'ok' | 'failed'; degraded: boolean; degraded_reason: string | null; latest_successful_capture: | Pick | null; pending_capture_count: number; failed_capture_count: number; latest_skipped_summary: Record; hook_installed: boolean; hook_runtime_ready: boolean; }