sessionmem 1.4.0 → 1.6.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.
Files changed (57) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/README.md +233 -41
  3. package/dist/adapters/diagnostics.js +109 -0
  4. package/dist/adapters/generic.js +6 -2
  5. package/dist/adapters/global/antigravity.js +4 -1
  6. package/dist/adapters/global/claudeCode.js +19 -4
  7. package/dist/adapters/global/codex.js +7 -6
  8. package/dist/adapters/global/qcoder.js +4 -1
  9. package/dist/adapters/ide/cline.js +3 -0
  10. package/dist/adapters/ide/cursor.js +3 -0
  11. package/dist/adapters/ide/installer.js +17 -5
  12. package/dist/adapters/ide/windsurf.js +3 -0
  13. package/dist/adapters/installedHosts.js +51 -0
  14. package/dist/cli/commands/doctor.js +155 -0
  15. package/dist/cli/commands/entities.js +27 -0
  16. package/dist/cli/commands/history.js +23 -0
  17. package/dist/cli/commands/ingestHook.js +4 -78
  18. package/dist/cli/commands/install.js +34 -56
  19. package/dist/cli/commands/scan.js +16 -0
  20. package/dist/cli/commands/search.js +1 -0
  21. package/dist/cli/commands/team.js +7 -3
  22. package/dist/cli/commands/ui.js +67 -0
  23. package/dist/cli/commands/watch.js +48 -0
  24. package/dist/cli/index.js +44 -1
  25. package/dist/cli/projectId.js +1 -2
  26. package/dist/cli/transcriptSweep.js +142 -0
  27. package/dist/cli/transcripts/claudeCode.js +62 -0
  28. package/dist/cli/transcripts/codex.js +111 -0
  29. package/dist/cli/transcripts/cursor.js +295 -0
  30. package/dist/cli/transcripts/index.js +118 -0
  31. package/dist/cli/transcripts/types.js +15 -0
  32. package/dist/core/api/contracts.js +4 -0
  33. package/dist/core/api/memoryCoreService.js +9 -1
  34. package/dist/core/api/sessionLifecycleService.js +13 -1
  35. package/dist/core/capture/toolEvent.js +94 -0
  36. package/dist/core/extract/factClaims.js +97 -0
  37. package/dist/core/extract/knowledge.js +127 -0
  38. package/dist/core/retrieve/retrieveMemories.js +20 -4
  39. package/dist/core/schema/migrations/012_transcript_checkpoints.sql +4 -0
  40. package/dist/core/schema/migrations/013_fts_porter.sql +32 -0
  41. package/dist/core/schema/migrations/014_memory_entities.sql +19 -0
  42. package/dist/core/schema/migrations/015_memory_supersessions.sql +41 -0
  43. package/dist/core/schema/runMigrations.js +46 -0
  44. package/dist/core/storage/knowledgeRepo.js +67 -0
  45. package/dist/core/storage/memoryRepo.js +45 -12
  46. package/dist/core/storage/memorySearchRepo.js +30 -20
  47. package/dist/core/storage/sessionEventsRepo.js +12 -3
  48. package/dist/core/storage/supersessionRepo.js +101 -0
  49. package/dist/core/summarize/summaryShape.js +1 -1
  50. package/dist/ui/assets.js +181 -0
  51. package/dist/ui/server.js +147 -0
  52. package/docs/REGISTRY_LISTING.md +88 -0
  53. package/docs/architecture.md +27 -3
  54. package/docs/benchmark.md +105 -33
  55. package/docs/migration.md +2 -0
  56. package/docs/troubleshooting.md +52 -4
  57. package/package.json +1 -1
