/** * `~/.cleo` link audit and repair — the keystone of global protocol delivery. * * The global hub `~/.agents/AGENTS.md` references * `@~/.cleo/templates/CLEO-INJECTION.md`. That path is only real when * `~/.cleo` links to the OS data directory (`getCleoHome()`): `~/.local/share/cleo` * on Linux, `~/Library/Application Support/cleo` on macOS, * `%LOCALAPPDATA%\cleo\Data` on Windows. A link carried between machines by * dotfiles (a macOS `~/.cleo` pointing at `/home//.local/share/cleo`) * dangles, and every harness loading the hub silently receives NO protocol — * no error, just an unresolved reference (T12596). * * `existsSync` follows links, so a dangling link reads as ABSENT; creating a * link over it then fails with `EEXIST`. Everything here classifies with * `lstat` first for that reason. * * @task T12596 */ /** The reference the global hub writes; identical on every OS. */ export declare const CANONICAL_HUB_TEMPLATE_REF = "@~/.cleo/templates/CLEO-INJECTION.md"; /** * State of `~/.cleo`: * - `canonical` — a link to `getCleoHome()` (or `CLEO_HOME` IS `~/.cleo`). * - `absent` — nothing there. * - `dangling` — a link whose target does not exist (e.g. a Linux path on macOS). * - `foreign` — a link to an existing directory that is not `getCleoHome()`. * - `directory` — a real directory (pre-canonical layout). * - `other` — a regular file or anything else; never touched. */ export type CleoLinkState = 'canonical' | 'absent' | 'dangling' | 'foreign' | 'directory' | 'other'; /** Result of {@link auditCleoLink}. */ export interface CleoLinkAudit { /** Absolute `~/.cleo` path. */ path: string; /** Where the link must point: `getCleoHome()`. */ canonicalTarget: string; /** Classified state. */ state: CleoLinkState; /** Current link target, or null when `~/.cleo` is not a link. */ target: string | null; /** True when the hub reference `~/.cleo/templates/CLEO-INJECTION.md` resolves to a file. */ hubReferenceResolves: boolean; /** True when `repairCleoLink` can bring the link to `canonical`. */ repairable: boolean; /** Exact command that repairs this state, or null when healthy / not repairable. */ remedy: string | null; } /** Receipt written for every non-dry-run {@link repairCleoLink}. */ export interface CleoLinkRepairReceipt { /** Unique receipt id. */ receiptId: string; /** ISO timestamp. */ at: string; /** What was done. */ action: 'none' | 'created' | 'relinked' | 'refused'; /** State and target before the repair. */ before: { state: CleoLinkState; target: string | null; }; /** State and target after the repair. */ after: { state: CleoLinkState; target: string | null; }; /** * Where the previous entry was moved (a live foreign link or a directory), * so the repair is reversible; null when nothing needed preserving. */ preservedAt: string | null; /** Why the repair was refused, when `action === 'refused'`. */ reason: string | null; /** JSONL file the receipt was appended to, or null on a dry run. */ receiptLog: string | null; /** * Lifecycle phase of this receipt line. An `intent` line is appended BEFORE * anything on disk changes, so a crash between the preserve-rename and the * new link still leaves a record of where the old entry went; the final * line is `completed` or `rolled-back`. `planned` receipts (dry run, no-op, * refused) are returned but never written. */ phase: 'intent' | 'completed' | 'rolled-back' | 'planned'; } /** Thrown when creating the `~/.cleo` link fails; the previous entry has been restored. */ export declare class CleoLinkRepairError extends Error { readonly receipt: CleoLinkRepairReceipt; /** Stable error code. */ readonly code = "E_CLEO_LINK_REPAIR_FAILED"; /** * @param message - What failed. * @param receipt - The `rolled-back` receipt (also appended to the log). */ constructor(message: string, receipt: CleoLinkRepairReceipt); } /** Options shared by the audit and repair functions (tests inject paths). */ export interface CleoLinkOptions { /** `~/.cleo` path. Defaults to `resolveLegacyCleoDir()`. */ path?: string; /** Link target. Defaults to `getCleoHome()`. */ canonicalTarget?: string; } /** Repair command printed in remedies and warnings. */ export declare const CLEO_LINK_REPAIR_COMMAND = "cleo doctor global-delivery --repair"; /** * True when mutating `linkPath` to point at `target` would bind a real, * non-temporary `~/.cleo` to a temporary directory — the shape of a test run * that overrides `CLEO_HOME` without overriding `HOME`. Refused so a test can * never repoint the developer's own `~/.cleo` at a scratch directory. */ export declare function wouldBindRealHomeToTemp(linkPath: string, target: string): boolean; /** * Classify `~/.cleo` without modifying anything. * * @param opts - Path overrides (tests). * @returns The audit; `remedy` names the exact repair command when one applies. * @task T12596 */ export declare function auditCleoLink(opts?: CleoLinkOptions): CleoLinkAudit; /** * Bring `~/.cleo` to the canonical link and record a receipt. * * - `absent` → create the link. * - `dangling` → replace the link (it reaches nothing, so nothing is lost; * the old target is kept in the receipt). * - `foreign` / `directory` → move the entry to `~/.cleo.preserved-` (a * foreign link stays a link, keeping its target), then create the link. * - `other`, or a real `~/.cleo` whose target would be a temp dir → refused. * * Receipts are appended to `/audit/cleo-link-repairs.jsonl`. * * @param opts - `dryRun` reports the planned action without touching disk; * `states` limits which states may be repaired (bootstrap passes only the * lossless ones: `absent`, `dangling`). * @returns The final audit plus the receipt. * @task T12596 */ export declare function repairCleoLink(opts?: CleoLinkOptions & { dryRun?: boolean; states?: readonly CleoLinkState[]; }): Promise<{ audit: CleoLinkAudit; receipt: CleoLinkRepairReceipt; }>; /** * Content for the global hub's CAAMP block. * * Normally the one-line canonical reference. When `~/.cleo/templates` does not * resolve (a link the bootstrap could not repair), a reference would deliver * nothing — so the protocol text is embedded instead, with a marker naming * the repair. Once the link is repaired the next bootstrap writes the * reference again. * * @param templateContent - Installed `CLEO-INJECTION.md` text (embedded on fallback). * @param opts - Path overrides (tests). * @returns The block content and which mode was chosen. * @task T12596 */ export declare function resolveGlobalHubContent(templateContent: string | null, opts?: CleoLinkOptions): { content: string; mode: 'reference' | 'embedded'; audit: CleoLinkAudit; }; //# sourceMappingURL=cleo-link.d.ts.map