| 703 | } |
| 704 | |
| 705 | function nextTaskKey(tasks: readonly Task[], parent: Task | undefined): string { |
| 706 | const siblings = tasks.filter((task) => task.parentId === parent?.id); |
| 707 | const prefix = parent ? `${parent.key}.` : 'T'; |
| 708 | const used = new Set(siblings.map((task) => task.key)); |
| 709 | let index = 1; |
| 710 | while (used.has(`${prefix}${index}`)) index += 1; |
| 711 | const key = `${prefix}${index}`; |
| 712 | if (!isTaskKey(key)) |
| 713 | throw new Error( |
| 714 | `Task hierarchy is too deep to allocate a stable key under ${parent?.key ?? 'root'}`, |
| 715 | ); |
| 716 | return key; |
| 717 | } |
| 718 | |
| 719 | function assertChildTaskOwner( |
| 720 | owner: TaskOwner, |