@@ -0,0 +1,88 @@
1
+ # Registry listing — draft for review
2
+
3
+ **Status: DRAFT FOR REVIEW. This is proposed listing text only; it has not been
4
+ submitted to any MCP or tool registry.**
5
+
6
+ ## Name
7
+
8
+ sessionmem
9
+
10
+ MCP identifier: `io.github.catfish-1234/sessionmem`
11
+
12
+ ## One-line description
13
+
14
+ An offline MCP memory server that keeps coding-agent decisions, warnings, and
15
+ project context in local SQLite across sessions.
16
+
17
+ ## Features
18
+
19
+ - Persistent project memory through MCP tools for storing, retrieving, listing,
20
+ inspecting, and forgetting memories.
21
+ - Claude Code hooks capture supported tool events, summarize sessions locally,
22
+ and load relevant prior context automatically. Other MCP hosts use memory
23
+ tools and installed guidance; automatic lifecycle capture depends on the host.
24
+ - Adapters for Claude Code, Codex, Cursor, Cline, Windsurf, Antigravity, QCoder,
25
+ and generic MCP hosts.
26
+ - Offline BM25 retrieval with English stemming, entity overlap, recency, and
27
+ importance; startup context is trimmed to a token budget.
28
+ - Deterministic entity/relation extraction and supersession history. Fully
29
+ replaced memories are excluded from normal recall, with explicit history
30
+ lookup available. These language rules have limited coverage.
31
+ - Offline `scan`/`watch` commands for existing and new Claude Code transcripts.
32
+ - Local SQLite storage, default secret-pattern redaction, configurable retention,
33
+ JSON export/import, and offline installation diagnostics with `sessionmem doctor`.
34
+ - A committed LoCoMo corpus and reproducible offline evidence-retrieval runner;
35
+ see the [comparison and evaluation limits](../COMPARISON.md#evaluation-and-measured-results).
36
+
37
+ ## Install and connect
38
+
39
+ Requires Node.js `^20.19.0 || >=22.13.0`.
40
+
41
+ ```bash
42
+ npm install -g sessionmem
43
+ ```
44
+
45
+ From the project directory, register it with a configured host:
46
+
47
+ ```bash
48
+ sessionmem install
49
+ ```
50
+
51
+ Automatic discovery currently detects Claude Code. Select other adapters
52
+ explicitly, for example:
53
+
54
+ ```bash
55
+ sessionmem install --adapter codex
56
+ ```
57
+
58
+ Restart the host after registration. The host launches the stdio server with
59
+ `sessionmem run`; this is the server command for registries that request one.
60
+ See the [quickstart](../README.md#quickstart) for host-specific setup.
61
+
62
+ ## Offline guarantee
63
+
64
+ **The local memory pipeline requires no API keys and makes no network calls.**
65
+ Capture, local summarization, entity/relation extraction, supersession, and
66
+ retrieval run on the user's machine without downloading models. Memories are
67
+ stored by default in `~/.sessionmem/memories.db`. No hosted memory account or
68
+ service is needed. The coding agent's own model connection is separate.
69
+
70
+ Package installation may require network access or an offline package cache.
71
+ Explicitly enabling [cloud summarization](cloud-summarization.md) with both its
72
+ configuration flag and an Anthropic API key sends a redacted transcript to
73
+ Anthropic. Optional [team sharing](team-mode.md) uses a user-selected shared
74
+ folder. These opt-in paths are outside the local-only guarantee. The optional
75
+ read-only viewer uses loopback HTTP with locally bundled assets and no external
76
+ services or CDNs.
77
+
78
+ ## Links and license
79
+
80
+ - [Source and setup](https://github.com/catfish-1234/sessionmem)
81
+ - [npm package](https://www.npmjs.com/package/sessionmem)
82
+ - [Comparison](../COMPARISON.md)
83
+ - [Privacy and retention](privacy-and-retention.md)
84
+ - [MIT license](../LICENSE); the bundled LoCoMo dataset has a separate
85
+ [CC BY-NC 4.0 license](../benchmarks/data/LICENSE.txt).
86
+
87
+ Review the wording and destination-specific registry fields before any future
88
+ submission. This draft does not claim registry acceptance or verification.
@@ -30,7 +30,7 @@
30
30
 
31
31
  ### Core engine
32
32
 
33
- The core engine captures session events, summarizes them into stored memories at session end, ranks those memories, and selects which to inject. It uses the adapter layer for all communication with specific tools. Retrieval combines semantic similarity, recency, and importance into a relevance score.
33
+ The core engine captures session events, summarizes them into stored memories at session end, ranks those memories, and selects which to inject. It uses the adapter layer for all communication with specific tools. Retrieval combines BM25 lexical relevance, entity overlap, recency, and importance into a relevance score.
34
34
 
35
35
  ### Adapters
36
36
 
@@ -42,11 +42,35 @@ The CLI (`sessionmem`) registers the server with a host and runs the MCP server.
42
42
 
43
43
  ### SQLite storage
44
44
 
45
- SQLite stores memories, embeddings for vector search, raw session events, and feedback history in one local file. Database access uses `better-sqlite3`, with forward-only [migrations](migration.md). No hosted database is required.
45
+ SQLite stores memories, embeddings for vector search, raw session events, extracted entities and relations, and feedback history in one local file. Database access uses `better-sqlite3`, with forward-only [migrations](migration.md). No hosted database is required.
46
+
47
+ ## Entity and relation extraction
48
+
49
+ Capture, batch writes, imports, team pulls, and content rewrites derive a graph locally. Session-end summarization (including scan/watch) reads the same event text as the existing summarizer before summary line/token caps. Extraction always applies the built-in redaction rules, including when indexing legacy text. It never invokes a model or an external API.
50
+
51
+ The rules recognize labeled speakers, explicit `person`, `project`, `tool`, `service`, and `file` names, common tools/services, and file paths with supported extensions. Short affirmative clauses such as `Alice works on project Atlas`, `Alice uses SQLite`, `Alice decided to use SQLite`, `Alice prefers Python`, and `Project Atlas is blocked by GitHub` yield `works_on`, `uses`, `decided`, `prefers`, and `blocked_by` edges. Decision clauses become decision entities. `Ran:` tool events yield `uses` for recognized executables; git commits also yield decisions, matching the existing local summarizer. Unlabeled first-person/imperative clauses use `user` (or `team` for `we`); labeled speakers resolve `I`. Questions, negation, hypothetical clauses, and unresolved third-person pronouns are skipped. These conservative rules are not general natural-language understanding and can miss or misclassify unfamiliar phrasing.
52
+
53
+ Names use NFKC, lowercase, stripped quotes/possessives, and collapsed whitespace. This also folds file-path case. `memory_entities` stores unique `(memory_id, kind, name)` rows; `memory_relations` references both endpoints in the same memory. Updates replace derived rows atomically, and foreign keys cascade memory deletion and summary ID changes. Migration 014 backfills existing memories, using full events for summaries when available. Expired memories are excluded from graph reads and ranking. Export/import request and response formats are unchanged; graphs are rebuilt from imported content, so event-only details absent from an exported summary do not round-trip.
54
+
55
+ `sessionmem entities --project <id>` lists entities and relations with source memory IDs; `--json` provides structured output. Omitting `--project` selects the current project.
56
+
57
+ ## Contradiction and supersession
58
+
59
+ Migration 015 adds `memory_claims` and `memory_supersessions`. Claims use migration 014's canonical entity and typed-relation extractor, with a small grammar for `does not`, `no longer`, `stopped using`, `switched to/from`, and `replaced ... with`. A comparison requires the same entity and relation. Opposite polarity on the same value is a contradiction. Different positive values supersede one another when their lexical purpose overlaps (at least two words and Jaccard overlap 0.6, or an exact purpose), their tool category matches (editor, language, database, package manager, test runner), or a replacement explicitly names the old value. `now works on` also replaces a prior project. Different purposes, entities, or relation types remain independent. Questions, hypothetical statements, reported quotations, and unresolved pronouns are skipped. Rules are conservative heuristics and do not resolve arbitrary language or coreference.
60
+
61
+ Each link records the old memory in `supersedes`, the replacement in `superseded_by`, both claim keys, the reason, the replacement assertion's `superseded_at`, and the wall-clock `detected_at`. Memory bodies, IDs, and importance are preserved. A derived `superseded_memories` view marks a memory fully superseded only when every extracted claim has a replacement. Independent claims in a mixed summary keep it searchable; its content can still contain stale claims, so inspect partial supersessions in history when auditing such summaries. No old memory is deleted by supersession; explicit deletion and retention keep their existing behavior.
62
+
63
+ Writes reconcile only affected entity/relation groups within the same project, atomically with memory and graph updates. Assertions are ordered by their stored timestamp, then memory insertion rowid for equal timestamps. This gives pinned-clock captures a deterministic arrival order. The earliest later contradictory assertion supplies each link, permitting chains and later reaffirmations without cycles. Identical replay preserves links and detection timestamps; imports, content rewrites, summary ID changes, and deletion reconnect affected chains. Migration 015 backfills existing memories once, using full session events for summaries. Scan preserves valid original transcript timestamps, so filename order does not determine freshness. Without original timestamps, stored capture order is the fallback. An unrelated appended event does not change an earlier assertion's time.
64
+
65
+ Recall filters fully superseded memories before the FTS candidate limit and fallback scan, giving current facts priority. The optional `includeHistory: true` request field, exposed as `sessionmem search --include-history`, restores normal relevance ranking across current and superseded memories. Existing requests and response shapes remain compatible. `getMemory`, list and export still expose earlier memories. `sessionmem history [--project <id>] [--json]` lists links with old/new values, timestamps, reasons, source IDs, and partial/full status. Export formats remain unchanged: importing rebuilds links from exported bodies and timestamps; event-only claims absent from a summary cannot round-trip.
46
66
 
47
67
  ## Retrieval flow
48
68
 
49
- When an agent or `sessionmem search` submits a query, the core engine embeds it and runs a vector search over the `memories` table. It ranks candidates by semantic similarity, recency, and importance, then returns the memories with their scores.
69
+ When an agent or `sessionmem search` submits a query, the core engine searches the SQLite FTS5 index over stored memory content, including summaries. It removes common English question words and matches any remaining term. SQLite's built-in Porter tokenizer matches English inflections such as “hike” and “hiking”. BM25 accounts for term rarity, frequency, and memory length; at most 50 lexical candidates are returned, ordered by BM25 and then ID.
70
+
71
+ The ranker divides each positive BM25 score by the best score for that query. If the query contains known entity names in this project, relevance is `0.90 * base relevance + 0.10 * entity overlap`. Overlap is the fraction of distinct matched query names linked to the candidate memory; names are matched as literal token sequences (up to eight tokens), including lowercase questions. With no known query entities, relevance is unchanged. This reranks the existing candidates; it does not expand the FTS candidate pool or traverse relations. The outer relevance, recency, and importance weights stay 0.60, 0.25, and 0.15. Sparse lexical matches retain the recency/importance fallback union. If there are no lexical matches, base relevance uses the previous hash-vector ranking. Project scope and expiry checks apply to both paths. Automatic migrations preserve memory bodies and IDs.
72
+
73
+ Existing public request fields and all response fields are unchanged; `includeHistory` is an optional addition. The `semantic` field still reports hash cosine similarity. The legacy `score.raw.semantic` and `score.weighted.semantic` fields carry the relevance component used for ranking, including entity overlap when query entities match. Scores are relative to the current query's candidates, not calibrated probabilities. Retrieval needs no API keys, downloaded models, or new dependencies.
50
74
 
51
75
  ## Injection flow
52
76
 
package/docs/benchmark.md CHANGED
@@ -1,50 +1,122 @@
1
- # Benchmark
1
+ # Conversational retrieval benchmark
2
2
 
3
- `npm run benchmark` (`scripts/benchmark.mjs`) generates this report using the production functions `retrieveMemories`, `formatStartupInjection`, and `countTokens`. It measures token reduction against full session history and retrieval relevance using curated, synthetic fixtures. It runs offline with a hash-based embedding function, `deterministicEmbed`, and a fixed clock, so repeated runs produce identical output.
3
+ `npm run benchmark` runs the committed LoCoMo corpus through the public
4
+ `storeMemory` capture and `retrieveMemories` recall APIs. See
5
+ [benchmarks/README.md](../benchmarks/README.md) for the corpus license, selection
6
+ rules, metric definitions, and detailed reproduction instructions.
4
7
 
5
- Startup injection used **~85.6% fewer tokens** than full session history. Retrieval had a **100.0% hit-rate** across 10 curated queries.
8
+ ## Entity overlap comparison
6
9
 
7
- ## Token reduction
10
+ The baseline was run first on current main at `81f987c`. A fixed 10% entity
11
+ contribution inside the existing relevance component was then evaluated without
12
+ a weight sweep. Both runs used Node v24.19.0, Linux x64, sessionmem 1.4.0, the
13
+ same installed lockfile dependencies, top-5, fixed clocks, and the unchanged
14
+ LoCoMo corpus and scoring rules. Each run scored 1,527 questions after capturing
15
+ 5,882 turns; both recorded zero network attempts.
8
16
 
9
- Token counts use the production `countTokens` function (js-tiktoken `o200k_base`). The table compares a single startup injection and average per-query context with the same full-history baseline. The result above uses startup injection.
17
+ | Macro retrieval metric @5 | Main (BM25) | BM25 + entity overlap |
18
+ | --- | ---: | ---: |
19
+ | Hit rate | 61.95% | 63.92% |
20
+ | Precision | 13.45% | 14.05% |
21
+ | Recall | 55.96% | 57.45% |
22
+ | All-evidence rate | 51.15% | 52.26% |
10
23
 
11
- | Framing | Baseline tokens (full history) | Injected tokens | Reduction |
12
- |---------|-------------------------------|-----------------|-----------|
13
- | (a) Top-3 startup injection vs full history | 1587 | 228 | 85.6% |
14
- | (b) Per-query injected context (avg) vs full history | 1587 | 232 | 85.4% |
24
+ | Recall latency | Main | Entity overlap |
25
+ | --- | ---: | ---: |
26
+ | Mean | 8.57 ms | 8.05 ms |
27
+ | Median | 7.27 ms | 7.58 ms |
28
+ | p95 | 21.04 ms | 14.94 ms |
29
+ | Maximum | 35.81 ms | 28.38 ms |
15
30
 
16
- Row (a) measures one startup injection of the top-ranked memories. Row (b) averages the injected context across the curated queries to model per-turn retrieval.
31
+ Entity overlap gained hits on 34 questions and lost hits on four, a net gain
32
+ of 30. Precision and recall increased on 48 questions and decreased on five.
33
+ The signal measurably improved retrieval on this corpus, so it is retained.
34
+ Timing is one call per question without warmup and varies with load; the lower
35
+ mean/p95 is not evidence that the added lookup makes retrieval faster. This
36
+ does not establish generalization to other corpora or measure extraction accuracy.
37
+ The rule vocabulary and fixed weight were not tuned against these results.
17
38
 
18
- ## Retrieval relevance
39
+ [Recorded aggregate results](../benchmarks/entity-overlap-results.json) include
40
+ the corpus checksum, shared configuration, runtime, category metrics, and paired
41
+ question counts. To reproduce, run the commands below on `81f987c` with output
42
+ `benchmarks/results/locomo-main.json`, then on this change with output
43
+ `benchmarks/results/locomo-entities.json`. Full per-question reports remain ignored
44
+ local artifacts.
19
45
 
20
- Each query runs through `retrieveMemories` with a limit of 3 results. The returned ids are compared with the expected memory ids. A query counts as a hit if at least one expected memory is returned.
46
+ ## Earlier BM25 comparison
21
47
 
22
- - **Hit-rate:** 100.0% (10 queries)
23
- - **Overall recall:** 100.0%
24
- - **Overall precision:** 33.3%
48
+ The baseline was run first on main at `c06857d`, before changing retrieval.
49
+ Both runs used sessionmem 1.4.0, Node v24.19.0, Linux x64, top-5,
50
+ and the same lockfile dependencies and fixed capture/retrieval clock.
51
+ They captured 5,882 turns across 272 sessions in 10 conversations and scored
52
+ 1,527 questions. The same 446 adversarial, four missing-evidence, and nine
53
+ invalid-evidence questions were excluded by fixed annotation rules.
25
54
 
26
- | Query (memory content) | Expected memory | Recall | Precision |
27
- |------------------------|-----------------|--------|-----------|
28
- | We chose JWT access tokens with a 15-minute expiry and ro... | mem-auth-decision | 100.0% | 33.3% |
29
- | The persistence layer uses better-sqlite3 with WAL mode; ... | mem-db-decision | 100.0% | 33.3% |
30
- | Embeddings are computed offline with a deterministic sha2... | mem-embed-fact | 100.0% | 33.3% |
31
- | Retrieval ranks candidates by a weighted blend of semanti... | mem-retrieval-fact | 100.0% | 33.3% |
32
- | Startup injection formats the top-ranked memories under a... | mem-injection-fact | 100.0% | 33.3% |
33
- | Never edit an already-shipped migration file in place; ad... | mem-migration-warning | 100.0% | 33.3% |
34
- | Redaction must run on every memory-write path before stor... | mem-secret-warning | 100.0% | 33.3% |
35
- | The CLI exposes remember, retention prune, redact-scan, a... | mem-cli-fact | 100.0% | 33.3% |
36
- | Tests use vitest; integration specs seed an in-memory dat... | mem-testing-fact | 100.0% | 33.3% |
37
- | The MCP server runs over stdio and exposes memory retriev... | mem-mcp-decision | 100.0% | 33.3% |
55
+ | Macro retrieval metric @5 | Main (hash ranking) | BM25 + stop words + stemming |
56
+ | --- | ---: | ---: |
57
+ | Hit rate | 1.44% | 61.95% |
58
+ | Precision | 0.29% | 13.45% |
59
+ | Recall | 0.88% | 55.96% |
60
+ | All-evidence rate | 0.65% | 51.15% |
38
61
 
39
- ### Relevance interpretation
62
+ | Recall latency | Main | Selected change |
63
+ | --- | ---: | ---: |
64
+ | Mean | 16.33 ms | 14.93 ms |
65
+ | Median | 15.22 ms | 13.52 ms |
66
+ | p95 | 28.80 ms | 28.81 ms |
67
+ | Maximum | 133.49 ms | 56.73 ms |
40
68
 
41
- `deterministicEmbed` uses a hash-based fingerprint. Identical text has a cosine similarity of 1.0; wording changes produce noisy scores. It supports exact or near-exact recall rather than semantic matching of paraphrases. These queries contain the target memory's content, so the hit-rate measures whether ranking retrieves that memory in that case. Matching paraphrases requires a semantic embedding model. Replacing the embedding model leaves the retrieval and scoring code unchanged, so the benchmark can still exercise those paths.
69
+ Latency includes the complete public service response, including startup-injection
70
+ formatting, and excludes capture, process startup, and corpus loading. Each query
71
+ is timed once without warmup. Timing depends on hardware and load.
42
72
 
43
- ## Reproducing
73
+ | Question category | Questions | Hit rate | Precision | Recall |
74
+ | --- | ---: | ---: | ---: | ---: |
75
+ | Multi-hop | 278 | 46.76% | 13.60% | 25.06% |
76
+ | Temporal | 320 | 69.38% | 14.38% | 66.22% |
77
+ | Open-domain | 89 | 38.20% | 8.09% | 28.25% |
78
+ | Single-hop | 840 | 66.67% | 13.62% | 65.22% |
79
+
80
+ ## Candidate comparisons
81
+
82
+ Each candidate was run with the existing offline evaluator on the same questions.
83
+ Only additions that increased hit rate, precision, and recall were retained.
84
+
85
+ | Candidate @5 | Hit rate | Precision | Recall |
86
+ | --- | ---: | ---: | ---: |
87
+ | BM25 with OR terms | 52.78% | 11.15% | 47.69% |
88
+ | + English stop-word filtering | 57.69% | 12.39% | 52.62% |
89
+ | + Porter stemming (selected) | 61.95% | 13.45% | 55.96% |
90
+ | 90% BM25 / 10% hash cosine (discarded) | 61.76% | 13.43% | 55.78% |
91
+
92
+ BM25 preserves lexical relevance instead of replacing it with hash-vector noise.
93
+ Common question words no longer require a literal match, and SQLite's built-in
94
+ Porter tokenizer matches English inflections. The existing recency, importance,
95
+ expiry, project scope, and no-match vector fallback remain in place. There are
96
+ no new dependencies, API keys, or model downloads. Migration 013 rebuilds the
97
+ existing FTS index; memory content and IDs are preserved.
98
+
99
+ These comparisons use the same corpus used to select the ranker; they are not
100
+ a held-out generalization estimate. BM25 still needs lexical overlap, and a hit
101
+ can leave evidence missing for multi-hop questions. These are annotated-evidence
102
+ retrieval scores, not answer-generation accuracy or summarization quality.
103
+
104
+ ## Reproduce
105
+
106
+ After installing the lockfile dependencies, run on main to record the baseline,
107
+ then repeat on the change:
44
108
 
45
109
  ```bash
46
- npm run build # benchmark imports built functions from dist/
47
- npm run benchmark # regenerates this file deterministically
110
+ npm run build
111
+ npm run benchmark -- --output benchmarks/results/locomo.json
48
112
  ```
49
113
 
50
- _Fixtures are synthetic; the report contains only aggregate metrics and synthetic example content. Generated by `scripts/benchmark.mjs`._
114
+ The corpus is pinned to upstream commit
115
+ `3eb6f2c585f5e1699204e3c3bdf7adc5c28cb376`, SHA-256
116
+ `79fa87e90f04081343b8c8debecb80a9a6842b76a7aa537dc9fdf651ea698ff4`.
117
+ The runner verifies this checksum and blocks network calls. No API keys are
118
+ required. A second full run with an empty environment produced identical
119
+ retrieved IDs and quality metrics for all 1,527 questions. JSON output includes
120
+ every scored question, answer, evidence list, returned IDs, and exclusion reason
121
+ so failures can be inspected. The report above is a recorded result; the command
122
+ prints current results and writes JSON only when requested.
package/docs/migration.md CHANGED
@@ -19,6 +19,8 @@ src/core/schema/migrations/
19
19
 
20
20
  At startup, the runner creates the `_migrations` tracking table if needed and sorts the `.sql` files by name. It applies each migration in its own transaction, skipping any already recorded in `_migrations`. Starting sessionmem again does not reapply completed migrations. There are no down-migrations.
21
21
 
22
+ Migration `015_memory_supersessions.sql` adds derived fact claims, timestamped replacement links, and a view identifying fully superseded memories. It backfills existing records locally in the migration transaction, using full session events for summaries where available. Stored memory content and IDs are preserved. Recall then defaults to current facts; use `includeHistory: true` or `sessionmem search --include-history` to retrieve superseded facts, and `sessionmem history` to inspect their chains.
23
+
22
24
  ### Build-time copy: `copy-migrations`
23
25
 
24
26
  The TypeScript compiler does not copy `.sql` files. The build step `copy-migrations` runs `scripts/copy-migrations.mjs` to copy them from `src/core/schema/migrations/` to `dist/core/schema/migrations/`. This includes the migrations in the published package alongside the compiled code.
@@ -2,6 +2,41 @@
2
2
 
3
3
  This guide covers install failures, adapter (MCP host) issues, and `better-sqlite3` native-build failures. Configuration lives in `~/.sessionmem/config.json`.
4
4
 
5
+ ## Run offline diagnostics
6
+
7
+ ```bash
8
+ sessionmem doctor
9
+ sessionmem doctor --adapter claude-code # select one host explicitly
10
+ ```
11
+
12
+ Doctor prints PASS or FAIL and a fix hint for each problem. Any failed check
13
+ returns a nonzero exit status. It checks:
14
+
15
+ - **Memory store:** the selected database exists, opens, and passes SQLite's quick integrity check. It does not create a missing database.
16
+ - **Schema:** all bundled migrations have been applied. It reports pending or unrecognized migrations without changing the schema.
17
+ - **Hooks, per host:** Claude Code's SessionStart, SessionEnd, and PostToolUse commands, types, matchers, and enabled state match the current version's definitions. Other hosts report that lifecycle hooks are not required.
18
+ - **Adapter wiring, per host:** the installed MCP entry matches the installer, its local command starts, the server version matches, and the expected tools and stats response work. This tests the configured server process without starting the coding agent itself.
19
+ - **Recall:** the real memory service writes and retrieves a canary in a separate temporary project. The transaction is rolled back on success or failure, including index and access-count changes.
20
+
21
+ For Codex, the wiring check supports the installer-generated TOML command and
22
+ args. Custom Codex launch settings require manual verification.
23
+
24
+ All checks work offline, including when cloud summarization is enabled. Doctor
25
+ does not summarize sessions or sync shared memories. It honors `SESSIONMEM_DB_PATH`
26
+ and the same host overrides as install. Keep those environment settings when
27
+ running a suggested repair.
28
+
29
+ Safe repair commands printed by doctor include:
30
+
31
+ ```bash
32
+ sessionmem ping # initialize a missing store / apply pending migrations
33
+ sessionmem install --adapter claude-code # repair MCP registration and hook definitions
34
+ ```
35
+
36
+ Re-run doctor after repair. A corrupt store, a database from a newer version,
37
+ globally disabled hooks, or missing filesystem permissions needs the indicated
38
+ manual repair first; doctor does not delete data or downgrade a schema.
39
+
5
40
  ## Install failures
6
41
 
7
42
  ### `config.json` not written
@@ -10,7 +45,17 @@ This guide covers install failures, adapter (MCP host) issues, and `better-sqlit
10
45
 
11
46
  ### Adapter not detected
12
47
 
13
- `install` registers sessionmem with the MCP host in the current directory. If install reports that it could not find a host, you are likely running it outside a project the host recognizes. `cd` into your project root (where the host's config lives) and re-run `sessionmem install`. Use `sessionmem install --adapter <name>` from a plain terminal (for example `--adapter cline` or `--adapter windsurf`, which cannot be reliably auto-detected). Run `sessionmem ping` afterward to check local database access; it does not probe the host's MCP connection.
48
+ `install` discovers installed hosts from executables on the machine, including
49
+ from a plain terminal. Automatic discovery currently supports Claude Code on
50
+ `PATH`, `~/.local/bin/claude`, or `~/.claude/local/claude` (including Windows
51
+ executable extensions). It does not rely on an active agent session or treat a
52
+ leftover config directory as proof that the host is installed.
53
+
54
+ If no supported host is found, install exits nonzero before creating files. Put
55
+ Claude Code on `PATH` or select a host with `sessionmem install --adapter <name>`.
56
+ Use the flag for other adapters, such as `--adapter cline` or `--adapter windsurf`,
57
+ and for automation. Run `sessionmem doctor --adapter <name>` afterward. The
58
+ `SESSIONMEM_ADAPTER` environment variable is also supported; the flag wins.
14
59
 
15
60
  ### Command not found
16
61
 
@@ -20,11 +65,14 @@ If `sessionmem` is not on your `PATH` after `npm install -g sessionmem`, your np
20
65
 
21
66
  Each MCP host uses its own adapter. If the server starts but memories are missing, check the host's configuration:
22
67
 
23
- - **Claude Code**: if memories are not injected at session start, confirm `sessionmem install` was run inside the project and that the MCP server entry exists in the host config. Use `sessionmem ping` to verify local database access, then check MCP connectivity in the host.
24
- - **Cursor**: Cursor must be pointed at the registered MCP server. Re-run `install` from the project root and restart Cursor so it reloads MCP servers.
68
+ - **Claude Code**: if memories are not injected at session start, run `sessionmem doctor --adapter claude-code`. Re-run `sessionmem install --adapter claude-code` to refresh the registration in `~/.claude.json` and all three hooks in `~/.claude/settings.json`, then restart the agent.
69
+ - **Cursor**: run `sessionmem doctor --adapter cursor`, repair registration with `sessionmem install --adapter cursor`, and restart Cursor so it reloads MCP servers.
25
70
  - **Generic MCP host**: for any other MCP-compatible host, ensure the host is configured to launch `sessionmem run` as the MCP server command. If the host starts but no memory appears, check that the working directory matches the project whose memories you expect.
26
71
 
27
- If commands hang after the host loads, run `sessionmem ping` to check local database access, then check the host's MCP connection.
72
+ If commands hang after the host loads, run `sessionmem doctor --adapter <name>`
73
+ to check the configured MCP command as well as local database access. A missing
74
+ `sessionmem` executable, stale server version, or failed MCP response fails the
75
+ adapter wiring check. Fix `PATH` for the environment that starts your host too.
28
76
 
29
77
  ## "0 sessions" / no session data recorded
30
78
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sessionmem",
3
- "version": "1.4.0",
3
+ "version": "1.6.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Local-first MCP memory layer for coding agents across Claude Code, Codex, Cursor, Cline, Windsurf, and other MCP-compatible hosts.",