feat(claude-do): depends_on als Menge statt Einzelfeld
Ein Task kann jetzt auf beliebig viele Vorgaenger warten. Die Einzelspalte tasks.depends_on_task_id wird durch die Beziehungstabelle task_dependencies ersetzt (Composite-PK, beide FKs ON DELETE CASCADE -- das reproduziert das alte ON DELETE SET NULL: geloeschter Vorgaenger = Kante weg = Task wieder pickbar). BlockedByTaskId bleibt unberuehrt. - Migration AddTaskDependencies kopiert jede bestehende depends_on_task_id verlustfrei in die Tabelle, bevor die Spalte fallengelassen wird - QueuePicker gatet per doppelt negiertem NOT EXISTS: kein Task mit 0 Kanten wird blockiert, alle Kanten muessen done sein, eine Kante auf einen verschwundenen Task blockiert weiter - SetDependsOnAsync ersetzt die ganze Menge; Zykluspruefung ist jetzt eine BFS ueber den Graphen, faengt also auch A->B->C->A - blockedReason nennt alle offenen Vorgaenger (External/TaskBlocking, von ExternalMcpService und TaskWaitMcpTools gemeinsam genutzt) - add_task/update_task nehmen dependsOnTaskIds; die alte Skalarform bleibt als Ein-Element-Menge inkl. ""-Clear-Sentinel gueltig - UI: Fan-in-Zeile bleibt flach und listet alle Vorgaenger im After-Label, die lineare Kette rendert unveraendert
This commit is contained in:
@@ -113,7 +113,14 @@ public sealed partial class TaskRowViewModel : ViewModelBase
|
||||
[NotifyPropertyChangedFor(nameof(IsWaiting))]
|
||||
[NotifyPropertyChangedFor(nameof(StatusChipClass))]
|
||||
private string? _blockedByTaskId;
|
||||
[ObservableProperty] private string? _dependsOnTaskId;
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(DependsOnTaskId))]
|
||||
private IReadOnlyList<string> _dependsOnTaskIds = [];
|
||||
|
||||
// The single predecessor, or null when the task has none or several. The chain rail can only
|
||||
// draw a line, so a task waiting on n predecessors gets a ChainAfterLabel instead — see
|
||||
// TasksIslandViewModel.ApplyChainGrouping.
|
||||
public string? DependsOnTaskId => DependsOnTaskIds.Count == 1 ? DependsOnTaskIds[0] : null;
|
||||
[ObservableProperty] private bool _isExpanded = true;
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(IsPlanningParent))]
|
||||
@@ -488,7 +495,10 @@ public sealed partial class TaskRowViewModel : ViewModelBase
|
||||
ParentTaskId = t.ParentTaskId;
|
||||
CreatedBy = t.CreatedBy;
|
||||
BlockedByTaskId = t.BlockedByTaskId;
|
||||
DependsOnTaskId = t.DependsOnTaskId;
|
||||
// Guarded: TaskEntity.DependsOnTaskIds projects a fresh List every read, so a plain
|
||||
// assignment would fire PropertyChanged on every reconcile tick even when nothing moved.
|
||||
var deps = t.DependsOnTaskIds;
|
||||
if (!DependsOnTaskIds.SequenceEqual(deps)) DependsOnTaskIds = deps;
|
||||
RoadblockCount = t.RoadblockCount;
|
||||
FailureReason = t.FailureReason;
|
||||
FailureTurnsUsed = t.FailureTurnsUsed;
|
||||
|
||||
Reference in New Issue
Block a user