export interface ScanPushFile { path: string; hash: string; chunks: Array<{ content: string; startLine: number; endLine: number; chunkType: string; language: string; contentHash: string; metadata: { fileName: string; extension: string; size: number; /** * Symbol identity resolved by the AST chunker. Optional: absent for languages * with no vendored grammar, which keep the heuristic chunker. * * MUST stay in lockstep with `scanChunkSchema.metadata` in * src/server/routes/schemas.ts. That object is closed and Zod strips unknown * keys SILENTLY, so a field added here alone is discarded at the HTTP * boundary with no error and no log — which is exactly what happened to * symbolName and signature between February and 2026-07-30. */ symbolName?: string; symbolKind?: string; signature?: string; /** Immediate structural container. Lookup stays on the bare symbolName. */ symbolContainer?: string; }; }>; /** * Optional raw file content. Sent by the scanner daemon for ALL files * (code and authority/manifest alike) so the doc-truth worker can run * claim extraction against whole documents without filesystem access, and * so every stored chunk has a stored source to be verified against. * * The push ceiling is the shared `MAX_SCANNED_FILE_BYTES` (10 MB) — the * same ceiling that decides what gets scanned at all, so size can no * longer cause omission. Omitted ONLY when the raw read failed; the daemon * logs a warning naming the path whenever that happens. * * On that path `chunks` are still sent — omission costs nothing downstream * of search — but content is left absent rather than reconstructed from * those chunks. A chunk join is not the file (trimmed whitespace, boundary * overlap, dropped sub-minChunkSize fragments), and shipping it as * whole-file content would have citation verification judge snippets * against bytes that never existed on disk. Absent content is a no-op for * the server's stored content, preserving the last faithful copy. */ content?: string; } export interface ScanPushCommit { sha: string; author: string; date: string; message: string; files: string[]; parents: string[]; } export interface ScanPushPayload { projectId: string; files: ScanPushFile[]; commits?: ScanPushCommit[]; ignorePatterns?: string[]; } export interface ScanStatusResponse { files: Array<{ path: string; hash: string; }>; gitMining?: { enabled: boolean; lastMinedCommit: string | null; }; } export interface GitMiningMeta { enabled: boolean; lastMinedCommit: string | null; } /** * A request the daemon must not redrive without a payload/configuration change. * Retrying these responses every ten seconds cannot make them succeed and can * turn one rejected scan into a permanent upload loop. */ export declare class PermanentScannerRequestError extends Error { readonly status: number; constructor(message: string, status: number); } export declare class MnemonikClient { private serverUrl; private apiKey; constructor(serverUrl: string, apiKey: string); private request; /** * Fetch per-file hashes for dedup, plus git-mining metadata. * The daemon uses `gitMining.enabled` to decide whether to collect commits * this cycle, and `lastMinedCommit` as the lower bound of `git log`. */ getStatus(projectId: string): Promise<{ fileHashes: Map; gitMining: GitMiningMeta; }>; /** * Push file chunks in batches. When `commits` is supplied (non-empty) it is * attached to the first batch only — BullMQ's idempotent jobId means a * duplicate would collapse anyway, but one payload saves bandwidth. * * When `files` is empty and `commits` is non-empty, a single commit-only * push is made — the server accepts `files=[]` since If both are * empty, no request is sent. */ pushFiles(projectId: string, files: ScanPushFile[], commits?: ScanPushCommit[], ignorePatterns?: string[]): Promise<{ success: boolean; }>; sendHeartbeat(projectId: string, scanner: { scope: 'global'; version?: string; }): Promise; /** * Notify the server of files that have been removed since the daemon's * previous scan of this project. Server deprecates exactly those code * memories. Empty arrays are accepted as no-ops so the daemon can call * this every tick regardless of whether anything was removed. * * The caller is responsible for computing the removal set locally — the * old inventory-diff shape that asked the server to derive removals from * a "known files" list has been removed because a small/malformed list * would mass-deprecate. The narrow `removedFiles` shape cannot exhibit * that failure mode by construction. */ reportRemovedFiles(projectId: string, removedFiles: string[]): Promise<{ deprecated: number; couplingsRemoved: number; }>; healthCheck(): Promise; }