Persist merge intent so a restart mid-merge-turn doesn't lose it

This commit is contained in:
Ian Gulliver
2026-10-15 10:16:32 -07:00
parent 184bfe429e
commit c934b00737
6 changed files with 106 additions and 20 deletions
+6 -4
View File
@@ -51,7 +51,6 @@ type Manager struct {
live map[string]*live
closing bool
rateLimits map[api.AgentSessionVendor]map[string]any
merges map[string]string
leadAnswered map[string]bool
paneFocused map[string]bool
@@ -99,7 +98,6 @@ func New(st *store.Store, limits Limits, worktreeRoot, leadRoot string) *Manager
leadRoot: leadRoot,
live: map[string]*live{},
rateLimits: map[api.AgentSessionVendor]map[string]any{},
merges: map[string]string{},
leadAnswered: map[string]bool{},
paneFocused: map[string]bool{},
signals: make(chan api.Event, 1024),
@@ -281,6 +279,9 @@ func (m *Manager) Recover(ctx context.Context) error {
if err != nil {
return err
}
if sess.Owner == "" {
m.takeMerge(task.Id)
}
continue
}
@@ -699,6 +700,7 @@ func (m *Manager) pump(l *live) {
slog.Error("record session exit", "session", l.id, "err", err)
}
if l.owner == "" {
m.takeMerge(l.taskID)
m.fileError(l, "The agent process exited mid-turn. Send a message to resume it.")
}
@@ -823,8 +825,8 @@ func (m *Manager) handle(ctx context.Context, l *live, ev claude.Event) error {
go m.continueFromHandoff(l.id, res.Result)
return nil
}
mergeBy, merging := m.takeMerge(l.taskID)
if merging && finished {
mergeBy := m.takeMerge(l.taskID)
if mergeBy != "" && finished {
go m.finishMerge(l, mergeBy)
return nil
}
+11 -12
View File
@@ -50,25 +50,24 @@ func (m *Manager) Merge(ctx context.Context, task api.Task, project api.Project,
return api.AgentSession{}, err
}
m.mu.Lock()
m.merges[task.Id] = user.Login
m.mu.Unlock()
err = m.store.SetMergingBy(ctx, task.Id, user.Login)
if err != nil {
return api.AgentSession{}, err
}
sess, err := m.MergeIn(ctx, task, user, project.DefaultBranch)
if err != nil {
m.mu.Lock()
delete(m.merges, task.Id)
m.mu.Unlock()
m.takeMerge(task.Id)
}
return sess, err
}
func (m *Manager) takeMerge(taskID string) (string, bool) {
m.mu.Lock()
defer m.mu.Unlock()
login, ok := m.merges[taskID]
delete(m.merges, taskID)
return login, ok
func (m *Manager) takeMerge(taskID string) string {
login, err := m.store.TakeMergingBy(context.Background(), taskID)
if err != nil {
slog.Error("take merge intent", "task", taskID, "err", err)
}
return login
}
func (m *Manager) finishMerge(l *live, login string) {