/** * `sklx agent uninstall` core orchestration (SMI-5456 Wave 1 Step 5). * * Reverses EXACTLY what `installAgentPack` wrote by replaying the manifest * it saved — never by re-deriving "what the generator would currently * produce" (which could have drifted across a version bump between install * and uninstall). Per manifest entry: * - `backupPath !== null` (a shared config file we merged a key into): * restore the file to the FULL pre-merge content captured in the * backup — this removes exactly our `skillsmith` key/hook entry while * leaving every other key in the file untouched, because the backup was * taken of the whole file immediately before the merge. * - `backupPath === null` (a file we created outright — skill pack copy, * shim, hook script): delete it. There is nothing to restore to. * - A path already missing on disk (user deleted it manually) is a no-op, * not an error. * * SECURITY (governance follow-up, 2026-07-01; symlink check added SMI-6275 * Wave 5 per two rounds of GPT-5.6-Sol pr-reviewer findings — round 1 caught * a symlinked LEAF, round 2 caught round 1's own fix still missing a * symlinked ANCESTOR directory): before touching the filesystem, every * entry's `path` is checked against {@link isAllowedManifestEntryPath} (must * structurally match one of the installer's known per-harness target * locations), that `realpathSync()`'s fully-resolved form of the path * (dereferencing EVERY symlink in the chain, leaf and ancestors alike) * equals its own plain `path.resolve()` (a matching suffix proves the path * LOOKS right, not that every component of the actual filesystem node * reached by that path is a plain, non-symlinked directory/file the * installer actually wrote — a link anywhere in the chain would make the * restore branch's `writeFileSync` follow it and overwrite whatever is at * the far end instead), and, when `backupPath` is set, * {@link isAllowedManifestBackupPath} (must resolve under this run's * manifest backups directory). The manifest is an ordinary user-writable * JSON file, not a signed record — a corrupted or tampered manifest must * never become an arbitrary-file-delete/overwrite primitive. An entry * failing any check is skipped entirely (added to `result.rejected`, * counted toward neither `removed` nor `restored`) * rather than acted on. * * After removing all installer-created files, now-empty directories we * likely created (the parents of removed paths) are cleaned up bottom-up — * a non-empty directory is left alone (`rmdirSync` only removes empty ones). * * Known limitation: a hook script's original executable bit is not * separately tracked, so restoring a backup writes default file * permissions. This only matters for the vanishingly rare case of a * pre-existing FOREIGN executable file that happened to already occupy our * namespaced hook-script path — documented, not defended against. * * @module @skillsmith/core/install/agent-pack-uninstaller */ import type { AgentUninstallOptions, AgentUninstallResult } from './agent-pack-installer.types.js'; export declare function uninstallAgentPack(_opts?: AgentUninstallOptions): AgentUninstallResult; //# sourceMappingURL=agent-pack-uninstaller.d.ts.map