/** * Audit record — what an agent actually touched. * * Distinct from `history.ts`, which exists to undo things: that journal keeps * file contents so a write can be reversed, records only mutations, and lives * in `~/.codeep/history/`. This one answers a different question — *what did * this agent do to this project* — so it records reads and refusals too, keeps * no file contents at all, and lives with the project it describes. * * The most valuable entry is the one nothing recorded before: a tool call the * capability boundary refused. A boundary you cannot audit is a boundary you * have to take on faith. * * Format is JSON Lines. Appending one line per event survives a crash mid-run, * needs no read-modify-write, and stays greppable without a parser. * * PRIVACY: entries carry command lines, file paths and MCP tool arguments, not * file contents. A command or an argument can still contain a secret someone * typed into it, exactly as shell history can — treat the directory like shell * history, not like source. * * It sits under `.codeep/`, which most projects already ignore, but Codeep does * not edit anyone's `.gitignore` and this module must not claim otherwise. If a * project tracks `.codeep/`, the audit log will be committed with it. */ /** One thing an agent did, or was stopped from doing. */ export interface AuditEvent { /** Epoch millis. */ ts: number; /** Groups every event from one agent run. */ run: string; /** Provider-facing tool name, e.g. `read_file`. Absent on run markers. */ tool?: string; /** What kind of thing happened. `refused` is a boundary denial. */ action: 'run-start' | 'run-end' | 'read' | 'write' | 'edit' | 'delete' | 'command' | 'search' | 'list' | 'mkdir' | 'fetch' | 'refused'; /** File path, command line, or URL — truncated, never file contents. */ target?: string; outcome?: 'ok' | 'error' | 'refused'; /** Short reason or note. Never a file body. */ detail?: string; /** Run markers only: the active custom bot and what it was granted. */ agent?: string; capabilities?: string[]; prompt?: string; } /** A one-line, content-free description of what a tool call was aimed at. * Paths, commands and URLs are the point of the record; file bodies are not, * and `content`/`old_string` style arguments are never read here. */ export declare function describeAuditTarget(call: { tool: string; parameters: Record; }): string; /** Audit is on unless explicitly disabled. A record you have to remember to * switch on is not a record you can rely on having. */ export declare function isAuditEnabled(): boolean; /** * Append one event. Never throws: an unwritable project (read-only checkout, * full disk, a directory we lack permission for) must not take the agent down * with it. A missing audit line is a gap in the record; a crashed run is worse. */ export declare function recordAuditEvent(projectRoot: string, event: AuditEvent): void; /** Open a run and return its id. Records the agent and the capabilities it was * granted, so a later reader can tell what the boundary *was* at the time — * a bot edited afterwards must not rewrite the history of what it could do. */ export declare function beginAuditRun(projectRoot: string, opts: { prompt: string; agent?: string; capabilities?: string[]; }): string; export declare function endAuditRun(projectRoot: string, run: string, outcome: 'ok' | 'error', detail?: string): void; /** One run, reassembled from its lines. */ export interface AuditRun { run: string; startedAt: number; endedAt?: number; prompt?: string; agent?: string; capabilities?: string[]; outcome?: 'ok' | 'error'; events: AuditEvent[]; refusals: number; } /** * Read back the most recent runs, newest first. * * Malformed lines are skipped rather than throwing: an append-only log written * by a process that may be killed mid-write will occasionally end in a partial * line, and one torn line must not make the whole record unreadable. */ export declare function readAuditRuns(projectRoot: string, limit?: number): AuditRun[]; /** Render recent runs for `/audit`. Deliberately compact: the question this * answers is "what has been happening here", and a wall of every event * answers it worse than a summary with the refusals called out. */ export declare function formatAuditLog(projectRoot: string, limit?: number): string;