Fuellarbeit: zeitlich flexible Arbeit fuellt ungenutztes Budget (#717, Stufe 1)

Eine einmalige Aufgabe mit fill_by (spaetestens bis) statt Termin laeuft,
wenn der Tag Budget uebrig laesst: nach regulaerer und nachgeholter Arbeit,
nur wenn nichts vom Agenten wartet, bevorzugt ab 18 Uhr, und nur wenn ihre
eigene Schaetzung in den Spielraum aus #716 passt. Kurz vor der Frist wird
einmal ein Mensch gefragt; nach der Frist laeuft sie als regulaere Arbeit.

Ehrliche Schaetzung (TaskCostEstimator): eigene Laeufe, dann Geschwister
unter derselben Elternaufgabe, dann die Angabe des Autors (als Schaetzung
gekennzeichnet), zuletzt das Mittel des Agenten.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-09-25 15:34:15 +02:00
co-authored by Claude Opus 5.5
parent 25f74d9ad6
commit 183e922278
21 changed files with 1185 additions and 36 deletions
+25
View File
@@ -252,6 +252,31 @@ public sealed record TaskItem
/// <summary>#697: The task that run was working on, if any — the task this one arose from.</summary>
public string OriginTaskId { get; init; } = "";
// ─── Fill work and estimates (#717) ───
/// <summary>
/// #717: Fill work — "at the latest by" instead of an appointment (UTC). The task runs when
/// the day's budget has room that would otherwise lapse, and before this point at the
/// latest. Only for one-time tasks; a recurring task has its appointments.
/// </summary>
public DateTime? FillBy { get; init; }
/// <summary>
/// #717: What the task's author expects one run to cost, in USD — a guess, and marked as
/// one. Used only while there is nothing measured: the task's own runs, or those of its
/// siblings, replace it (see <see cref="Budget.TaskCostEstimator"/>).
/// </summary>
public decimal? EstimateUsd { get; init; }
/// <summary>
/// #717: When a human was asked because the fill work found no room before its deadline.
/// Asked once; execution state, not part of the file.
/// </summary>
public DateTime? FillAlertedAt { get; init; }
/// <summary>#717: One-time work with a deadline instead of an appointment.</summary>
public bool IsFillWork => FillBy is not null && !IsRecurring;
/// <summary>A one-time task that was refused for lack of budget and carried over.</summary>
public bool IsCarriedOver => !IsRecurring && BudgetMissCount > 0;