// Shared types for the PR-bot. Small and explicit — the bot's behavior // should be readable from these shapes alone. export interface Gap { id: string; // hash of prd_line — stable key for dedup prd_line: string; // the [bot-eligible]-tagged line, verbatim context: string; // surrounding context from the PRD (next ~5 lines) source_file: string; // e.g. "docs/PRD.md" line_number: number; } export interface ProposalFile { path: string; // repo-relative (no leading slash) content: string; // full file content — the bot writes whole files, not patches is_new: boolean; // true = create, false = overwrite existing } export interface Proposal { summary: string; // one-line rationale: string; // why this change addresses the gap files: ProposalFile[]; estimated_loc: number; // total added+changed lines across all files model_used: string; tokens_used: number; } export interface CycleContext { startedAt: string; // ISO dailyCallsUsed: number; dailyCallsBudget: number; dailyTokensUsed: number; dailyTokensBudget: number; lastCycleAt: string | null; lastCycleGapId: string | null; autotuneBusy: boolean; workingTreeDirty: boolean; } export type CycleOutcome = | "ok" // PR opened | "skipped_pause" | "skipped_cost" | "skipped_policy" | "skipped_no_gap" | "skipped_dirty_tree" | "proposal_rejected" | "apply_failed" | "cycle_noop" // proposal applied but every file was identical to what's on disk | "tests_failed" | "pr_skipped_by_policy" | "pr_failed" | "model_failed"; // Mem0-aligned apply outcomes. Three shapes instead of the binary // "written" / "errored". NOOP is a first-class outcome — identical // content shouldn't waste test cycles or open an empty PR. export type ApplyMode = "add" | "update" | "noop"; export interface ApplyOutcome { added: string[]; updated: string[]; noop: string[]; errors: string[]; } export interface CycleResult { cycle_id: string; started_at: string; ended_at: string; outcome: CycleOutcome; reason: string; gap: Gap | null; proposal: Proposal | null; filesAdded: string[]; filesUpdated: string[]; filesNoop: string[]; testsGreen: boolean | null; // null = not run testsOutput: string; prUrl: string | null; tokens_used: number; cloud_calls: number; } export interface CostState { date: string; // YYYY-MM-DD UTC calls: number; tokens: number; }