From the Codex review of PR #3019 (issue #2926) at head fa62b03d04b6da287d6cca5f2e57b713a47d56c2 (inline comment 3992872287, P2). Source-traced, not runtime-reproduced. Non-blocking: the outcome is the pre-existing "approve passes, apply fails and rolls back" shape, never an over-limit column, and the underlying defect predates #3019.
Defect (pre-existing, Apply side)
When a proposal move targets a column whose card positions are non-contiguous (for example positions 0 and 2 after a middle card was deleted, or sparse positions from an import), OperationHandlerRegistry computes the append position as max+1 (3) and CardService.MoveCardAsync calls Insert(3, ...) on a two-item list, which throws. The proposal rolls back at execution.
Interaction with #3019
The preview projection treats such a move as executable and releases its source slot, so a following restore can pass approval on capacity the failed move never frees. Disposition is unchanged (the proposal cannot apply either way); only the failure moves from approve-time to apply-time for that combination.
Acceptance
- Make the executor append by list count (or normalise positions before insert) so a move into a sparse column succeeds; regression with positions 0 and 2.
- Alternatively, or additionally, have the preview validator refuse a move whose append position is invalid, keeping the source occupancy.
- Preview/apply parity test for the sparse-column move plus restore combination.
Related: #3020 (preview does not WIP-check create/move themselves), #3012 (conflict-detector projection omits lifecycle effects).
From the Codex review of PR #3019 (issue #2926) at head
fa62b03d04b6da287d6cca5f2e57b713a47d56c2(inline comment 3992872287, P2). Source-traced, not runtime-reproduced. Non-blocking: the outcome is the pre-existing "approve passes, apply fails and rolls back" shape, never an over-limit column, and the underlying defect predates #3019.Defect (pre-existing, Apply side)
When a proposal
movetargets a column whose card positions are non-contiguous (for example positions 0 and 2 after a middle card was deleted, or sparse positions from an import),OperationHandlerRegistrycomputes the append position as max+1 (3) andCardService.MoveCardAsynccallsInsert(3, ...)on a two-item list, which throws. The proposal rolls back at execution.Interaction with #3019
The preview projection treats such a move as executable and releases its source slot, so a following restore can pass approval on capacity the failed move never frees. Disposition is unchanged (the proposal cannot apply either way); only the failure moves from approve-time to apply-time for that combination.
Acceptance
Related: #3020 (preview does not WIP-check create/move themselves), #3012 (conflict-detector projection omits lifecycle effects).