Close flushes the current session draft to a markdown file and adds a record to index.json. An empty draft (no Save calls) is a no-op — empty sessions shouldn't pollute the index. Safe to call multiple times; only the first call has any effect.
()
| 194 | // sessions shouldn't pollute the index. Safe to call multiple times; only |
| 195 | // the first call has any effect. |
| 196 | func (s *SessionFiles) Close() error { |
| 197 | s.mu.Lock() |
| 198 | defer s.mu.Unlock() |
| 199 | if len(s.draft) == 0 { |
| 200 | return nil |
| 201 | } |
| 202 | summary, tags, body := s.assembleSession() |
| 203 | filename := s.sessionStart.Format("2006-01-02-15h04") + ".md" |
| 204 | rel := filepath.Join("sessions", filename) |
| 205 | fullPath := filepath.Join(s.root, rel) |
| 206 | if err := os.WriteFile(fullPath, []byte(body), 0o644); err != nil { |
| 207 | return fmt.Errorf("memory: write session: %w", err) |
| 208 | } |
| 209 | s.index = append(s.index, SessionRecord{ |
| 210 | Path: rel, |
| 211 | Date: s.sessionStart, |
| 212 | Summary: summary, |
| 213 | Tags: tags, |
| 214 | }) |
| 215 | if err := s.flushIndex(); err != nil { |
| 216 | return err |
| 217 | } |
| 218 | s.draft = nil |
| 219 | return nil |
| 220 | } |
| 221 | |
| 222 | // assembleSession turns the in-memory draft into (summary, tags, body). |
| 223 | // The session-summary entry (if any) becomes the file header + the index |