diff --git a/agent/agentic_loop.go b/agent/agentic_loop.go index fa98e3fc..537724e6 100644 --- a/agent/agentic_loop.go +++ b/agent/agentic_loop.go @@ -46,6 +46,11 @@ func (a *Agent) shouldUseAgenticTurn(userID int64) bool { if _, ok := a.getPendingProposalSession(userID); ok { return false } + // Suspended tasks are parked on the snapshot stack with all active + // contexts cleared; only the legacy router knows how to resume them. + if len(a.SnapshotManager(userID).Stack()) > 0 { + return false + } return true } diff --git a/agent/agentic_loop_test.go b/agent/agentic_loop_test.go index 7e9eb138..093222f6 100644 --- a/agent/agentic_loop_test.go +++ b/agent/agentic_loop_test.go @@ -274,6 +274,26 @@ func TestShouldUseAgenticTurn(t *testing.T) { } }) + t.Run("suspended task snapshot stays on legacy stack", func(t *testing.T) { + st, err := store.New(filepath.Join(t.TempDir(), "agentic-snapshot.db")) + if err != nil { + t.Fatalf("create store: %v", err) + } + b := New(nil, st, DefaultConfig(), slog.Default()) + b.SetAIClient(&scriptedAIClient{}) + if !b.shouldUseAgenticTurn(12) { + t.Fatal("fresh conversation should use the agentic turn") + } + b.SnapshotManager(12).Save(SuspendedTask{ + SnapshotID: "snap_test", + Kind: "skill", + ResumeHint: "continue strategy create", + }) + if b.shouldUseAgenticTurn(12) { + t.Fatal("suspended task snapshot must stay on the legacy stack so it can be resumed") + } + }) + t.Run("active legacy session stays on legacy stack", func(t *testing.T) { st, err := store.New(filepath.Join(t.TempDir(), "agentic-guard.db")) if err != nil {