fix(core): restore must rewrite statePayload.runtime.handle, not just top-level
Restore was writing the freshly-spawned runtime handle to the top-level metadata `runtimeHandle` key, but the canonical lifecycle parser prefers `statePayload.runtime.handle` and falls back to the top-level only when statePayload is missing. The next lifecycle tick read the stale handle from statePayload and rewrote both keys from it, silently undoing the restore's update. Symptom: a session restored after AO restart kept the old PID in metadata. Lifecycle probe found that PID dead (it was from a previous boot) and the dashboard rendered the orchestrator as exited/killed even though a new process was actually running. Fix: rebuild the canonical lifecycle with the new handle via buildUpdatedLifecycle() and persist via lifecycleMetadataUpdates() so statePayload and runtimeHandle stay in sync. Mirrors the pattern used in kill/spawn paths. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d16d3c3f4d
commit
24eefda23b
|
|
@ -2876,11 +2876,23 @@ export function createSessionManager(deps: SessionManagerDeps): OpenCodeSessionM
|
|||
},
|
||||
});
|
||||
|
||||
// 9. Update metadata — merge updates, preserving existing fields
|
||||
// 9. Update metadata — merge updates, preserving existing fields.
|
||||
//
|
||||
// We must update both the top-level `runtimeHandle` AND the nested
|
||||
// `runtime.handle` inside `statePayload`. The lifecycle parser prefers
|
||||
// the statePayload over top-level keys, so writing only the top-level
|
||||
// key gets silently clobbered by the next lifecycle tick (which reads
|
||||
// statePayload and rewrites the top-level field from it). Rebuilding
|
||||
// the canonical lifecycle with the fresh handle keeps both in sync.
|
||||
const now = new Date().toISOString();
|
||||
const updatedLifecycle = buildUpdatedLifecycle(sessionId, raw, (lifecycle) => {
|
||||
lifecycle.runtime.handle = handle;
|
||||
lifecycle.runtime.tmuxName = tmuxName ?? lifecycle.runtime.tmuxName;
|
||||
lifecycle.runtime.lastObservedAt = now;
|
||||
});
|
||||
updateMetadata(sessionsDir, sessionId, {
|
||||
...lifecycleMetadataUpdates(raw, updatedLifecycle),
|
||||
status: "spawning",
|
||||
runtimeHandle: JSON.stringify(handle),
|
||||
restoredAt: now,
|
||||
});
|
||||
invalidateCache();
|
||||
|
|
|
|||
Loading…
Reference in New Issue