mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-05 15:09:42 +02:00
fix(reboot-restore): the merge-time items from the #442 review
Seven things, none of which changes what the feature does. 1. The rebuilt Session dropped `nameSource`, so the constructor re-inferred it from the name: a session the user renamed by hand to something shaped like `w<n>-<case>` came back as `placeholder`, and with auto-naming on the next prompt overwrote their name. The route persists right after, so the loss went to disk. `restoreMuxSessions()` already passes it. 2. The already-live sets were snapshotted once before a loop that awaits a real `startInteractive()` per entry, so by the tenth entry the snapshot was tens of seconds old and a conversation resumed by hand from the Resume list in that window was invisible to it: two panes on one transcript, the exact thing the check exists to prevent. Both sets are now read per iteration, and the late case is spent rather than re-offered for the same reason the batch case is. 3. Auto-resume no longer re-arms the pre-reboot `autoResumeAt` on this path. The stamp predates the reboot and the pane is new, so honouring it meant one click had every restored session type `continue` into itself about a minute later, unattended, against the route header's own promise that a restored session comes back idle and disarmed. The setting stays ENABLED, so it re-arms on the next real limit message. A Codeman restart still re-arms from the stamp, because the limit footer will not reprint on its own; the new option exists only to tell the two paths apart. 4. `discardPartiallyBuiltSession()` now also calls `recordSessionStopped()` and `ralphTracker.fullReset()`, the two teardown steps `_doCleanupSession` performs that it was missing. Cosmetic, but a run left open reads as still going in the away digest. 5. A restored claude session gets `seedAgentSessionPreamble()` like both create paths, so the agent skill's bootstrap stays a two-line loader. 6. The heuristic's container comment was wrong in one direction and quiet about the real gap: after a genuine host reboot a containerized Codeman sees the host's short uptime and the banner does appear. What it cannot see is a container-only restart, which is where this would help most. 7. The banner is hidden in a solo window, which shows one session and has no tab strip to put restored ones in. Also reverts 17 of the 18 hunks in docs/api-reference.md, which were Prettier reformatting of prose the PR does not otherwise touch (docs/ is outside the format glob), keeping only the Reboot restore section and repairing the two continuation lines that reformat de-indented; renumbers reboot-restore-ui.js to @loadorder 11.65, since 11.7 is admin-ui.js, which loads after it; and gives the feature its CLAUDE.md entry plus a route test for the multi-user workspace-forbidden branch, the only new rule that had nothing behind it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+19
-2
@@ -2940,7 +2940,8 @@ export class WebServer extends EventEmitter {
|
||||
async reapplyPersistedSessionState(
|
||||
session: Session,
|
||||
saved: SessionState,
|
||||
phase: 'before-spawn' | 'after-spawn'
|
||||
phase: 'before-spawn' | 'after-spawn',
|
||||
options?: { rearmAutoResumeSchedule?: boolean }
|
||||
): Promise<void> {
|
||||
if (phase === 'before-spawn') {
|
||||
// The custom-model env has to be rebuilt from the endpoint store: the persist
|
||||
@@ -2968,7 +2969,14 @@ export class WebServer extends EventEmitter {
|
||||
session.setAutoClear(saved.autoClearEnabled ?? false, saved.autoClearThreshold);
|
||||
}
|
||||
if (saved.autoResumeEnabled) {
|
||||
session.restoreAutoResume(true, saved.autoResumeAt);
|
||||
// The stamp is re-armed by default, because a Codeman restart leaves the
|
||||
// limit footer un-reprinted and dropping it there would strand the pause.
|
||||
// A reboot restore opts out: that stamp predates the reboot, the pane is
|
||||
// new, and honouring it means every session the user restored types
|
||||
// `continue` into itself about a minute later, unattended. The setting
|
||||
// itself stays on either way, so it re-arms on the next limit message.
|
||||
const rearm = options?.rearmAutoResumeSchedule !== false;
|
||||
session.restoreAutoResume(true, rearm ? saved.autoResumeAt : undefined);
|
||||
}
|
||||
if (saved.inputTokens !== undefined || saved.outputTokens !== undefined || saved.totalCost !== undefined) {
|
||||
session.restoreTokens(saved.inputTokens ?? 0, saved.outputTokens ?? 0, saved.totalCost ?? 0);
|
||||
@@ -3024,9 +3032,18 @@ export class WebServer extends EventEmitter {
|
||||
session.ralphTracker.stopWatchingFixPlan();
|
||||
const summaryTracker = this.runSummaryTrackers.get(sessionId);
|
||||
if (summaryTracker) {
|
||||
// Closes the run's own record before the tracker goes, the way
|
||||
// `_doCleanupSession()` does. Cosmetic rather than load-bearing, but a
|
||||
// run left open reads as still going in the away digest.
|
||||
summaryTracker.recordSessionStopped();
|
||||
summaryTracker.stop();
|
||||
this.runSummaryTrackers.delete(sessionId);
|
||||
}
|
||||
// Also mirrors `_doCleanupSession()`. The PERSISTED Ralph state is left
|
||||
// alone on purpose (that is one of the things separating this from
|
||||
// cleanupSession); this only clears the in-memory tracker the failed
|
||||
// construction built, which the retry reuses the id of.
|
||||
session.ralphTracker.fullReset();
|
||||
|
||||
// --- what anything else may have attached to this id in the meantime ---
|
||||
// A rebuild can fail AFTER startInteractive() resolved, and a restored
|
||||
|
||||
Reference in New Issue
Block a user