gabriel / muse public
Open #29 testing
filed by gabriel human · 6 days ago

Comprehensive merge strategy TDD: all --strategy and --history permutations with deliberate conflicts

0 Anchors
Blast radius
Churn 30d
0 Proposals

Goal

Build a load-bearing TDD suite that exercises every permutation of `muse merge` strategy and history options with deliberate, engineered conflicts at all three levels Muse tracks: file, directory, and symbol. This suite is the ground truth for "Muse shines at merges" — if it is green, the claim is proved. If it is red, we know exactly what is broken.

Background

Muse tracks conflicts at the symbol level via `.muse/MERGE_STATE.json` and `muse conflicts --json`. Unlike git's line-level conflict markers, Muse can resolve conflicts at the function/class boundary. This suite must exercise all three levels end-to-end and assert the correct resolution mechanics for each.

Agents have been losing work during merge operations because of a flaw in how `muse commit --allow-empty` stores the merge snapshot (it uses the ours-side snapshot, silently discarding theirs-side changes). This suite will catch that regression and others like it.

Strategy matrix

`--strategy` `--history` Description
`overlay` `merge` Feature branch wins on conflicts, full DAG preserved
`overlay` `squash` Feature branch wins, single squashed commit
`overlay` `rebase` Feature branch wins, linear history
`state_merge` `merge` Three-way merge with conflict detection, full DAG
`state_merge` `squash` Three-way merge, single squashed commit
`state_merge` `rebase` Three-way merge, linear history

Conflict level matrix

Level How to engineer What to assert
File-level Both branches edit the same file at non-overlapping regions File contents merged correctly; neither side's changes lost
Directory-level Both branches add/delete/rename files in the same directory All additions present, deletions applied, renames resolved
Symbol-level Both branches modify the same function/class body `muse conflicts --json` lists the symbol; `muse resolve` stages correct merged body

Test phases

Phase 1 — Fixtures and helpers

TDD-first: write a `conftest.py` or `test_merge_matrix.py` with:

  • `make_conflict_repo()` — builds a repo with ours/theirs branches pre-loaded with deliberate conflicts at all three levels
  • `assert_no_work_lost()` — verifies that after merge, every change from both sides is present
  • `assert_symbol_conflict_listed()` — checks `muse conflicts --json` lists expected symbol paths
  • `assert_merge_history()` — verifies parent commit structure matches `--history` option

All helpers must fail before any implementation changes.

Phase 2 — Strategy × History matrix tests

One test per cell in the 6-cell matrix above. Each test:

  1. Creates a fresh repo with engineered conflicts
  2. Runs `muse merge <branch> --strategy <s> --history <h>`
  3. For `state_merge` with conflicts: resolves manually via `muse resolve`
  4. Commits and asserts:
    • All expected files present
    • All expected symbols present with correct bodies
    • Commit DAG structure matches history option
    • `muse verify --json` reports clean

Phase 3 — Regression tests for known failure modes

  • `--allow-empty` snapshot regression: after a merge commit with no tracked changes, the working tree must reflect both sides' content (not just ours)
  • Symbol-level conflict: after `muse resolve`, the staged file must contain the manually-merged body, not a conflict-marker blob
  • Dry-run merge: `muse merge --dry-run` must not mutate any state (working tree, MERGE_STATE, reflog)

Phase 4 — MP GUI smoke tests (optional, separate issue if scope grows)

  • `muse hub proposal read <id>` returns `blockedBy` list when predicted conflicts exist
  • `muse diff --text <from>..<to>` returns the expected diff text for the proposal view

Acceptance criteria

  • All 6 strategy × history combinations have a passing test
  • All 3 conflict levels (file, directory, symbol) are exercised
  • `--allow-empty` snapshot regression test is red before fix, green after
  • `muse verify --json` passes after every merge scenario
  • `muse code test --json` runs only these tests on changed files (no full-suite run needed)
  • Tests are TDD — written first, implementation fixed to make them pass

Out of scope

  • MP GUI conflict surfacing (separate issue)
  • `muse diff --text` in proposal view (separate issue)

Notes

  • Use `muse merge --dry-run --json` to predict conflicts before asserting
  • `muse conflicts --json` returns `[]` when no conflicts are pending
  • `muse resolve path/to/file.py --json` stages the resolution; do NOT use `muse code add`
  • Harmony autoupdate is on by default; verify it learns from each resolved conflict
Activity
gabriel opened this issue 6 days ago
No activity yet. Use the CLI to comment.