fix(tracker): Gantt cascade — do not pull a predecessor back when its due falls on a non-working day - #11054
Merged
ArtyomSavchenko merged 1 commit intoOct 2, 2026
Conversation
…atisfied In working-days mode the reverse anchor is not the inverse of the forward anchor when the predecessor's anchor falls on a non-working day: fsAnchor(Sat) = Mon, but fsReverseAnchor(Mon) = Fri. The reverse pass of simulateCascade only compared the reverse anchor against the predecessor, so after an FS push that left a successor ending on a Saturday, the next link in the chain pulled that successor back by the calendar delta. The pulled issue then started on its own predecessor's last day, and that upstream link was never re-checked because the primary edit is guarded. Check the violation with the forward anchor (the same predicate the outgoing pass uses) before pulling. Legacy calendar-day mode is unaffected because its forward and reverse anchors are exact inverses. Tests cover the reported chain (A -> B -> C across a weekend), a successor dropped on the first working day after a Saturday-ending predecessor, a real violation that must still pull, and legacy-mode regressions. Signed-off-by: Michael Uray <michaeluray@users.noreply.github.com>
ArtyomSavchenko
approved these changes
Oct 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #10992 (Gantt chart), which introduced the scheduler code changed here.
Problem
With a working-days calendar (Mon–Fri), an FS chain can end up with a successor starting on its predecessor's last day.
Example (Mon–Fri, FS chain A → B → C):
Expected: B Fri 16 – Sat 17, C Mon 19 – Tue 20.
Actual: B Thu 15 – Fri 16 (overlaps A's last day), C Mon 19 – Tue 20.
Root cause
The reverse pass in
simulateCascadedecides whether to pull a predecessor by comparingfsReverseAnchor(successor)with the predecessor's due date. In working-days modefsReverseAnchoris not the inverse offsAnchorwhen the predecessor ends on a non-working day:fsAnchor(Sat 17) = Mon 19, butfsReverseAnchor(Mon 19) = Fri 16 < Sat 17. So C (already correctly placed on Mon 19) pulls B back by a day. B's own link to A is never re-checked, because A is the primary edit.Legacy calendar-day mode is not affected: its forward and reverse anchors are exact inverses.
Fix
Before pulling, check the violation with the forward anchor, the same check the outgoing pass uses (
fsAnchor/ssAnchor/ffAnchor/sfAnchoragainst the successor's start or due date). A predecessor is pulled only if the constraint is actually violated. How far it gets pulled is unchanged.Tests
scheduler-cascade.test.ts:pull-predecessor); a successor dropped on the first working day after a Saturday-ending predecessor givesno-cascade; a real violation (successor on the predecessor's Friday) still pulls the predecessor to Wed 14 – Thu 15.pull-predecessor; existing pull behaviour is unchanged.All gantt suites in
plugins/tracker-resourcesandpackages/ganttpass.Out of scope: snapping drags to working days, and working-day durations for cascaded successors.