Claim a held merge as soon as the merge ahead of it finishes
This commit is contained in:
+34
-11
@@ -470,6 +470,7 @@ func (m *Manager) Recover(ctx context.Context) error {
|
||||
|
||||
go m.deliverAllLeads()
|
||||
go m.deliverAllQueued(context.Background())
|
||||
go m.advanceMergeClaims(context.Background())
|
||||
go m.startHeldMerges(context.Background())
|
||||
go m.recoverMergeAfterReviews(context.Background())
|
||||
go m.auditAll(context.Background())
|
||||
@@ -484,15 +485,18 @@ func (m *Manager) failResume(ctx context.Context, sess api.AgentSession, task ap
|
||||
if derr != nil {
|
||||
return derr
|
||||
}
|
||||
next, _, serr := m.store.EndTurn(ctx, sess.Id, "byre", map[string]any{"error": err.Error()}, nil, false, false)
|
||||
end, serr := m.store.EndTurn(ctx, sess.Id, "byre", map[string]any{"error": err.Error()}, nil, false, false, false)
|
||||
if serr != nil {
|
||||
return serr
|
||||
}
|
||||
switch {
|
||||
case next == store.DiscardClosing:
|
||||
case end.Discard == store.DiscardClosing:
|
||||
go m.finishDiscard(task.Id)
|
||||
case next == store.DiscardHeld:
|
||||
case end.Discard == store.DiscardHeld:
|
||||
go m.startDiscard(task.Id)
|
||||
case end.MergeBy != "":
|
||||
go m.startClaimedMerge(task.Id, end.MergeBy)
|
||||
case end.MergeWaiting:
|
||||
case sess.Role == api.Implementer && m.leadsTask(ctx, task.Id, sess.Id):
|
||||
m.abandonMerge(task.Id, task.ProjectId)
|
||||
}
|
||||
@@ -679,6 +683,18 @@ func (m *Manager) failStart(ctx context.Context, sessionID, actor string, err er
|
||||
if serr != nil {
|
||||
slog.Error("record failed start", "session", sessionID, "err", serr)
|
||||
}
|
||||
go m.advanceSessionMergeClaim(context.Background(), sessionID)
|
||||
}
|
||||
|
||||
func (m *Manager) advanceSessionMergeClaim(ctx context.Context, sessionID string) {
|
||||
sess, err := m.store.GetSession(ctx, sessionID)
|
||||
if err != nil {
|
||||
slog.Error("load session for merge claim", "session", sessionID, "err", err)
|
||||
return
|
||||
}
|
||||
if sess.TaskId != "" {
|
||||
m.advanceMergeClaim(sess.TaskId)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Manager) syncModel(ctx context.Context, l *live, model string) error {
|
||||
@@ -998,7 +1014,7 @@ func (m *Manager) pump(l *live) {
|
||||
}
|
||||
}
|
||||
m.endMergeTurn(l.id, true)
|
||||
next, _, err := m.store.EndTurn(ctx, l.id, agentActor, map[string]any{"error": "agent process exited mid-turn", "stopped": true}, nil, false, false)
|
||||
end, err := m.store.EndTurn(ctx, l.id, agentActor, map[string]any{"error": "agent process exited mid-turn", "stopped": true}, nil, false, false, false)
|
||||
if err != nil {
|
||||
slog.Error("record session exit", "session", l.id, "err", err)
|
||||
}
|
||||
@@ -1006,7 +1022,7 @@ func (m *Manager) pump(l *live) {
|
||||
m.finishReviewer(l, "the reviewer's process exited mid-turn")
|
||||
return
|
||||
}
|
||||
switch next {
|
||||
switch end.Discard {
|
||||
case store.DiscardClosing:
|
||||
m.finishDiscard(l.taskID)
|
||||
return
|
||||
@@ -1014,8 +1030,11 @@ func (m *Manager) pump(l *live) {
|
||||
m.startDiscard(l.taskID)
|
||||
return
|
||||
}
|
||||
if end.MergeBy != "" {
|
||||
go m.startClaimedMerge(l.taskID, end.MergeBy)
|
||||
}
|
||||
if l.owner == "" {
|
||||
if m.leadsTask(ctx, l.taskID, l.id) {
|
||||
if end.MergeBy == "" && !end.MergeWaiting && m.leadsTask(ctx, l.taskID, l.id) {
|
||||
m.abandonMerge(l.taskID, l.projectID)
|
||||
}
|
||||
m.recordError(l, "The agent process exited mid-turn. Send a message to resume it.")
|
||||
@@ -1310,15 +1329,19 @@ func (m *Manager) turnEnded(ctx context.Context, l *live, res endResult) error {
|
||||
state = map[string]any{"stopped": true}
|
||||
}
|
||||
turn := m.event(l, agentActor, "turn.ended", payload)
|
||||
next, finalizeBy, err := m.store.EndTurn(ctx, l.id, agentActor, state, &turn, review && !held, finished && !handoff)
|
||||
end, err := m.store.EndTurn(ctx, l.id, agentActor, state, &turn, review && !held, finished && !handoff, handoff)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if snapshot && !held {
|
||||
m.snapshotSoon(liveTarget(l), api.SnapshotTriggerTurnEnd, 0, review, false)
|
||||
}
|
||||
if end.MergeBy != "" {
|
||||
go m.startClaimedMerge(l.taskID, end.MergeBy)
|
||||
return nil
|
||||
}
|
||||
|
||||
switch next {
|
||||
switch end.Discard {
|
||||
case store.DiscardClosing:
|
||||
m.logUndelivered(ctx, l.id, "turn ended in discard")
|
||||
go m.finishDiscard(l.taskID)
|
||||
@@ -1337,14 +1360,14 @@ func (m *Manager) turnEnded(ctx context.Context, l *live, res endResult) error {
|
||||
go m.continueFromHandoff(l.id, res.result)
|
||||
return nil
|
||||
}
|
||||
if finalizeBy != "" {
|
||||
if end.FinalizeBy != "" {
|
||||
m.logUndelivered(ctx, l.id, "turn ended in merge")
|
||||
keep = owner
|
||||
go m.finishMerge(l, finalizeBy)
|
||||
go m.finishMerge(l, end.FinalizeBy)
|
||||
return nil
|
||||
}
|
||||
mergeBy := ""
|
||||
if m.leadsTask(ctx, l.taskID, l.id) {
|
||||
if !end.MergeWaiting && m.leadsTask(ctx, l.taskID, l.id) {
|
||||
mergeBy = m.takeMerge(l.taskID)
|
||||
}
|
||||
switch {
|
||||
|
||||
Reference in New Issue
Block a user