Grossaufgaben und Sonderbudget (#717, Stufe 2+3)
Eine Aufgabe, deren eigene Schaetzung (gemessen, Geschwister oder Autor) ueber der Haelfte der Tageskostengrenze liegt, bekommt zuerst einen Planungslauf: teilen (Teile unter der Elternaufgabe) oder Sonderbudget beantragen. Danach wartet sie auf ihre Teile bzw. die Freigabe und laeuft einmal zum Zusammenfuehren. Sonderbudget ueber Escalation.request_budget, ausnahmslos freigabepflichtig (auch gegen Werkzeugkonfiguration und Dauerfreigabe). Laeufe im Baum ziehen den Topf statt der Tagesgrenzen, tragen BudgetPot in Verbrauch und Beleg und sind in der Kostenanalyse (nach Budget) und auf der Aufgabenkarte gesondert sichtbar. Aufgebraucht zaehlen sie wieder gegen den Tag. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
183e922278
commit
67649559f5
@@ -67,6 +67,9 @@ public sealed class AppHost : IAsyncDisposable
|
||||
/// <summary>#689: The desk a human decides at; <c>null</c> without a task board.</summary>
|
||||
public Core.Cases.ICaseDesk? CaseDesk => Engine?.CaseDesk;
|
||||
|
||||
/// <summary>#717: Special budgets — one pot per task tree, approved by a human.</summary>
|
||||
public Core.Budget.ISpecialBudgetRepository? SpecialBudgets { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Zustandsspeicher und Audit-Log der Instanz. Nicht oeffentlich — sie gehoeren dem
|
||||
/// Aufbau, nicht den Oberflaechen; gebraucht werden sie hier fuer die Sichtung
|
||||
@@ -548,6 +551,7 @@ public sealed class AppHost : IAsyncDisposable
|
||||
var usage = new SqliteUsageRepository(storage);
|
||||
var transcripts = new Core.Transcripts.SqliteRunTranscriptStore(storage);
|
||||
var cases = new Core.Cases.SqliteCaseRepository(storage);
|
||||
var specialBudgets = new SqliteSpecialBudgetRepository(storage);
|
||||
|
||||
// Preise fürs Budget: Ohne sie greift nur die Token-Grenze.
|
||||
var pricing = new ModelPricingCatalog();
|
||||
@@ -565,7 +569,9 @@ public sealed class AppHost : IAsyncDisposable
|
||||
TranscriptStore = transcripts,
|
||||
DefaultTranscriptRetention = () => instance.PromptHistory.RetentionDays,
|
||||
MaxDelegationDepth = instance.MaxDelegationDepth,
|
||||
DelegationGateTimeout = TimeSpan.FromSeconds(instance.DelegationGateTimeoutSeconds)
|
||||
DelegationGateTimeout = TimeSpan.FromSeconds(instance.DelegationGateTimeoutSeconds),
|
||||
// #717: runs in a funded task tree draw on its pot, not on the daily limits.
|
||||
SpecialBudgets = specialBudgets
|
||||
};
|
||||
|
||||
engine.SetAgentConfigProvider(
|
||||
@@ -607,6 +613,7 @@ public sealed class AppHost : IAsyncDisposable
|
||||
Usage = usage,
|
||||
Transcripts = transcripts,
|
||||
Cases = cases,
|
||||
SpecialBudgets = specialBudgets,
|
||||
Insights = new RunInsights(audit, transcripts, board, staging,
|
||||
agentId => instance.Agents.FirstOrDefault(a => a.AgentId == agentId) is { } agent
|
||||
? engine.TranscriptRetentionFor(agent)
|
||||
@@ -809,7 +816,12 @@ public sealed class AppHost : IAsyncDisposable
|
||||
var estimate = estimator is null ? TaskEstimate.Nothing : await estimator.EstimateAsync(task, ct);
|
||||
await board.CreateAsync(FillWorkNotice.QuestionFor(task, estimate), ct);
|
||||
},
|
||||
fillWarnBefore: () => instance.FillWork.WarnBeforeDeadline);
|
||||
fillWarnBefore: () => instance.FillWork.WarnBeforeDeadline,
|
||||
// #717: A large task is not simply started — its run proposes a split or a special budget.
|
||||
largeTaskCheck: estimator is null
|
||||
? null
|
||||
: new LargeTaskCheck(estimator, taskRepository, engine.SpecialBudgets, () => instance.Agents, () => instance.FillWork),
|
||||
noteOnTask: async (taskId, note, ct) => await board.AddCommentAsync(taskId, "system", note, ct));
|
||||
|
||||
// Reconciliation nicht blockierend: Der Start soll nicht auf das Dateisystem warten.
|
||||
_ = Task.Run(async () =>
|
||||
|
||||
Reference in New Issue
Block a user