5 Commits
Author SHA1 Message Date
Lauri Ojansivu acb2c0786a Resolve a rule's later move, sort, move-all and archive on the board its card went to.
As decided on 2026-10-03, after a rule moved its card to another board, a
later action that names the rule's own board works where the card is now,
in the ordinary engine and in durable Sync alike:

- RulesHelper.ruleBoards gives the board the card is on and the board an
  action works on. A move to the top or bottom, a sort and a move-all
  resolve their list and swimlane names there; the write-access check
  covers that board. Before this, a move to "*" after a move to another
  board took the card's new list and swimlane but the old board, leaving
  the card split across two boards.
- The durable move, sort, move-all and archive commands find the card
  through ruleCardNow and save the board it is on as `onBoard`, written
  only when it is not the plan's, so every command saved before still
  validates; the archive's cascade takes the children on that board.
- These actions may now follow a move to another board, so such a plan
  stays durable. An email still may not, nor a second move to yet another
  board.

The archive reservation and follower guards follow the decision; the
cross-board move test now expects sorting and archiving to follow and
refuses an email instead, and a new server test runs the whole chain
durably and with the ordinary engine on a twin card, with the same result.

Thanks to xet7 !
2026-10-03 09:44:45 +03:00
Lauri Ojansivu 9cc42caac9 Make rule moves to another list or swimlane, and move-all, durable on the card's own board.
The rule stage's guard now accepts the card where a saved move of the
SAME rule plan put it (maintainer decision of 2026-10-02), so the rule's
later actions act on the moved card once. Each move is a saved command
with Card.move's effects: the update, the position History row, the
legacy undo row, the attachments' placement and the moveCard activity.
moveAllCardsInList saves one unit per card. Moves, copies and links to
another board stay on the direct path.

Thanks to xet7 !
2026-10-02 17:53:05 +03:00
Lauri Ojansivu 044454e6d0 Run the linkCard rule action through durable Sync on the card's own board.
A linkCard rule that links onto the card's own board now has a saved
command: the linked card is built once as Card.link builds it (a copy
without id and labels, of type cardType-linkedCard pointing at the
original), under an id derived from the rule invocation so a replay
inserts it once, and its creation activity is saved and delivered
durably. The target is resolved by RulesHelper.linkCardTarget, which the
ordinary action now uses too. A link to another board keeps the board
on direct Sync.

Thanks to xet7 !
2026-10-02 17:11:47 +03:00
Lauri Ojansivu 22311feaf4 Run the copyCard rule action through durable Sync on the card's own board.
A copyCard rule that copies onto the card's own board now has a saved
command. What the copy contains is decided once, with the ordinary
copy's own helpers: the card as Card.copy builds it (the custom fields
the actor may read, its dependencies on the board, its Scrum metadata,
a new card number, the bottom of the list), its live attachments, its
checklists and items, its subtasks with their checklists, and its
comments. Every document gets an id derived from the rule invocation,
so a replay inserts each once. The copy's and its subtasks' creation
activities are saved and delivered durably; each attachment file is
copied once (copyFile can now be given the id) and its History row is
written from the stored attachment; checklists, items and comments are
direct inserts, as Card.copy makes them. The cover is remapped to the
copied attachment by its derived id. Like the ordinary copy chain
guard, a copy whose own creation triggers the same action is not copied
again. A copy to another board keeps the board on direct Sync.

The server test copies a card with all of those, replays it, checks the
chain guard, and compares the result with the ordinary Card.copy.

Thanks to xet7 !
2026-10-02 17:09:16 +03:00
Lauri Ojansivu b3b4962414 Run rule moves to the top or bottom of the card's own list through durable Sync.
A moveCardToTop or moveCardToBottom rule whose list and swimlane are '*'
on the card's own board only changes the card's sort. It now has a saved
command, like the card-field actions: the sort is computed once at
capture as the ordinary action computes it, the write is conditional on
the saved sort, the hook's position History row is planned and written
once, and the legacy UserPositionHistory row that Ctrl+Z reads is
written once with trackChange's redo-stack clearing. Replays apply the
saved command and change nothing more.

A move to another list, swimlane or board is reported to eligibility as
'<type>:elsewhere', so a board with such a rule keeps direct Sync.

Thanks to xet7 !
2026-10-02 15:34:18 +03:00