namespace ClawdDotNet.Core.Tasks; /// /// Der Ausführungszustand des Taskboards. Die Definition der Aufgaben lebt in /// Markdown-Dateien; dieses Repository ist die DB-Seite, die das Claiming atomar macht /// (was ein Dateisystem nicht verlässlich kann) und dem Scanner erlaubt, ohne /// Dateizugriff zu entscheiden. /// public interface ITaskRepository { /// /// Legt eine Aufgabe an oder aktualisiert ihre Definition (Importer). Idempotent über /// die — ein zweiter Import erzeugt keine Dublette. Der /// Ausführungszustand (Marker, Claim) bleibt dabei unangetastet. /// Task UpsertAsync(TaskItem task, CancellationToken ct); Task GetAsync(string id, CancellationToken ct); Task> ListAsync(TaskQuery query, CancellationToken ct); /// /// #682: Every task in status todo — the scanner's candidates, without a cap. /// /// clamps to 500 because it serves views and tools. The /// scanner used it too, so beyond 500 tasks schedules silently fell out of the tick. /// Only todo can be claimed, so this list is bounded by the work that is /// actually waiting, not by the size of the board. /// Task> ListRunnableAsync(CancellationToken ct); /// /// Every task, without a cap — for the few callers that must see the whole board: the /// cost forecast, duplicate detection, the import's orphan sweep. Before #716 they used /// with its limit of 500 and silently saw only part of it. /// Task> ListAllAsync(bool includeArchived, CancellationToken ct); /// /// Beansprucht einen fälligen Termin atomar. Genau ein gleichzeitiger Aufruf gewinnt; /// jeder weitere erhält false. Setzt den Marker () /// sofort — ein Termin ist damit auch dann verbraucht, wenn der Lauf später scheitert /// oder der Prozess abstürzt (at-most-once, kein Retry-Sturm). /// /// Sortierbarer ISO-UTC-Zeitstempel des Termins. /// /// Claims, die älter sind, gelten als verwaist (abgestürzter Lauf) und dürfen /// überschrieben werden. /// Task TryClaimAsync( string id, string occurrenceKey, string claimToken, DateTime now, DateTime leaseCutoff, CancellationToken ct); /// /// Schließt einen beanspruchten Lauf ab und setzt den Endstatus. Nur wirksam, solange /// der Aufrufer den Claim noch hält ( passt) — ein Lauf, /// der seine Lease verloren hat, überschreibt nichts mehr. Gibt zurück, ob der Claim /// noch gehörte. /// Task CompleteClaimAsync( string id, string claimToken, TaskItemStatus finalStatus, DateTime now, CancellationToken ct); /// /// Gibt einen Claim zurück, als hätte es ihn nicht gegeben: Status todo und der /// Marker auf (#643). Für Läufe, die gar nicht /// stattfanden. Nur wirksam, solange der Aufrufer den Claim hält. /// Task ReleaseClaimAsync( string id, string claimToken, string? previousOccurrence, DateTime now, CancellationToken ct); /// Ändert den Status direkt (Tool-Aktionen, Auto-Dispatch, Eskalation). Task SetStatusAsync(string id, TaskItemStatus status, DateTime now, CancellationToken ct); /// /// #716: The budget refused a run of a one-time task. Releases the claim, restores the /// occurrence (the task is still due) and defers it to . /// Task CarryOverAsync( string id, string claimToken, string? previousOccurrence, DateTime deferredUntil, DateTime now, CancellationToken ct); /// /// #716: The budget refused a run of a recurring task. Releases the claim back to /// todo; the occurrence stays consumed. With a /// single catch-up run is scheduled for then — an already pending one is kept. /// Task RecordBudgetMissAsync( string id, string claimToken, DateTime? catchUpUntil, DateTime now, CancellationToken ct); /// /// #716: A run took place — clears the miss counter, a pending catch-up and the /// deferral. stays as history. /// Task ClearBudgetMissAsync(string id, DateTime now, CancellationToken ct); /// /// Reconciliation beim Start: verwaiste Claims (älter als ) /// lösen und die betroffenen Aufgaben von zurück /// auf stellen. Gibt die Zahl der zurückgesetzten /// Aufgaben zurück. /// Task ReleaseStaleClaimsAsync(DateTime leaseCutoff, DateTime now, CancellationToken ct); /// /// Aufgaben, die auf warten — Grundlage für den /// Auto-Dispatch, wenn der letzte Blocker fertig wird. /// Task> ListBlockedByAsync(string blockerId, CancellationToken ct); Task CountAsync(CancellationToken ct); }