@phase1 @infrastructure @sandbox @merge
Feature: Sandbox Merge Strategies
  As a system managing parallel sandbox changes
  I want multiple strategies for merging concurrent edits to the same resource
  So that conflicts are detected, reported, or resolved automatically

  # --- Git three-way merge ---

  @git_merge
  Scenario: A clean merge combines non-overlapping changes from both sides
    Given a base document with three paragraphs
    And one side appends a paragraph at the end
    And the other side prepends a paragraph at the start
    When the changes are merged using the git strategy
    Then the merge should succeed without conflicts
    And the merged document should contain content from both sides

  @git_merge
  Scenario: Overlapping edits to the same line produce a conflict
    Given a base document with a single line
    And one side changes the line to "alpha version"
    And the other side changes the line to "beta version"
    When the changes are merged using the git strategy
    Then the merge should report a conflict
    And the merged output should contain conflict markers
    And the conflict regions should be identified with line ranges

  @git_merge
  Scenario: Merging three empty documents yields an empty result
    Given all three merge inputs are empty
    When the changes are merged using the git strategy
    Then the merge should succeed without conflicts
    And the merged content should be empty

  @git_merge
  Scenario: The git strategy cleans up temporary files after merging
    Given a base document with a single line
    And one side leaves the document unchanged
    And the other side appends a new line
    When the changes are merged using the git strategy
    Then no temporary merge files should remain on disk

  @git_merge
  Scenario: The git strategy falls back to sequential merge when git is unavailable
    Given a base document with a single line
    And one side changes the line to "ours edit"
    And the other side changes the line to "theirs edit"
    When the changes are merged using the git strategy with git unavailable
    Then the merge should succeed without conflicts
    And the merged content should be the incoming side

  # --- Conflict marker detection ---

  @git_merge @conflict_markers
  Scenario: No conflict markers are found in clean content
    Given a document with no conflict markers
    When the document is scanned for conflict regions
    Then no conflict regions should be found

  @git_merge @conflict_markers
  Scenario: A single conflict region is correctly identified
    Given a document containing one conflict region
    When the document is scanned for conflict regions
    Then exactly one conflict region should be found
    And the conflict region should span the expected lines

  @git_merge @conflict_markers
  Scenario: Multiple conflict regions are all identified
    Given a document containing two conflict regions
    When the document is scanned for conflict regions
    Then exactly two conflict regions should be found

  # --- Sequential last-write-wins merge ---

  @sequential_merge
  Scenario: The incoming content always wins regardless of changes
    Given a base document, a current version, and an incoming version
    When the changes are merged using the sequential strategy
    Then the merge should succeed without conflicts
    And the merged content should be the incoming version

  @sequential_merge
  Scenario: An empty incoming version results in empty content
    Given a base document, a current version, and an empty incoming version
    When the changes are merged using the sequential strategy
    Then the merged content should be empty

  # --- JSON deep merge ---

  @json_merge
  Scenario: Non-overlapping keys from both sides are combined
    Given a current JSON document with key "alpha"
    And an incoming JSON document with key "beta"
    When the documents are merged using the JSON strategy
    Then the merge should succeed without conflicts
    And the merged JSON should contain both keys

  @json_merge
  Scenario: A shared key is recursively merged when both values are objects
    Given a current JSON document with nested object under "config"
    And an incoming JSON document with additional nested keys under "config"
    When the documents are merged using the JSON strategy
    Then the merged JSON "config" should contain keys from both sides

  @json_merge
  Scenario: A shared scalar key is overwritten by the incoming value
    Given a current JSON document with "version" set to 1
    And an incoming JSON document with "version" set to 2
    When the documents are merged using the JSON strategy
    Then the merged JSON "version" should be the incoming value

  @json_merge
  Scenario: Arrays are replaced by the incoming side in replace mode
    Given a current JSON document with an array under "items"
    And an incoming JSON document with a different array under "items"
    When the documents are merged using the JSON strategy in replace mode
    Then the merged JSON "items" should be the incoming array

  @json_merge
  Scenario: Arrays are concatenated in concat mode
    Given a current JSON document with an array under "items"
    And an incoming JSON document with a different array under "items"
    When the documents are merged using the JSON strategy in concat mode
    Then the merged JSON "items" should contain elements from both arrays

  @json_merge
  Scenario: Invalid JSON in one document produces a failed merge
    Given a current document containing invalid JSON
    And an incoming JSON document with key "valid"
    When the documents are merged using the JSON strategy
    Then the merge should fail
    And the failed merge content should fall back to the incoming text

  @json_merge
  Scenario: An empty current document is treated as an empty object
    Given an empty current JSON document
    And an incoming JSON document with key "data"
    When the documents are merged using the JSON strategy
    Then the merge should succeed without conflicts
    And the merged JSON should contain key "data"

  @json_merge
  Scenario: An empty incoming document is treated as an empty object
    Given a current JSON document with key "existing"
    And an empty incoming JSON document
    When the documents are merged using the JSON strategy
    Then the merge should succeed without conflicts
    And the merged JSON should contain key "existing"

  @json_merge
  Scenario: An unrecognized array mode is rejected during configuration
    When the JSON strategy is configured with an invalid array mode
    Then a configuration error should be raised

  @json_merge
  Scenario: A type mismatch between sides is resolved by the incoming value
    Given a current JSON document with "field" as a string
    And an incoming JSON document with "field" as a number
    When the documents are merged using the JSON strategy
    Then the merged JSON "field" should be the incoming number value
