Feature: Checkpoint Service Coverage R3
  Scenarios targeting uncovered lines in checkpoint_service.py:
  selective_rollback exception paths (425-426, 453-460),
  archive_artifacts with explicit archive_dir (487),
  and _compute_diff_snapshot edge cases (541, 546, 548, 556-566).

  Background:
    Given chkcov3 the checkpoint service module is available

  # ---------------------------------------------------------------
  # selective_rollback: rev-parse HEAD fails → current_head = None
  # Lines 425-426
  # ---------------------------------------------------------------
  Scenario: selective_rollback when rev-parse HEAD fails sets current_head to None and re-raises
    Given chkcov3 a checkpoint service with in-memory storage
    And chkcov3 a sandbox directory with .git exists
    And chkcov3 a checkpoint exists for the sandbox plan
    And chkcov3 _run_git is mocked to always fail
    When chkcov3 I call selective_rollback for the plan and checkpoint
    Then chkcov3 an exception should be stored on context
    And chkcov3 the stored exception should be a BusinessRuleViolation

  # ---------------------------------------------------------------
  # selective_rollback: rollback fails AND recovery also fails
  # Lines 453-458, 460
  # ---------------------------------------------------------------
  Scenario: selective_rollback recovery failure is logged when both rollback and recovery fail
    Given chkcov3 a checkpoint service with in-memory storage
    And chkcov3 a sandbox directory with .git exists
    And chkcov3 a checkpoint exists for the sandbox plan
    And chkcov3 _run_git is mocked to succeed once then fail thereafter
    When chkcov3 I call selective_rollback for the plan and checkpoint
    Then chkcov3 an exception should be stored on context
    And chkcov3 the stored exception should be a BusinessRuleViolation

  # ---------------------------------------------------------------
  # archive_artifacts with explicit archive_dir
  # Line 487
  # ---------------------------------------------------------------
  Scenario: archive_artifacts uses explicit archive_dir when provided
    Given chkcov3 a checkpoint service with in-memory storage
    And chkcov3 a temporary sandbox with artifact files
    And chkcov3 an explicit archive directory
    When chkcov3 I call archive_artifacts with the explicit archive_dir
    Then chkcov3 the archived list should contain the artifact paths
    And chkcov3 the artifacts should exist in the explicit archive directory

  # ---------------------------------------------------------------
  # _compute_diff_snapshot: previous_ref == current_ref
  # Line 541
  # ---------------------------------------------------------------
  Scenario: _compute_diff_snapshot returns empty when refs are identical
    Given chkcov3 a checkpoint service with in-memory storage
    And chkcov3 a diff-plan checkpoint with ref "aaa111"
    When chkcov3 I call _compute_diff_snapshot with current_ref "aaa111"
    Then chkcov3 the diff result should be an empty list

  # ---------------------------------------------------------------
  # _compute_diff_snapshot: _resolve_sandbox_path raises
  # Lines 546, 548
  # ---------------------------------------------------------------
  Scenario: _compute_diff_snapshot returns empty when no sandbox is registered
    Given chkcov3 a checkpoint service with in-memory storage
    And chkcov3 an unregistered plan "plan-no-sandbox" has a checkpoint with ref "bbb222"
    When chkcov3 I call _compute_diff_snapshot for plan "plan-no-sandbox" with current_ref "ccc333"
    Then chkcov3 the diff result should be an empty list

  # ---------------------------------------------------------------
  # _compute_diff_snapshot: git diff command fails
  # Lines 556-562, 564, 566
  # ---------------------------------------------------------------
  Scenario: _compute_diff_snapshot returns empty when git diff fails
    Given chkcov3 a checkpoint service with in-memory storage
    And chkcov3 a sandbox directory with .git exists
    And chkcov3 the sandbox plan has a checkpoint with ref "ddd444"
    And chkcov3 _run_git is mocked to raise on diff command
    When chkcov3 I call _compute_diff_snapshot for the sandbox plan with current_ref "eee555"
    Then chkcov3 the diff result should be an empty list
