# V3-10 — Trip splitting **Phase** Ride management · **Depends on** nothing · **Size** S · **Status** Not started ## Goal Split one recorded ride into two at a chosen point. The natural counterpart to merge. ## Context Merge exists and is well tested; split does not. The case is a rider who forgot to stop — one "ride" that is really the trip out, lunch, and the trip home. Merge already establishes the hard parts: re-parenting points and segments inside a transaction, and recomputing aggregates rather than summing them. ## Design Split at a **segment boundary** rather than an arbitrary point. Segments already mark where the rider paused, which is exactly where a forgotten stop shows up — and it avoids inventing a new boundary type or splitting a segment in half. The original trip keeps the earlier segments; a new trip takes the later ones. Both get aggregates recomputed from the points they actually own. If a ride has only one segment there is nothing to split, and the UI should say so rather than offering a dead control. ## Implementation 1. `TripRepository.splitTrip(tripId, atSegmentId)` inside a transaction: create the new trip, re-parent segments and points from `atSegmentId` onward, set `startedAt`/`endedAt` from the segments each trip now owns, recompute aggregates for both 2. Trip detail: a split action listing segment boundaries with their times 3. Confirmation naming what the two resulting rides will be ## Acceptance criteria - [ ] Splitting produces two trips whose point counts sum to the original - [ ] Neither trip's distance includes the gap between them - [ ] Both have plausible `startedAt`/`endedAt` - [ ] Single-segment rides cannot be split, and the UI explains why - [ ] Atomic — a failure part-way leaves the original intact ## Tests - Point counts sum; no points orphaned - Distance of the parts is less than the original by roughly the gap - Split then merge returns to the original aggregates — a good round-trip property - Rejects a single-segment trip - Atomicity under a forced mid-transaction failure ## Risks Getting `startedAt`/`endedAt` from the wrong source. Derive them from the segments each trip owns, not from the original trip. ## Out of scope Splitting mid-segment.