hippo-memory 0.6.2 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -47,6 +47,7 @@ That's it. You have a memory system.
47
47
 
48
48
  - **SQLite-first storage** with markdown/JSON mirrors for humans and git
49
49
  - **Active task snapshots** for bare `continue` recovery
50
+ - **Session event trails** for short-term continuity across stops and resumes
50
51
  - **Persistent stale-memory lifecycle** during `hippo sleep`
51
52
  - **Conflict tracking** with `hippo conflicts` and `.hippo/conflicts/` mirrors
52
53
 
@@ -126,6 +127,29 @@ hippo snapshot clear
126
127
 
127
128
  `hippo context --auto` includes the active task snapshot before long-term memories, so agents get both the immediate thread and the deeper lessons.
128
129
 
130
+ ### Session event trails
131
+
132
+ Manual snapshots are useful, but real work also needs a breadcrumb trail. Hippo can now store short session events and link them to the active snapshot so context output shows the latest steps, not just the last summary.
133
+
134
+ ```bash
135
+ hippo session log \
136
+ --id sess_20260326 \
137
+ --task "Ship continuity" \
138
+ --type progress \
139
+ --content "Schema migration is done, next step is CLI wiring"
140
+
141
+ hippo snapshot save \
142
+ --task "Ship continuity" \
143
+ --summary "Structured session events are flowing" \
144
+ --next-step "Surface them in framework hooks" \
145
+ --session sess_20260326
146
+
147
+ hippo session show --id sess_20260326
148
+ hippo context --auto --budget 1500
149
+ ```
150
+
151
+ Hippo mirrors the latest trail to `.hippo/buffer/recent-session.md` so you can inspect the short-term thread without opening SQLite.
152
+
129
153
  ---
130
154
 
131
155
  ## How It Works
@@ -555,11 +579,9 @@ Issues and PRs welcome. Before contributing, run `hippo status` in the repo root
555
579
 
556
580
  The interesting problems:
557
581
  - Better consolidation heuristics (what makes a good semantic memory?)
558
- - Embedding-based search (currently BM25 only)
559
- - MCP server wrapper
560
- - Conflict detection between semantic memories
561
582
  - Schema acceleration (fast-track memories that fit existing patterns)
562
583
  - Multi-agent shared memory with attribution
584
+ - Benchmark eval: memory-augmented agent vs static memory vs no memory
563
585
 
564
586
  ## License
565
587
 
@@ -26,6 +26,10 @@ export declare function runWatched(command: string): Promise<{
26
26
  exitCode: number;
27
27
  stderr: string;
28
28
  }>;
