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 !
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 !
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 !
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 !
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 !