Feature: CONC3 - Garbage collection and cleanup As a platform operator I want to clean up stale sandboxes, checkpoints, and sessions So that disk space is reclaimed and the system stays healthy # --- Retention policy defaults --- Scenario: Default sandbox max age is 48 hours Given the default cleanup settings Then the sandbox max age hours should be 48 Scenario: Default checkpoint max per plan is 50 Given the default cleanup settings Then the checkpoint max per plan should be 50 Scenario: Default session inactivity days is 30 Given the default cleanup settings Then the session inactivity days should be 30 Scenario: Default log retention days is 30 Given the default cleanup settings Then the log retention days should be 30 Scenario: Default backup retention days is 7 Given the default cleanup settings Then the backup retention days should be 7 # --- Cleanup service: sandboxes --- Scenario: Identify stale sandbox directories Given a sandbox directory older than the max age When I scan for stale sandboxes Then the stale sandbox should be identified Scenario: Skip active sandboxes linked to running plans Given a sandbox directory linked to a running plan When I scan for stale sandboxes Then the active sandbox should be skipped And the skipped sandbox should be logged Scenario: Purge a stale sandbox directory Given a sandbox directory older than the max age When I purge stale sandboxes Then the sandbox directory should be removed And the cleanup summary should report 1 sandbox removed Scenario: Git worktree sandbox cleanup removes branch Given a stale git worktree sandbox with branch "cleveragents/plan-test-plan" When I purge stale sandboxes Then the worktree directory should be removed And the cleanup summary should report 1 sandbox removed # --- Cleanup service: checkpoints --- Scenario: Identify excess checkpoints per plan Given a plan with 60 checkpoints and max per plan is 50 When I scan for excess checkpoints Then 10 excess checkpoints should be identified Scenario: Pruning keeps first and most recent checkpoints Given a plan with 60 checkpoints and max per plan is 50 When I prune excess checkpoints Then 50 checkpoints should remain And the first checkpoint should be preserved And the most recent checkpoint should be preserved # --- Cleanup service: sessions --- Scenario: Identify inactive sessions Given a session inactive for 45 days and threshold is 30 When I scan for inactive sessions Then the inactive session should be identified Scenario: Active sessions within threshold are skipped Given a session inactive for 5 days and threshold is 30 When I scan for inactive sessions Then the session should not be identified Scenario: Purge inactive sessions Given a session inactive for 45 days and threshold is 30 When I purge inactive sessions Then the session should be removed And the cleanup summary should report 1 session removed # --- Cleanup service: logs --- Scenario: Identify expired log files Given a log file older than 30 days When I scan for expired logs Then the expired log file should be identified Scenario: Fresh log files are preserved Given a log file created 5 days ago When I scan for expired logs Then the log file should not be identified # --- Cleanup service: backups --- Scenario: Identify expired backup files Given a backup file older than 7 days When I scan for expired backups Then the expired backup should be identified # --- Dry-run mode --- Scenario: Dry-run reports counts without deleting Given a sandbox directory older than the max age And a session inactive for 45 days and threshold is 30 When I run cleanup in dry-run mode Then the dry-run report should show 1 sandbox to clean And the dry-run report should show 1 session to clean And no files should be deleted Scenario: Dry-run reports stale paths Given a sandbox directory older than the max age When I run cleanup in dry-run mode Then the dry-run report should include the sandbox path # --- Full purge mode --- Scenario: Full purge cleans all resource types Given a sandbox directory older than the max age And a session inactive for 45 days and threshold is 30 And a log file older than 30 days When I run cleanup with purge all Then the sandbox directory should be removed And the session should be removed And the log file should be removed # --- Per-resource cleanup summaries --- Scenario: Cleanup summary includes per-resource counts Given a sandbox directory older than the max age And a session inactive for 45 days and threshold is 30 When I run cleanup with purge all Then the cleanup summary should report 1 sandbox removed And the cleanup summary should report 1 session removed Scenario: Cleanup summary reports zero when nothing to clean Given no stale resources exist When I run cleanup with purge all Then the cleanup summary should report 0 sandboxes removed And the cleanup summary should report 0 sessions removed And the cleanup summary should report 0 checkpoints removed # --- Config keys for retention --- Scenario: Custom retention settings override defaults Given cleanup settings with sandbox max age 24 hours Then the sandbox max age hours should be 24 Scenario: Cleanup schedule defaults to manual Given the default cleanup settings Then the cleanup schedule should be "manual" # --- Edge cases --- Scenario: Cleanup handles missing directories gracefully Given the sandbox temp directory does not exist When I scan for stale sandboxes Then zero stale sandboxes should be found Scenario: Cleanup handles empty database gracefully Given an empty database with no sessions or plans When I scan for inactive sessions Then zero inactive sessions should be found # --- CLI command tests --- Scenario: CLI scan command reports stale resources Given a cleanup CLI runner And a stale sandbox for CLI testing When I invoke the cleanup scan command Then the CLI exit code should be 0 And the cleanup CLI output should contain "Cleanup Scan Results" Scenario: CLI purge dry-run command shows preview Given a cleanup CLI runner When I invoke the cleanup purge command with dry-run Then the CLI exit code should be 0 And the cleanup CLI output should contain "Dry-Run" Scenario: CLI purge command with yes flag executes Given a cleanup CLI runner When I invoke the cleanup purge command with yes flag Then the CLI exit code should be 0 And the cleanup CLI output should contain "Cleanup Complete" Scenario: CLI purge all command with yes flag Given a cleanup CLI runner When I invoke the cleanup purge command with all and yes Then the CLI exit code should be 0 And the cleanup CLI output should contain "Cleanup Complete" Scenario: CLI status command shows retention policies Given a cleanup CLI runner When I invoke the cleanup status command Then the CLI exit code should be 0 And the cleanup CLI output should contain "Retention Policies" And the cleanup CLI output should contain "Sandbox max age" And the cleanup CLI output should contain "Checkpoint max/plan" And the cleanup CLI output should contain "Session inactivity" And the cleanup CLI output should contain "Log retention" And the cleanup CLI output should contain "Backup retention" And the cleanup CLI output should contain "Schedule" Scenario: CLI purge command without yes prompts for confirmation Given a cleanup CLI runner When I invoke the cleanup purge command without confirmation Then the CLI exit code should be 1 Scenario: CleanupReport as_dict returns correct structure When I create a cleanup report with known values Then the report dict should contain key "sandboxes" And the report dict should contain key "checkpoints" And the report dict should contain key "sessions" And the report dict should contain key "logs" And the report dict should contain key "backups" Scenario: CleanupService rejects non-Settings argument When I create a cleanup service with invalid settings Then a TypeError should be raised Scenario: Age description returns human-readable string Given a cleanup service for age description testing When I check the age description for a 2 hour old file Then the age description should contain "hours old" Scenario: Age description returns minutes for recent files Given a cleanup service for age description testing When I check the age description for a 10 minute old file Then the age description should contain "minutes old" Scenario: Age description returns days for old files Given a cleanup service for age description testing When I check the age description for a 5 day old file Then the age description should contain "days old" Scenario: Scan logs via full scan method Given a log file older than 30 days When I run a full scan Then the report should contain log stale items Scenario: Scan backups via full scan method Given a backup file older than 7 days When I run a full scan Then the report should contain backup stale items Scenario: Purge logs via purge all method Given a log file older than 30 days When I run purge all Then the log file should be removed Scenario: Purge backups via purge all method Given a backup file older than 7 days When I run purge all Then the backup file should be removed Scenario: Scan checkpoints via full scan method Given a plan with 60 checkpoints and max per plan is 50 When I run a full checkpoint scan Then the report should contain checkpoint stale items Scenario: Purge checkpoints via purge method Given a plan with 60 checkpoints and max per plan is 50 When I run purge for checkpoints Then the report should show checkpoints removed