fix(agent): don't auto-complete sessions with pending approvals
The auto-complete fired when the agent hit the P5 approval gate — it queued a config_mutation run for approval, the P5 gate blocked further runs, the turn ended, and auto-complete closed the session as 'partial'. The operator's approval would then land on a dead task. Fix: hasPendingApprovals check — if the session has any executions in pending_approval state, skip auto-complete. The session stays in 'executing' until the operator approves (or denies). VERSION 0.7.5 → 0.7.6
This commit is contained in:
@@ -931,6 +931,23 @@ func (s *store) allPlanStepsTerminal(ctx context.Context, sessionID string) bool
|
|||||||
return total > 0 && total == terminal
|
return total > 0 && total == terminal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hasPendingApprovals reports whether this session has any executions in
|
||||||
|
// pending_approval state. Used by autoCompleteIfPlanDone to avoid closing a
|
||||||
|
// session that's blocked waiting for operator approval — the agent hit the
|
||||||
|
// P5 gate and can't continue until the operator responds.
|
||||||
|
func (s *store) hasPendingApprovals(ctx context.Context, sessionID string) bool {
|
||||||
|
if s == nil || sessionID == "" || sessionID == "ephemeral" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
var count int
|
||||||
|
s.pool.QueryRow(ctx, `
|
||||||
|
SELECT COUNT(*) FROM nomos_plan_executions pe
|
||||||
|
JOIN executions ex ON ex.entity_id = pe.execution_id
|
||||||
|
WHERE pe.session_id = $1 AND ex.status = 'pending_approval'`,
|
||||||
|
sessionID).Scan(&count)
|
||||||
|
return count > 0
|
||||||
|
}
|
||||||
|
|
||||||
// planStep is a persisted plan step, as returned to the frontend for hydration
|
// planStep is a persisted plan step, as returned to the frontend for hydration
|
||||||
// (the panel otherwise only sees steps live via plan.proposed/plan.step.*).
|
// (the panel otherwise only sees steps live via plan.proposed/plan.step.*).
|
||||||
type planStep struct {
|
type planStep struct {
|
||||||
|
|||||||
@@ -376,6 +376,15 @@ func (a *agent) autoCompleteIfPlanDone(ctx context.Context, sessionID, responseT
|
|||||||
if err != nil || sess.Status != "executing" {
|
if err != nil || sess.Status != "executing" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// Don't auto-complete if there are pending approvals — the agent is
|
||||||
|
// blocked waiting for the operator, not done. Auto-completing here
|
||||||
|
// would close the session and the operator's approval would land on a
|
||||||
|
// dead task. Confirmed in eval: agent hits P5 approval gate, turn
|
||||||
|
// ends, auto-complete fires incorrectly because the approval-queue
|
||||||
|
// `run` responses were logged as success=true in agent_activity.
|
||||||
|
if a.store.hasPendingApprovals(ctx, sessionID) {
|
||||||
|
return
|
||||||
|
}
|
||||||
discovery := a.store.hadDiscovery(ctx, sessionID)
|
discovery := a.store.hadDiscovery(ctx, sessionID)
|
||||||
writeback := a.store.hadEntityWriteback(ctx, sessionID)
|
writeback := a.store.hadEntityWriteback(ctx, sessionID)
|
||||||
// (a) all plan steps terminal, OR (b) agent did discovery (ran `run`).
|
// (a) all plan steps terminal, OR (b) agent did discovery (ran `run`).
|
||||||
|
|||||||
Reference in New Issue
Block a user