/** * Portable storage of graph source roots (T12474). * * `_nexus_meta` used to persist the absolute project root, source root and * per-repository paths of the machine that last ran `cleo nexus analyze`. The * graph database lives inside the project's own `.cleo/`, so after the project * moved (another mount, another machine, a copied checkout) every reader walked * the OLD path: `cleo nexus status` failed with `scandir ENOENT`, and the * ownership fingerprint changed, forcing a full rebuild. * * Paths are now stored relative to the canonical project root and resolved * against the LIVE project root on read. A legacy absolute record is rebased * onto the live root when every path it holds lies inside the project root it * recorded (a moved project); a record whose paths are inconsistent is returned * unchanged, so a genuinely foreign binding still fails its ownership checks. * * Code placed in `packages/core/` per Package-Boundary Check — verified against AGENTS.md. * * @task T12474 * @module nexus/stored-roots */ import type { GraphIndexAssessment } from '@cleocode/contracts'; /** * Canonicalize a live project root the way source-root observation does. * @param projectRoot - Live project root, possibly relative or through a symlink. * @returns Its real path, or the resolved path when it does not exist. */ export declare function canonicalProjectRoot(projectRoot: string): string; /** * Express an absolute path relative to the project root, with `/` separators. * @param projectRoot - Canonical project root. * @param path - Absolute path to store. * @returns `'.'` for the root itself, otherwise the project-relative path. * @example * ```ts * toStoredPath('/repo', '/repo/app'); // 'app' * ``` */ export declare function toStoredPath(projectRoot: string, path: string): string; /** * Resolve a stored path against the live project root. * @param projectRoot - Canonical live project root. * @param stored - Stored path; relative since T12474, absolute before it. * @param legacyRoot - Project root a legacy absolute record was written under. * @returns The absolute path in the live project. */ export declare function fromStoredPath(projectRoot: string, stored: string, legacyRoot?: string): string; /** Whether `path` is `root` or lies beneath it. */ export declare function isWithin(root: string, path: string): boolean; /** Path fields of one observed root, stored or live. */ export interface RootPathFields { /** Requested location. */ readonly requestedPath: string; /** Real location, when observed. */ readonly canonicalPath: string | null; } /** Path fields of a source-root observation, stored or live. */ export interface SourceRootPathFields { /** Parent project location. */ readonly projectRoot: string; /** Graph source location. */ readonly sourceRoot: string; /** Source root followed by explicitly included repositories. */ readonly roots: readonly R[]; } /** * Project-relative form of an observation — no absolute root survives. * * Used both for storage and for ownership fingerprints, so a project that moved * keeps the same fingerprint and its graph stays incrementally reusable. * * @param roots - Observation with absolute paths. * @returns The same observation with every path relative to its project root. */ export declare function portableSourceRoots(roots: S): S; /** * Encode an assessment for `_nexus_meta`: every root path project-relative. * * An assessment without source-root provenance has no recorded project root to * be relative to and is stored unchanged; every analysis records provenance. * * @param assessment - Assessment with absolute paths, as held in memory. * @returns The stored form. */ export declare function encodeStoredAssessment(assessment: GraphIndexAssessment): GraphIndexAssessment; /** Shape of a stored assessment's path fields before validation. */ export interface StoredAssessmentRoots { /** Stored source root. */ readonly sourceRoot: string; /** Stored source-root observation, when recorded. */ readonly sourceRoots?: SourceRootPathFields; } /** * Resolve a stored assessment's paths against the live project root. * * Relative paths (T12474+) resolve directly. A legacy absolute record is * rebased only when all of its paths sit inside the project root it recorded — * the signature of a moved project. An inconsistent record is returned as * stored so ownership validation still rejects it. * * @param stored - Parsed stored value. * @param liveProjectRoot - Project the database was opened for. * @returns The value with absolute, live paths. */ export declare function decodeStoredAssessment(stored: T, liveProjectRoot: string): T; /** * Command that proves or repairs the live project identity; the remedy when a * stored graph names a different project id (T12659). */ export declare const NEXUS_IDENTITY_REMEDY_COMMAND = "cleo doctor project-identity"; /** * Quote one argument for the user's shell, so a printed remedy is exact. * * POSIX shells expand `$`, backticks and `\\` inside double quotes, so a path * is single-quoted there (an embedded `'` becomes `'\\''`). On Windows the path * is double-quoted verbatim — no JSON-style doubled backslashes (T12659). * * @param value - Argument to quote. * @param platform - Target platform; defaults to the host. * @returns The quoted argument. * @example * ```ts * shellQuoteArg("/Users/me/it's $HOME", 'darwin'); // `'/Users/me/it'\''s $HOME'` * shellQuoteArg('C:\\work\\app', 'win32'); // `"C:\\work\\app"` * ``` */ export declare function shellQuoteArg(value: string, platform?: NodeJS.Platform): string; /** Flag that lets an analysis drop included repositories missing on disk (T12659). */ export declare const DROP_MISSING_REPOSITORIES_FLAG = "--drop-missing-repositories"; /** * Exact command that re-binds a moved project's graph to its live root: a full * rebuild at that root. Accepted only when the stored project id equals the * live projectId read from project-info (T12659). * * @param projectRoot - Canonical live project root. * @param extraFlags - Further flags to append (e.g. {@link DROP_MISSING_REPOSITORIES_FLAG}). * @returns The runnable command, with the root quoted for the host shell. * @example * ```ts * nexusRebindCommand('/Users/me/app'); // "cleo nexus analyze '/Users/me/app' --full" * ``` */ export declare function nexusRebindCommand(projectRoot: string, extraFlags?: readonly string[]): string; /** Recorded vs live ownership of a stored graph. */ export interface GraphOwnershipMismatch { /** Project root the stored graph was built under. */ readonly recordedRoot: string; /** Project id the stored graph was built for. */ readonly recordedProjectId: string; /** Canonical live project root. */ readonly liveRoot: string; /** Verified live project id, when it could be read. */ readonly liveProjectId: string | undefined; } /** * The single remedy for a stored graph whose ownership differs from the live * binding: a `--full` re-bind when the project ids match (the project moved), * otherwise the identity check (the graph may belong to another project). * * @param mismatch - Recorded vs live ownership. * @returns The exact command to run. */ export declare function graphOwnershipRemedy(mismatch: GraphOwnershipMismatch): string; /** * One-line detail naming the recorded and live root and id plus the remedy. * * @param mismatch - Recorded vs live ownership. * @returns Human-readable detail for an ownership error. */ export declare function describeGraphOwnershipMismatch(mismatch: GraphOwnershipMismatch): string; //# sourceMappingURL=stored-roots.d.ts.map