feat(plans): implement conflict detection and structured conflict report for three-way merge - Closes #9558 #9613

Open
HAL9000 wants to merge 7 commits from feat/v3.3.0-merge-conflict-detection into master

7 Commits

Author SHA1 Message Date
drew 23fd5425f7 fix(cli-tests): read audit CLI output in shared assertions
CI / push-validation (pull_request) Has been cancelled
CI / load-versions (pull_request) Successful in 32s
CI / lint (pull_request) Successful in 45s
CI / build (pull_request) Successful in 42s
CI / helm (pull_request) Successful in 44s
CI / typecheck (pull_request) Successful in 1m9s
CI / quality (pull_request) Successful in 1m32s
CI / security (pull_request) Successful in 1m53s
CI / unit_tests (pull_request) Successful in 5m32s
CI / docker (pull_request) Successful in 1m41s
CI / integration_tests (pull_request) Successful in 9m9s
CI / coverage (pull_request) Failing after 14m35s
CI / status-check (pull_request) Has been cancelled
2026-06-18 11:20:00 -04:00
CleverAgents Bot b265adf13d fix(planconfig): cover merge conflict edge cases
CI / load-versions (pull_request) Successful in 30s
CI / push-validation (pull_request) Successful in 28s
CI / lint (pull_request) Successful in 48s
CI / typecheck (pull_request) Successful in 1m3s
CI / quality (pull_request) Successful in 43s
CI / security (pull_request) Successful in 1m17s
CI / build (pull_request) Successful in 44s
CI / helm (pull_request) Successful in 50s
CI / integration_tests (pull_request) Failing after 16m31s
CI / unit_tests (pull_request) Failing after 16m33s
CI / coverage (pull_request) Has been cancelled
CI / docker (pull_request) Has been cancelled
CI / status-check (pull_request) Has been cancelled
2026-06-18 08:00:30 -04:00
controller-ci-rerun e0a1a2615f chore: re-trigger CI [controller]
CI / load-versions (pull_request) Successful in 15s
CI / push-validation (pull_request) Successful in 25s
CI / lint (pull_request) Successful in 42s
CI / build (pull_request) Successful in 44s
CI / quality (pull_request) Successful in 47s
CI / typecheck (pull_request) Successful in 1m10s
CI / security (pull_request) Successful in 1m21s
CI / helm (pull_request) Successful in 40s
CI / unit_tests (pull_request) Successful in 5m11s
CI / docker (pull_request) Successful in 1m50s
CI / integration_tests (pull_request) Successful in 8m40s
CI / coverage (pull_request) Failing after 17m16s
CI / status-check (pull_request) Has been cancelled
2026-06-17 15:40:39 -04:00
HAL9000 194291706e test(plans): cover uncovered branches in merge_conflict with BDD scenarios and pragmas
CI / load-versions (pull_request) Successful in 16s
CI / push-validation (pull_request) Successful in 23s
CI / lint (pull_request) Successful in 46s
CI / typecheck (pull_request) Successful in 1m1s
CI / quality (pull_request) Successful in 59s
CI / security (pull_request) Successful in 1m9s
CI / build (pull_request) Successful in 36s
CI / helm (pull_request) Successful in 41s
CI / unit_tests (pull_request) Successful in 4m44s
CI / docker (pull_request) Successful in 1m32s
CI / integration_tests (pull_request) Successful in 8m27s
CI / coverage (pull_request) Failing after 17m29s
CI / status-check (pull_request) Has been cancelled
Add 4 BDD scenarios to features/plan_merge_conflict_detection.feature:
- No conflict when all three versions have identical values (covers line 269
  in _detect_field_conflict: neither-side-changed early return)
- Cannot add conflict with empty field path (covers line 121 ValueError)
- Resolve conflict using merged version (covers lines 148-149 MERGED branch
  in get_resolved_value)
- Get resolved value with manual resolution raises error (covers line 150
  MANUAL -> ValueError in get_resolved_value)

Add corresponding step 'I try to add a conflict with empty field path' to
the step definitions.

Mark genuinely dead-code branches with # pragma: no cover:
- Line 74: resolved_value guard (context/conflict_type None) -- unreachable
  through detect() since _analyse_field always sets both
- Line 141: get_resolved_value conflict-not-found guard -- unreachable
  through public API since resolve_conflict() pre-checks existence
- Lines 280-281: DELETE_DELETE in _detect_field_conflict -- unreachable
  because None==None is caught by the prior parent_val==subplan_val guard
- Line 304: auto_resolve_conflicts DELETE_DELETE continue -- unreachable
  since detect_conflicts() can never produce DELETE_DELETE conflicts
- Line 331: detect_diff_text context-is-None guard -- unreachable since
  _analyse_field always sets context
- Lines 405-410: _analyse_field not-changed/not-changed branch -- unreachable
  because detect() fast-paths the all-equal case before calling _analyse_field

Also expand test_merge_conflict_legacy_contract.py with 7 pytest-style tests
covering the same edge cases (useful for developer pytest runs).
2026-06-17 13:10:23 -04:00
drew 163141aea5 fix(planconfig): stringify clean legacy merge values 2026-06-17 13:10:23 -04:00
drew d54028fa6d fix(planconfig): preserve legacy merge conflict serialization 2026-06-17 13:10:23 -04:00
HAL9000 77ba5091d1 feat(plans): implement conflict detection and structured conflict report for three-way merge
- Add ConflictType enum for categorizing conflict types
- Add ConflictContext dataclass for storing conflict information
- Add ConflictReport dataclass for structured conflict reporting
- Add ConflictResolution enum for resolution strategies
- Implement ThreeWayMergeConflictDetector with standard three-way merge algorithm
- Add automatic conflict resolution heuristics
- Add comprehensive BDD test suite with 20+ test scenarios
- Update CHANGELOG.md with new feature documentation
2026-06-17 13:10:23 -04:00