Skip to content

Commit 7a22dd3

Browse files
committed
fix(memory): fix 4 bugs in store layer
- decisions.go: check error from memory INSERT in RecordDecision - store.go: fix GetRecentExchanges ordering (subquery for DESC+ASC) - store.go: sanitizeFTS now keeps single-char words instead of dropping - store.go: GetByCategory includes _global project (matches SearchFTS)
1 parent 162d8fb commit 7a22dd3

3 files changed

Lines changed: 20 additions & 16 deletions

File tree

internal/memory/decisions.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,12 @@ func (s *Store) RecordDecision(ctx context.Context, projectID, title, decision,
4141

4242
// Also save as a memory so it shows up in search and prompt context.
4343
content := fmt.Sprintf("%s: %s. Rationale: %s", title, decision, rationale)
44-
s.db.ExecContext(ctx, `
44+
if _, err := s.db.ExecContext(ctx, `
4545
INSERT INTO memories (project_id, category, content, source, importance, tags)
4646
VALUES (?, 'decision', ?, 'decision_log', 0.9, ?)
47-
`, projectID, content, string(tagJSON))
47+
`, projectID, content, string(tagJSON)); err != nil {
48+
return id, fmt.Errorf("record decision memory: %w", err)
49+
}
4850

4951
if s.onSave != nil {
5052
s.onSave(projectID)

internal/memory/store.go

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ func (s *Store) GetByCategory(ctx context.Context, projectID, category string, l
293293
SELECT id, project_id, category, content, importance, access_count,
294294
last_accessed, source, tags, pinned, created_at, updated_at
295295
FROM memories
296-
WHERE project_id = ? AND category = ?
296+
WHERE (project_id = ? OR project_id = '_global') AND category = ?
297297
ORDER BY importance DESC, created_at DESC
298298
LIMIT ?
299299
`, projectID, category, limit)
@@ -502,12 +502,14 @@ func (s *Store) GetRecentExchanges(ctx context.Context, projectID string, limit
502502
defer s.mu.RUnlock()
503503

504504
rows, err := s.db.QueryContext(ctx, `
505-
SELECT m.role, m.content
506-
FROM messages m
507-
JOIN conversations c ON c.id = m.conversation_id
508-
WHERE c.project_id = ? AND m.role IN ('user', 'assistant')
509-
ORDER BY m.created_at DESC
510-
LIMIT ?
505+
SELECT role, content FROM (
506+
SELECT m.role, m.content, m.created_at
507+
FROM messages m
508+
JOIN conversations c ON c.id = m.conversation_id
509+
WHERE c.project_id = ? AND m.role IN ('user', 'assistant')
510+
ORDER BY m.created_at DESC
511+
LIMIT ?
512+
) ORDER BY created_at ASC
511513
`, projectID, limit*2)
512514
if err != nil {
513515
return nil, err
@@ -521,11 +523,11 @@ func (s *Store) GetRecentExchanges(ctx context.Context, projectID string, limit
521523
if err := rows.Scan(&role, &content); err != nil {
522524
return nil, err
523525
}
524-
if role == "assistant" {
525-
current[1] = content
526-
} else {
526+
if role == "user" {
527527
current[0] = content
528-
if current[1] != "" {
528+
} else {
529+
current[1] = content
530+
if current[0] != "" {
529531
pairs = append(pairs, current)
530532
}
531533
current = [2]string{}
@@ -648,7 +650,7 @@ func sanitizeFTS(text string) string {
648650
clean := strings.TrimFunc(word, func(r rune) bool {
649651
return !((r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') || (r >= '0' && r <= '9'))
650652
})
651-
if len(clean) >= 2 {
653+
if len(clean) >= 1 {
652654
// Quote each word to treat as literal.
653655
words = append(words, `"`+clean+`"`)
654656
}

internal/memory/store_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -352,9 +352,9 @@ func TestSanitizeFTS(t *testing.T) {
352352
want: `"hello" OR "world"`,
353353
},
354354
{
355-
name: "strips short words",
355+
name: "keeps single-char words",
356356
input: "a Go is great",
357-
want: `"Go" OR "is" OR "great"`,
357+
want: `"a" OR "Go" OR "is" OR "great"`,
358358
},
359359
{
360360
name: "strips punctuation from edges",

0 commit comments

Comments
 (0)