* Extract memories from conventional git commits (refactor:, migrate:, fix:, revert:). * Scans last 90 days. Deduplicates via content hash. Zero friction alternative to manual memory.
(rootPath: string, memoryPath: string)
| 1200 | * Scans last 90 days. Deduplicates via content hash. Zero friction alternative to manual memory. |
| 1201 | */ |
| 1202 | async function extractGitMemories(rootPath: string, memoryPath: string): Promise<number> { |
| 1203 | // Quick check: skip if not a git repo |
| 1204 | if (!(await fileExists(path.join(rootPath, '.git')))) return 0; |
| 1205 | |
| 1206 | const { execSync } = await import('child_process'); |
| 1207 | |
| 1208 | let log: string; |
| 1209 | try { |
| 1210 | // Format: ISO-date<TAB>hash subject (e.g. "2026-01-15T10:00:00+00:00\tabc1234 fix: race condition") |
| 1211 | log = execSync('git log --format="%aI\t%h %s" --since="90 days ago" --no-merges', { |
| 1212 | cwd: rootPath, |
| 1213 | encoding: 'utf-8', |
| 1214 | timeout: 5000 |
| 1215 | }).trim(); |
| 1216 | } catch { |
| 1217 | // Git not available or command failed — silently skip |
| 1218 | return 0; |
| 1219 | } |
| 1220 | |
| 1221 | if (!log) return 0; |
| 1222 | |
| 1223 | const lines = log.split('\n').filter(Boolean); |
| 1224 | let added = 0; |
| 1225 | |
| 1226 | for (const line of lines) { |
| 1227 | const parsedMemory = parseGitLogLineToMemory(line); |
| 1228 | if (!parsedMemory) continue; |
| 1229 | |
| 1230 | const result = await appendMemoryFile(memoryPath, parsedMemory); |
| 1231 | if (result.status === 'added') added++; |
| 1232 | } |
| 1233 | |
| 1234 | return added; |
| 1235 | } |
| 1236 | |
| 1237 | async function performIndexingOnce( |
| 1238 | project: ProjectState, |
no test coverage detected