# ADR-0002: Use float sort_order for drag-and-drop ordering ## Status accepted ## Context The planning screens (PBI list, Story list, Task list, Solo board) all support drag-and-drop reordering. With integer positions, inserting an item between positions 3 and 4 requires renumbering every subsequent row — an O(N) write for every drag operation. At the scale of a sprint board this is tolerable, but it causes unnecessary lock contention and makes optimistic UI rollback harder. See `docs/patterns/sort-order.md` for the full implementation pattern. ## Decision Every ordered collection uses a `Float` column named `sort_order`. Inserting between two items sets `sort_order = (prev + next) / 2`. New items appended to the end get `last + 1.0`. ## Consequences ### Positive - Reorder writes are O(1) — only the moved item's row is updated. - Optimistic UI updates map directly to the same midpoint calculation. - No lock contention on adjacent rows during concurrent drags. ### Negative - Repeated insertions between the same two items cause float precision drift. Mitigation: a periodic compaction job normalizes `sort_order` values to integers × 1000 when the gap drops below `0.001`. This is a known trade-off; compaction has not been needed in practice yet. - Queries that return items in `sort_order` order must always include `ORDER BY sort_order` — there is no implicit ordering.