From a8f04cc9e3cb60aabcaeb26d6acccd2a3a4f3554 Mon Sep 17 00:00:00 2001 From: dtoro Date: Wed, 15 Jul 2026 11:58:57 +0200 Subject: [PATCH] fix(agent): open assent window on 'go ahead' after propose_plan MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The check len(lastAssistantCalls) == 0 was too restrictive — it only fired when the assistant had ZERO tool calls. But propose_plan + pre-plan research are tool calls, so the assent window never opened when the operator said 'go ahead' after a plan proposal. The agent then tried to execute config_mutation run calls without the assent window, they queued for approval, and the turn deadlocked. Fix: check len(pending) == 0 (no pending APPROVALS) instead of len(lastAssistantCalls) == 0 (no tool calls at all). --- cmd/nomos/agent.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/cmd/nomos/agent.go b/cmd/nomos/agent.go index f937108..3a1e595 100644 --- a/cmd/nomos/agent.go +++ b/cmd/nomos/agent.go @@ -322,12 +322,16 @@ func (a *agent) chatWith(ctx context.Context, sessionID, message, systemInject s note := fmt.Sprintf("[System: execution(s) %s are classified DESTRUCTIVE and were NOT approved by loose assent — you must ask the operator for an explicit typed confirmation before they can run. Once they do confirm, further destructive steps on that SAME target (e.g. finishing a stop-then-destroy sequence) will auto-run for 15 minutes without asking again — but a different target always needs its own confirmation.]", strings.Join(blocked, ", ")) messages = append(messages, openai.SystemMessage(note)) } - } else if assent && len(lastAssistantCalls) == 0 { - // The operator said "proceed"/"go ahead"/"yes" but the preceding - // assistant turn had NO pending approvals — meaning the agent - // proposed a plan in text and asked "shall I?" without calling - // run yet. Inject a system note telling the agent - // the operator approved — go execute the plan now. + } else if assent && len(pending) == 0 { + // The operator said "proceed"/"go ahead"/"yes" but there are no + // pending approvals from the preceding turn — meaning the agent + // proposed a plan (via propose_plan, possibly with pre-plan research + // tool calls) and asked "shall I?" without calling run yet. Inject + // a system note telling the agent the operator approved — go execute + // the plan now. The old check (len(lastAssistantCalls) == 0) was too + // restrictive: it only fired when the assistant had ZERO tool calls, + // but propose_plan + research tools are tool calls. The right check + // is "no pending APPROVALS" (len(pending) == 0), not "no tool calls." note := "[System: The operator approved your proposed plan. Execute it now — call run to carry out the steps you described. Do not re-describe the plan or ask for confirmation again. The assent window is active: config_mutation commands will auto-run once you create them.]" messages = append(messages, openai.SystemMessage(note)) a.openAssentWindow(ctx, sessionID)