/** * Resolved .gitmem directory path * * Solves: process.cwd() changes when agents cd into other repos (e.g., /workspace/gitmem), * but .gitmem/ was created in the project root. * The MCP server is long-running, so we resolve the path once and cache it. * * Resolution order: * 1. GITMEM_DIR env var (explicit override) * 2. Cached path from session_start (most reliable — session_start created the directory) * 3. Walk up from process.cwd() looking for existing .gitmem/ sentinels (backward compat) * 4. Fall back to ~/.gitmem (developer-scoped, survives across projects/containers) */ /** * Validate a string intended for use as a single path component (directory name or filename). * Rejects path traversal sequences, directory separators, and null bytes. * Throws on invalid input — callers should validate before reaching this layer. */ export declare function sanitizePathComponent(value: string, label: string): string; /** * Set the .gitmem directory path (called by session_start after creating it) */ export declare function setGitmemDir(dir: string): void; /** * Get the resolved .gitmem directory path * * Resolution order: * 1. GITMEM_DIR env var (explicit override) * 2. Cached path from session_start (most reliable) * 3. ~/.gitmem — authoritative, and independent of cwd. * * GIT-91 removed a cwd walk-up that sat between 2 and 3. Because it derived the * answer from process.cwd(), the MCP server and the SessionStart hook — which do * not share a cwd — resolved different roots for the same session. Project-scoped * roots are still supported, but must be named explicitly via GITMEM_DIR. */ export declare function getGitmemDir(): string; /** * The developer-scoped root: `/.gitmem`. * * GITMEM_HOME overrides the base directory. It is distinct from GITMEM_DIR: * GITMEM_DIR names the `.gitmem` directory itself and short-circuits resolution * entirely, while GITMEM_HOME only relocates the home the fallback is computed * from, leaving the precedence chain intact. * * It exists because os.homedir() reads the OS-level environment, which cannot be * redirected from inside a worker thread — process.env there is a JS-level copy * that never reaches getenv(). The test suite runs on `pool: "threads"` and * writes real session state, so without this there is no way to keep it off the * developer's store (GIT-92). The same lever is useful for containers and CI, * where HOME is often not where state should live. */ export declare function getHomeGitmemDir(): string; /** * GIT-91: project-scoped roots above the cwd that hold live state and are no * longer read. * * Exported because stderr is invisible in most MCP clients: session_start puts * this in its display, where the user will actually see it. Returns [] on any * error — a diagnostic must never break resolution. */ /** What a stranded root actually holds, for the session_start notice (R18). */ export interface GitmemRootContents { root: string; learnings: number; threads: number; sessions: number; } /** * GIT-91 / R18: what a stranded root contains. * * The notice has to state counts, not just a path. "Your memory is at another * path" is abstract enough to scroll past; "142 learnings, 6 threads are sitting * at this path" is not. Detection-without-use only works if the detection says * something a user can weigh. * * Counts are best-effort by design — an unreadable or unexpected file yields 0 * rather than throwing. A notice that fails to render because one file is * malformed would reintroduce exactly the silence this exists to prevent. */ export declare function describeGitmemRoot(root: string): GitmemRootContents; export declare function findStrandedProjectRoots(): string[]; /** * GIT-91: does this directory hold a gitmem store that is actually in use? * * Presence of a file is not evidence. The registry in particular is present and * empty on any tree a gitmem process has merely passed through, and empty means * the opposite of "sessions live here". Test runs leave the same residue * (GIT-92), so an unrelated repo can acquire a convincing-looking .gitmem/ * without ever having held a session. * * Any ONE of these counts: * - config.json a deliberate project-scoped install * - a registered session the registry names at least one * - a real session dir sessions//session.json parses with a session_id * * Exported for tests and diagnostics; the resolution path is the only caller * that matters. */ export declare function isLiveGitmemRoot(candidate: string): boolean; /** * Get a file path within the .gitmem directory */ export declare function getGitmemPath(filename: string): string; /** * Get the per-session directory path: .gitmem/sessions// * Creates the directory if it doesn't exist. */ export declare function getSessionDir(sessionId: string): string; /** * Get a file path within a per-session directory. */ export declare function getSessionPath(sessionId: string, filename: string): string; /** * Read the "project" field from .gitmem/config.json. * Returns null if the file doesn't exist or has no project field. * * Precedence (handled by callers): explicit param > config.json > "default" */ export declare function getConfigProject(): string | null; /** * Check if feedback submission is enabled in .gitmem/config.json */ export declare function isFeedbackEnabled(): boolean; /** * Get the install_id from .gitmem/config.json (anonymous install identifier) */ export declare function getInstallId(): string | null; /** * Clear the cached path (for testing) */ export declare function clearGitmemDirCache(): void; //# sourceMappingURL=gitmem-dir.d.ts.map