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
