export interface DiscoveredProject { projectId: string; path: string; projectName?: string; } /** * Why a watched directory is not a registered project. * - `no-config`: no `.mnemonik.json` at all. * - `unusable-config`: a `.mnemonik.json` exists but carries no usable * `projectId` (unparseable, or the field is missing/empty). This case used * to be doubly silent: nothing was registered AND the walk stopped there, * so the whole subtree disappeared without a word. */ export type UnregisteredReason = 'no-config' | 'unusable-config'; export interface UnregisteredRoot { path: string; reason: UnregisteredReason; /** Human-readable specifics for `unusable-config` (e.g. the parse error). */ detail?: string; } /** * The result of one discovery pass. WATCHED is not REGISTERED: the walk visits * every directory under the configured roots, but only those carrying a usable * `.mnemonik.json` become projects the daemon scans. `unregistered` is the * difference — directories that look like project roots, are under a watch * root, and are never scanned or indexed. They are reported, never registered: * whether a directory should be indexed is the owner's decision. */ export interface DiscoveryResult { projects: DiscoveredProject[]; unregistered: UnregisteredRoot[]; } export declare class ProjectDiscovery { private roots; private maxDepth; private timeoutMs; constructor(roots: string[], options?: { maxDepth?: number; timeoutMs?: number; }); /** * Walk the configured roots and report BOTH sides of the ledger: projects * with a usable `.mnemonik.json` (deduplicated by projectId — same project * found at multiple paths, first wins) and the project-shaped directories * that have none. Nothing is auto-registered. */ discover(): Promise; /** * Returns whether a registered project was found at or below `dir`. The * unregistered report is written post-order, so a directory is only ever * reported after its whole subtree came back empty — a timeout mid-subtree * therefore cannot produce a false "unregistered" claim. */ private walk; }