29
+ /**
30
+ * Check whether a directory is a git work tree.
31
+ */
32
+ export declare function isGitRepo(cwd: string): boolean;
29
33
  /**
30
34
  * Fetch recent git log lines (subject lines only).
31
35
  * days: how many days of history to include.
@@ -1 +1 @@
1
- {"version":3,"file":"autolearn.d.ts","sourceRoot":"","sources":["../src/autolearn.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,WAAW,EAAuB,MAAM,aAAa,CAAC;AAI/D;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,WAAW,CAkBb;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAsClF;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,SAAM,GACd,OAAO,CAST;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAwBzF;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAW7D"}
1
+ {"version":3,"file":"autolearn.d.ts","sourceRoot":"","sources":["../src/autolearn.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,WAAW,EAAuB,MAAM,aAAa,CAAC;AAI/D;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,WAAW,CAkBb;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAsClF;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,SAAM,GACd,OAAO,CAST;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAwBzF;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAY9C;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAW7D"}
package/dist/autolearn.js CHANGED
@@ -104,6 +104,23 @@ export function runWatched(command) {
104
104
  });
105
105
  });
106
106
  }
107
+ /**
108
+ * Check whether a directory is a git work tree.
109
+ */
110
+ export function isGitRepo(cwd) {
111
+ try {
112
+ const raw = execSync('git rev-parse --is-inside-work-tree', {
113
+ encoding: 'utf8',
114
+ cwd,
115
+ timeout: 10000,
116
+ stdio: ['ignore', 'pipe', 'ignore'],
117
+ });
118
+ return raw.trim() === 'true';
119
+ }
120
+ catch {
121
+ return false;
122
+ }
123
+ }
107
124
  /**
108
125
  * Fetch recent git log lines (subject lines only).
109
126
  * days: how many days of history to include.
@@ -1 +1 @@
1
- {"version":3,"file":"autolearn.js","sourceRoot":"","sources":["../src/autolearn.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"autolearn.js","sourceRoot":"","sources":["../src/autolearn.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts CHANGED
@@ -11,6 +11,7 @@
11
11
  * hippo outcome --good | --bad [--id <id>]
12
12
  * hippo conflicts [--status <status>] [--json]
13
13
  * hippo snapshot <save|show|clear>
14
+ * hippo session <log|show>
14
15
  * hippo forget <id>
15
16
  * hippo inspect <id>
16
17
  * hippo embed [--status]
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;GAmBG"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;GAoBG"}
package/dist/cli.js CHANGED
@@ -11,6 +11,7 @@
11
11
  * hippo outcome --good | --bad [--id <id>]
12
12
  * hippo conflicts [--status <status>] [--json]
13
13
  * hippo snapshot <save|show|clear>
14
+ * hippo session <log|show>
14
15
  * hippo forget <id>
15
16
  * hippo inspect <id>
16
17
  * hippo embed [--status]
@@ -23,12 +24,12 @@ import * as path from 'path';
23
24
  import * as fs from 'fs';
24
25
  import { execSync } from 'child_process';
25
26
  import { createMemory, calculateStrength, resolveConfidence, applyOutcome, Layer, } from './memory.js';
26
- import { getHippoRoot, isInitialized, initStore, writeEntry, readEntry, deleteEntry, loadAllEntries, loadSearchEntries, loadIndex, saveIndex, loadStats, updateStats, saveActiveTaskSnapshot, loadActiveTaskSnapshot, clearActiveTaskSnapshot, listMemoryConflicts, } from './store.js';
27
- import { search, markRetrieved, estimateTokens } from './search.js';
27
+ import { getHippoRoot, isInitialized, initStore, writeEntry, readEntry, deleteEntry, loadAllEntries, loadSearchEntries, loadIndex, saveIndex, loadStats, updateStats, saveActiveTaskSnapshot, loadActiveTaskSnapshot, clearActiveTaskSnapshot, appendSessionEvent, listSessionEvents, listMemoryConflicts, } from './store.js';
28
+ import { markRetrieved, estimateTokens, hybridSearch } from './search.js';
28
29
  import { consolidate } from './consolidate.js';
29
30
  import { isEmbeddingAvailable, embedAll, embedMemory, loadEmbeddingIndex, } from './embeddings.js';
30
- import { captureError, extractLessons, deduplicateLesson, runWatched, fetchGitLog, } from './autolearn.js';
31
- import { getGlobalRoot, initGlobal, promoteToGlobal, searchBoth, syncGlobalToLocal, } from './shared.js';
31
+ import { captureError, extractLessons, deduplicateLesson, runWatched, fetchGitLog, isGitRepo, } from './autolearn.js';
32
+ import { getGlobalRoot, initGlobal, promoteToGlobal, searchBothHybrid, syncGlobalToLocal, } from './shared.js';
32
33
  import { importChatGPT, importClaude, importCursor, importGenericFile, importMarkdown, } from './importers.js';
33
34
  import { cmdCapture } from './capture.js';
34
35
  // ---------------------------------------------------------------------------
@@ -259,7 +260,7 @@ function cmdRemember(hippoRoot, text, flags) {
259
260
  });
260
261
  }
261
262
  }
262
- function cmdRecall(hippoRoot, query, flags) {
263
+ async function cmdRecall(hippoRoot, query, flags) {
263
264
  requireInit(hippoRoot);
264
265
  const budget = parseInt(String(flags['budget'] ?? '4000'), 10);
265
266
  const asJson = Boolean(flags['json']);
@@ -269,12 +270,11 @@ function cmdRecall(hippoRoot, query, flags) {
269
270
  const hasGlobal = globalEntries.length > 0;
270
271
  let results;
271
272
  if (hasGlobal) {
272
- // Use searchBoth for merged results
273
- const merged = searchBoth(query, hippoRoot, globalRoot, { budget });
274
- results = merged;
273
+ // Use searchBothHybrid for merged results with embedding support
274
+ results = await searchBothHybrid(query, hippoRoot, globalRoot, { budget });
275
275
  }
276
276
  else {
277
- results = search(query, localEntries, { budget });
277
+ results = await hybridSearch(query, localEntries, { budget, hippoRoot });
278
278
  }
279
279
  if (results.length === 0) {
280
280
  if (asJson) {
@@ -494,6 +494,9 @@ function printActiveTaskSnapshot(snapshot) {
494
494
  console.log(`- Status: ${snapshot.status}`);
495
495
  console.log(`- Updated: ${snapshot.updated_at}`);
496
496
  console.log(`- Source: ${snapshot.source}`);
497
+ if (snapshot.session_id) {
498
+ console.log(`- Session: ${snapshot.session_id}`);
499
+ }
497
500
  console.log('');
498
501
  console.log('### Summary');
499
502
  console.log(snapshot.summary);
@@ -502,6 +505,22 @@ function printActiveTaskSnapshot(snapshot) {
502
505
  console.log(snapshot.next_step);
503
506
  console.log('');
504
507
  }
508
+ function printSessionEvents(events) {
509
+ if (events.length === 0) {
510
+ console.log('No session events found.');
511
+ return;
512
+ }
513
+ const latest = events[events.length - 1];
514
+ console.log('## Recent Session Trail\n');
515
+ console.log(`- Session: ${latest.session_id}`);
516
+ console.log(`- Task: ${latest.task ?? 'n/a'}`);
517
+ console.log(`- Updated: ${latest.created_at}`);
518
+ console.log('');
519
+ for (const event of events) {
520
+ console.log(`- [${event.created_at}] (${event.event_type}) ${event.content}`);
521
+ }
522
+ console.log('');
523
+ }
505
524
  function cmdConflicts(hippoRoot, flags) {
506
525
  requireInit(hippoRoot);
507
526
  const conflicts = listMemoryConflicts(hippoRoot, String(flags['status'] ?? 'open'));
@@ -528,8 +547,9 @@ function cmdSnapshot(hippoRoot, args, flags) {
528
547
  const task = String(flags['task'] ?? '').trim();
529
548
  const summary = String(flags['summary'] ?? '').trim();
530
549
  const nextStep = String(flags['next-step'] ?? '').trim();
550
+ const sessionId = String(flags['session'] ?? flags['id'] ?? '').trim();
531
551
  if (!task || !summary || !nextStep) {
532
- console.error('Usage: hippo snapshot save --task <task> --summary <summary> --next-step <step> [--source <source>]');
552
+ console.error('Usage: hippo snapshot save --task <task> --summary <summary> --next-step <step> [--source <source>] [--session <session-id>]');
533
553
  process.exit(1);
534
554
  }
535
555
  const snapshot = saveActiveTaskSnapshot(hippoRoot, {
@@ -537,10 +557,14 @@ function cmdSnapshot(hippoRoot, args, flags) {
537
557
  summary,
538
558
  next_step: nextStep,
539
559
  source: String(flags['source'] ?? 'cli'),
560
+ session_id: sessionId || null,
540
561
  });
541
562
  console.log(`Saved active task snapshot #${snapshot.id}`);
542
563
  console.log(` Task: ${snapshot.task}`);
543
564
  console.log(` Next: ${snapshot.next_step}`);
565
+ if (snapshot.session_id) {
566
+ console.log(` Session: ${snapshot.session_id}`);
567
+ }
544
568
  return;
545
569
  }
546
570
  if (subcommand === 'clear') {
@@ -573,7 +597,48 @@ function cmdSnapshot(hippoRoot, args, flags) {
573
597
  console.error('Usage: hippo snapshot <save|show|clear>');
574
598
  process.exit(1);
575
599
  }
576
- function cmdContext(hippoRoot, args, flags) {
600
+ function cmdSession(hippoRoot, args, flags) {
601
+ requireInit(hippoRoot);
602
+ const subcommand = args[0] ?? 'show';
603
+ const sessionId = String(flags['id'] ?? flags['session'] ?? '').trim();
604
+ const task = String(flags['task'] ?? '').trim();
605
+ const limit = Math.max(1, parseInt(String(flags['limit'] ?? '8'), 10) || 8);
606
+ if (subcommand === 'log') {
607
+ const eventType = String(flags['type'] ?? 'note').trim();
608
+ const content = String(flags['content'] ?? '').trim();
609
+ if (!sessionId || !content) {
610
+ console.error('Usage: hippo session log --id <session-id> --content <text> [--type <type>] [--task <task>] [--source <source>]');
611
+ process.exit(1);
612
+ }
613
+ const event = appendSessionEvent(hippoRoot, {
614
+ session_id: sessionId,
615
+ task: task || null,
616
+ event_type: eventType || 'note',
617
+ content,
618
+ source: String(flags['source'] ?? 'cli'),
619
+ });
620
+ console.log(`Logged session event #${event.id}`);
621
+ console.log(` Session: ${event.session_id}`);
622
+ console.log(` Type: ${event.event_type}`);
623
+ return;
624
+ }
625
+ if (subcommand === 'show') {
626
+ const events = listSessionEvents(hippoRoot, {
627
+ session_id: sessionId || undefined,
628
+ task: task || undefined,
629
+ limit,
630
+ });
631
+ if (flags['json']) {
632
+ console.log(JSON.stringify({ events }, null, 2));
633
+ return;
634
+ }
635
+ printSessionEvents(events);
636
+ return;
637
+ }
638
+ console.error('Usage: hippo session <log|show>');
639
+ process.exit(1);
640
+ }
641
+ async function cmdContext(hippoRoot, args, flags) {
577
642
  requireInit(hippoRoot);
578
643
  const budget = parseInt(String(flags['budget'] ?? '1500'), 10);
579
644
  // If budget is 0, skip entirely (zero token cost)
@@ -598,6 +663,9 @@ function cmdContext(hippoRoot, args, flags) {
598
663
  let selectedItems = [];
599
664
  let totalTokens = 0;
600
665
  const activeSnapshot = loadActiveTaskSnapshot(hippoRoot);
666
+ const recentSessionEvents = activeSnapshot?.session_id
667
+ ? listSessionEvents(hippoRoot, { session_id: activeSnapshot.session_id, limit: 5 })
668
+ : [];
601
669
  if (query === '*') {
602
670
  // No query: return strongest memories by strength, up to budget
603
671
  const now = new Date();
@@ -630,7 +698,7 @@ function cmdContext(hippoRoot, args, flags) {
630
698
  else {
631
699
  let results;
632
700
  if (hasGlobal) {
633
- const merged = searchBoth(query, hippoRoot, globalRoot, { budget });
701
+ const merged = await searchBothHybrid(query, hippoRoot, globalRoot, { budget });
634
702
  const localIndex = loadIndex(hippoRoot);
635
703
  results = merged.map((r) => ({
636
704
  entry: r.entry,
@@ -640,7 +708,7 @@ function cmdContext(hippoRoot, args, flags) {
640
708
  }));
641
709
  }
642
710
  else {
643
- results = search(query, localEntries, { budget }).map((r) => ({
711
+ results = (await hybridSearch(query, localEntries, { budget, hippoRoot })).map((r) => ({
644
712
  entry: r.entry,
645
713
  score: r.score,
646
714
  tokens: r.tokens,
@@ -650,7 +718,7 @@ function cmdContext(hippoRoot, args, flags) {
650
718
  selectedItems = results;
651
719
  totalTokens = results.reduce((sum, r) => sum + r.tokens, 0);
652
720
  }
653
- if (selectedItems.length === 0 && !activeSnapshot)
721
+ if (selectedItems.length === 0 && !activeSnapshot && recentSessionEvents.length === 0)
654
722
  return;
655
723
  // Mark retrieved and persist
656
724
  const toUpdate = selectedItems.map((s) => s.entry);
@@ -675,12 +743,15 @@ function cmdContext(hippoRoot, args, flags) {
675
743
  content: r.entry.content,
676
744
  global: r.isGlobal ?? false,
677
745
  }));
678
- console.log(JSON.stringify({ query, activeSnapshot, memories: output, tokens: totalTokens }));
746
+ console.log(JSON.stringify({ query, activeSnapshot, recentSessionEvents, memories: output, tokens: totalTokens }));
679
747
  }
680
748
  else {
681
749
  if (activeSnapshot) {
682
750
  printActiveTaskSnapshot(activeSnapshot);
683
751
  }
752
+ if (recentSessionEvents.length > 0) {
753
+ printSessionEvents(recentSessionEvents);
754
+ }
684
755
  printContextMarkdown(selectedItems.map((r) => ({
685
756
  entry: updatedEntries.find((u) => u.id === r.entry.id) ?? r.entry,
686
757
  score: r.score,
@@ -813,9 +884,13 @@ async function cmdWatch(command, hippoRoot) {
813
884
  // ---------------------------------------------------------------------------
814
885
  function learnFromRepo(hippoRoot, repoPath, days, label) {
815
886
  const prefix = label ? `[${label}] ` : '';
887
+ if (!isGitRepo(repoPath)) {
888
+ console.log(`${prefix}No git history found (or not a git repository).`);
889
+ return { added: 0, skipped: 0 };
890
+ }
816
891
  const gitLog = fetchGitLog(repoPath, days);
817
892
  if (!gitLog.trim()) {
818
- console.log(`${prefix}No git history found (or not a git repository).`);
893
+ console.log(`${prefix}No fix/revert/bug commits found in the specified period.`);
819
894
  return { added: 0, skipped: 0 };
820
895
  }
821
896
  const lessons = extractLessons(gitLog);
@@ -1217,10 +1292,23 @@ Commands:
1217
1292
  --summary <summary>
1218
1293
  --next-step <step>
1219
1294
  --source <source> Optional source label
1295
+ --session <id> Link snapshot to a session trail
1220
1296
  snapshot show Show the active task snapshot
1221
1297
  --json Output as JSON
1222
1298
  snapshot clear Clear the active task snapshot
1223
1299
  --status <status> Mark final status (default: cleared)
1300
+ session <sub> Append or inspect short-term session history
1301
+ session log Append a structured session event
1302
+ --id <session-id>
1303
+ --content <text>
1304
+ --type <type> Event type (default: note)
1305
+ --task <task> Optional task label
1306
+ --source <source> Optional source label
1307
+ session show Show recent events for a session or task
1308
+ --id <session-id>
1309
+ --task <task>
1310
+ --limit <n> Event limit (default: 8)
1311
+ --json Output as JSON
1224
1312
  forget <id> Force remove a memory
1225
1313
  inspect <id> Show full memory detail
1226
1314
  embed Embed all memories for semantic search
@@ -1259,7 +1347,8 @@ Examples:
1259
1347
  hippo recall "data pipeline issues" --budget 2000
1260
1348
  hippo context --auto --budget 1500
1261
1349
  hippo conflicts
1262
- hippo snapshot save --task "Ship feature" --summary "Tests are green" --next-step "Open the PR"
1350
+ hippo session log --id sess_123 --task "Ship feature" --type progress --content "Build is green, next step is docs"
1351
+ hippo snapshot save --task "Ship feature" --summary "Tests are green" --next-step "Open the PR" --session sess_123
1263
1352
  hippo embed --status
1264
1353
  hippo watch "npm run build"
1265
1354
  hippo learn --git --days 30
@@ -1296,7 +1385,7 @@ async function main() {
1296
1385
  console.error('Please provide a search query.');
1297
1386
  process.exit(1);
1298
1387
  }
1299
- cmdRecall(hippoRoot, query, flags);
1388
+ await cmdRecall(hippoRoot, query, flags);
1300
1389
  break;
1301
1390
  }
1302
1391
  case 'sleep':
@@ -1314,6 +1403,9 @@ async function main() {
1314
1403
  case 'snapshot':
1315
1404
  cmdSnapshot(hippoRoot, args, flags);
1316
1405
  break;
1406
+ case 'session':
1407
+ cmdSession(hippoRoot, args, flags);
1408
+ break;
1317
1409
  case 'forget': {
1318
1410
  const id = args[0];
1319
1411
  if (!id) {
@@ -1333,7 +1425,7 @@ async function main() {
1333
1425
  break;
1334
1426
  }
1335
1427
  case 'context':
1336
- cmdContext(hippoRoot, args, flags);
1428
+ await cmdContext(hippoRoot, args, flags);
1337
1429
  break;
1338
1430
  case 'hook':
1339
1431
  cmdHook(args, flags);