diff --git a/cmd/nomos/continue.go b/cmd/nomos/continue.go index 072cf74..ac532b7 100644 --- a/cmd/nomos/continue.go +++ b/cmd/nomos/continue.go @@ -176,6 +176,21 @@ func (a *agent) resumeSession(ctx context.Context, sessionID, note string) { if errText != "" && finalText == "" { slog.Error("nomos: resume produced no response after retry", "session", sessionID, "error", errText) + // Give the task a real, operator-visible terminal state instead of + // leaving it silently stuck at whatever status it was in (typically + // 'executing' or 'awaiting_input') forever. Before this, a + // permanently-failed resume was invisible beyond a log line — the + // task board just showed a task that never changed, with nothing + // telling the operator it needed attention. Marking it failed here + // doesn't prevent the operator from continuing to work the task via + // a fresh chat message afterward; it just stops the silent hang. + summary := fmt.Sprintf("Auto-resume failed after retrying: %s", errText) + if len(summary) > 200 { + summary = summary[:200] + "…" + } + if cerr := a.store.completeTask(context.Background(), sessionID, "failure", summary); cerr != nil { + slog.Error("nomos: failed to mark task failed after resume gave up", "session", sessionID, "error", cerr) + } } persist() // final state — same row, updated one last time with the concluding text }