import type { ClassifyResult } from "./classify.js"; import type { RepoMetaExtraction } from "./repo-meta.js"; import { JournalWriter } from "./journal.js"; /** * v0.7 — cleanup orchestrator. * Per docs/plan/v0.7-uninstall-lifecycle.md §5.1 step 3 + §10 #8 + * §5.4 keep-workspace matrix + §11.3 journal. * * Cleanup operates *after* the archive zip has been built and verified. * Each stage logs `begin`/`end` to the journal so a crashed run can resume * idempotently. Removing a path that no longer exists is a no-op, so * resuming is safe even mid-stage. * * Class matrix: * A — never touched (excluded from classification's traversal) * A* — surgical purge of `/.solosquad/` (only after meta extracted) * B — delete normally; under --keep-workspace, KEEP on disk * C — delete normally; sessions/*.json moved to sessions/_archived/ when keep-workspace * D — always deleted (secrets never linger on disk) * E — never touched (external resources) */ export interface CleanupOptions { workspace: string; classification: ClassifyResult; extractedRepos: RepoMetaExtraction[]; reposMissingRepoYaml: { orgSlug: string; repoSlug: string; solosquadDir: string; }[]; journal: JournalWriter; dryRun: boolean; keepWorkspace: boolean; alsoPurgeBackups: boolean; } export interface CleanupReport { removed: string[]; preserved: string[]; archivedSessions: string[]; skipped: string[]; assertions: RepoAssertion[]; /** Stages that were skipped because journal showed them already done. */ resumedSkippedStages: string[]; } export interface RepoAssertion { repoPath: string; passed: boolean; reason?: string; } export declare function runCleanup(opts: CleanupOptions): Promise; declare function surgicalRemoveRepoSolosquad(solosquadDir: string, dryRun: boolean): RepoAssertion; interface PathSnapshot { relPath: string; size: number; mtimeMs: number; } declare function snapshotRepoExcludingSolosquad(repoRoot: string): PathSnapshot[]; declare function snapshotsEqual(a: PathSnapshot[], b: PathSnapshot[]): boolean; /** * Decide whether a class B/C entry should remain on disk under * `--keep-workspace`. Per §5.4 matrix: * - B always kept on disk (preserved for re-install) * - C: workspace.yaml + .org.yaml are deleted (re-init regenerates). * Other C entries (.solosquad/agents/, docker-compose.yml, etc.) are * also deleted since re-init regenerates them. sessions/*.json get * special handling above. * - D always deleted. */ declare function shouldKeepUnderKeepWorkspace(cls: string, relPath: string): boolean; export declare const _cleanupInternals: { surgicalRemoveRepoSolosquad: typeof surgicalRemoveRepoSolosquad; snapshotRepoExcludingSolosquad: typeof snapshotRepoExcludingSolosquad; snapshotsEqual: typeof snapshotsEqual; shouldKeepUnderKeepWorkspace: typeof shouldKeepUnderKeepWorkspace; }; export {};