feat(worker): Handler-Session vor dem Usage-Limit warnen und Handoff bis zum Reset zurueckhalten
Eine PowerUse-Handler-Session soll am 5h-Limit nicht mehr mitten im Merge sterben, sondern vorher selbst sauber uebergeben: - HandlerUsageGuard (neu) warnt die laufende Session genau einmal pro Runde, sobald FiveHour.Utilization den Schwellwert PowerUseHandoffPct erreicht. Die Warnung wird per HandlerUsageWarning-Broadcast an Mission Control geschickt und dort in das Pane der Handler-TaskId getippt. - handoff_list_handler broadcastet den Handoff dann nicht sofort, sondern parkt ihn bis ResetsAt + 60 s; das Ergebnis traegt deferredUntil. Ohne ResetsAt wird wie bisher sofort gesendet. - Der geparkte Handoff liegt im HandlerRoundState (handler-rounds.json) und wird vom Guard-Tick ausgeloest, also auch nach einem Worker-Neustart wieder eingeplant bzw. sofort gesendet, wenn er ueberfaellig ist. - Review-Befund aus #272: HandlerRestartCoordinator wartet nicht mehr selbst bis ResetsAt, sondern parkt den Neustart im selben Slot. AutoRestartUsed wird erst gesetzt, wenn der Broadcast wirklich rausging - ein Worker-Absturz waehrend der Wartezeit laesst die Runde nicht mehr dauerhaft tot zurueck. Zurueckgehaltener Handoff und Auto-Neustart teilen sich einen Slot, also oeffnet nie beides dieselbe Runde. UsageLimitProofPct entfaellt zugunsten von PowerUseHandoffPct. - PtyTerminalSession.SendLineAsync schreibt in die laufende Session. Gegen eine echte claude-Session verifiziert: Text und Enter muessen zwei getrennte Writes sein, die Enter-Bytes kommen von Terminal.GenerateKeyInput.
This commit is contained in:
@@ -37,6 +37,12 @@ public sealed class HubBroadcaster : IPrimeBroadcaster, IRefineBroadcaster
|
||||
public Task HandoffRequested(string taskId, IReadOnlyList<string> survivingTaskIds, string nextPhase) =>
|
||||
_hub.Clients.All.SendAsync("HandoffRequested", taskId, survivingTaskIds, nextPhase);
|
||||
|
||||
// The 5h usage window is about to run out under a running list-handler session (HandlerUsageGuard).
|
||||
// Mission Control types `message` straight into that task's ConPTY pane, so the session can hand
|
||||
// off cleanly instead of dying mid-merge. No pane for the task = nothing happens.
|
||||
public Task HandlerUsageWarning(string handlerTaskId, string message) =>
|
||||
_hub.Clients.All.SendAsync("HandlerUsageWarning", handlerTaskId, message);
|
||||
|
||||
/// <summary>An agent wrote a note through MCP — the open notes editor reloads.</summary>
|
||||
public Task NotesUpdated() =>
|
||||
_hub.Clients.All.SendAsync("NotesUpdated");
|
||||
|
||||
Reference in New Issue
Block a user