From 899aee94ecd170fe0957a668c27d63bcb336cd03 Mon Sep 17 00:00:00 2001 From: Reidho Satria Date: Mon, 17 Aug 2026 10:45:59 +0700 Subject: [PATCH 1/3] fix(store): preallocate bounded query results Use normalized SQL limits as result-slice capacities for bounded memory, session, search, and cron queries. Preserve the existing non-nil empty-slice behavior while avoiding growth reallocations during row scans. --- internal/store/memory.go | 4 ++-- internal/store/ops.go | 2 +- internal/store/sessions.go | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/store/memory.go b/internal/store/memory.go index b8996bb..e641d9c 100644 --- a/internal/store/memory.go +++ b/internal/store/memory.go @@ -62,7 +62,7 @@ func (s *sqlStore) ListMemories(ctx context.Context, scope, scopeKey string, lim return nil, err } defer rows.Close() - out := []Memory{} + out := make([]Memory, 0, limit) for rows.Next() { m, err := scanMemory(rows) if err != nil { @@ -103,7 +103,7 @@ func (s *sqlStore) SearchMemories(ctx context.Context, query string, limit int) } } defer rows.Close() - out := []Memory{} + out := make([]Memory, 0, limit) for rows.Next() { m, err := scanMemory(rows) if err != nil { diff --git a/internal/store/ops.go b/internal/store/ops.go index a2b7a81..2fc7c7f 100644 --- a/internal/store/ops.go +++ b/internal/store/ops.go @@ -105,7 +105,7 @@ func (s *sqlStore) ListCronRuns(ctx context.Context, jobID string, limit int) ([ return nil, err } defer rows.Close() - out := []CronRun{} + out := make([]CronRun, 0, limit) for rows.Next() { var ( r CronRun diff --git a/internal/store/sessions.go b/internal/store/sessions.go index 461263c..6d2d91f 100644 --- a/internal/store/sessions.go +++ b/internal/store/sessions.go @@ -136,7 +136,7 @@ func (s *sqlStore) ListSessions(ctx context.Context, f SessionFilter) ([]Session } defer rows.Close() - out := []Session{} + out := make([]Session, 0, limit) for rows.Next() { sess, err := scanSession(rows) if err != nil { @@ -326,7 +326,7 @@ func (s *sqlStore) SearchMessages(ctx context.Context, query string, limit int) } defer rows.Close() - out := []SearchHit{} + out := make([]SearchHit, 0, limit) for rows.Next() { var ( h SearchHit From 0659477f22c87e8e2cd74df2b237c236e375de17 Mon Sep 17 00:00:00 2001 From: Reidho Satria Date: Mon, 17 Aug 2026 10:46:55 +0700 Subject: [PATCH 2/3] fix(agent): reserve bounded transcript collections Reserve the panel's bounded usable-answer list and the transcript repair index and turn list from the message count. Keep the existing two-pass tool-result binding and output ordering unchanged. --- internal/agent/agent.go | 4 ++-- internal/agent/harness.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/agent/agent.go b/internal/agent/agent.go index c382b5a..69cba97 100644 --- a/internal/agent/agent.go +++ b/internal/agent/agent.go @@ -1240,7 +1240,7 @@ func ensureToolResults(msgs []llm.Message) []llm.Message { // outside it. Reversing that order lets a turn whose result was compacted // away reach forward and take the result of a later turn sharing its id, // leaving the live call with a stub and the model with stale output. - byID := make(map[string][]int) + byID := make(map[string][]int, len(msgs)) for i, m := range msgs { if m.Role == llm.RoleTool { byID[m.ToolCallID] = append(byID[m.ToolCallID], i) @@ -1255,7 +1255,7 @@ func ensureToolResults(msgs []llm.Message) []llm.Message { end int bound []int // parallel to the turn's ToolCalls; -1 until a result binds } - var turns []turn + turns := make([]turn, 0, len(msgs)) for i, m := range msgs { if m.Role != llm.RoleAssistant { continue diff --git a/internal/agent/harness.go b/internal/agent/harness.go index 030f84a..c4e71d4 100644 --- a/internal/agent/harness.go +++ b/internal/agent/harness.go @@ -708,7 +708,7 @@ func (a *Agent) Panel(ctx context.Context, question string, models []string, emi } wg.Wait() - var usable []PanelAnswer + usable := make([]PanelAnswer, 0, len(answers)) for _, ans := range answers { if ans.Err == "" && strings.TrimSpace(ans.Answer) != "" { usable = append(usable, ans) From f341eebe89b558672d90a3d6cf9656b861e3c855 Mon Sep 17 00:00:00 2001 From: Reidho Satria Date: Mon, 17 Aug 2026 10:47:29 +0700 Subject: [PATCH 3/3] fix(server): preallocate engagement session rows Use the bounded session-list length as the response capacity while preserving the existing findings/intel filter and JSON shape. --- internal/server/handlers_engagement.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/server/handlers_engagement.go b/internal/server/handlers_engagement.go index 5261f52..fe64980 100644 --- a/internal/server/handlers_engagement.go +++ b/internal/server/handlers_engagement.go @@ -79,7 +79,7 @@ func (s *Server) handleEngagementSessions(w http.ResponseWriter, r *http.Request Findings int `json:"findings"` Intel int `json:"intel"` } - out := make([]row, 0) + out := make([]row, 0, len(sessions)) for _, sess := range sessions { f, intel := 0, 0 if s.agent.Findings() != nil {