nexusmem 0.7.0 → 0.9.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/CHANGELOG.md +60 -1
- package/README.md +76 -28
- package/dist/cli/index.js +524 -194
- package/dist/cli/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -11,6 +11,63 @@ built from, matched by publish timestamp: `v0.1.0` → `67a4776`, `v0.1.1` → `
|
|
|
11
11
|
|
|
12
12
|
No unreleased changes yet.
|
|
13
13
|
|
|
14
|
+
## [0.9.0] — 2026-08-27
|
|
15
|
+
|
|
16
|
+
Closes the three remaining mechanisms from a recurring external review (Simon Strandgaard, Agent
|
|
17
|
+
Memory Atlas): trust_state, bi-temporal reads, and a dismiss verb for standing suggestions. Also
|
|
18
|
+
fixes two real Windows-specific correctness bugs found dogfooding.
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- `nodes.trust_state` (`candidate` | `verified` | `rejected`, schema V10) and `nexusmem review
|
|
23
|
+
<nodeId> --verify|--reject`: a human verdict on a node, independent of the SLM contradiction
|
|
24
|
+
checker. `--reject` down-weights ranking (harsher than the existing supersede penalty, since a
|
|
25
|
+
human said no directly); `--verify` is a label only, no ranking boost. Both render as a tag in
|
|
26
|
+
packed context. Never deletes — same demote-not-delete rule as `mark-stale`.
|
|
27
|
+
- `--as-of <date>` on `nexusmem query` and the MCP `search_memory` tool: restricts both the BM25
|
|
28
|
+
and vector arms to nodes recorded at or before that instant via `created_at` (record time),
|
|
29
|
+
independent of how old the events themselves (`ts`, event time) are. Read-only — there is no
|
|
30
|
+
equivalent write, and nodes stay write-once.
|
|
31
|
+
- `nexusmem stale --dismiss`: silences a contradiction suggestion the user disagrees with, without
|
|
32
|
+
fabricating a `supersedes` relationship. Previously a wrong `--check-contradictions` verdict had
|
|
33
|
+
no way to be rejected — it re-decorated every future `stale`/`sync` run forever.
|
|
34
|
+
- `--prune-source`/`--prune-stale-shell` now record a `mutation_audit` row on their `--yes` path,
|
|
35
|
+
matching what `forget` already did. The dry-run preview stays a pure read.
|
|
36
|
+
|
|
37
|
+
### Fixed
|
|
38
|
+
|
|
39
|
+
- `git rev-parse` failures reported as "error launching git: Access is denied." (Git for Windows'
|
|
40
|
+
launcher shim failing to exec `git.exe` under handle/AV contention) were treated as git's own
|
|
41
|
+
verdict instead of a transient spawn failure, turning a one-off environment hiccup into a hard
|
|
42
|
+
failure. Now retried the same as the other known transient-spawn classes.
|
|
43
|
+
- The PowerShell prompt hook read only `$LASTEXITCODE`, which cmdlets (`Remove-Item`, `Copy-Item`,
|
|
44
|
+
…) never set — every failing cmdlet was silently logged as a success, and a stale
|
|
45
|
+
`$LASTEXITCODE` from an earlier native command could misattribute to later successful cmdlet
|
|
46
|
+
runs. Now reads `$?` alongside `$LASTEXITCODE`, before anything else can overwrite `$?`.
|
|
47
|
+
|
|
48
|
+
## [0.8.0] — 2026-08-22
|
|
49
|
+
|
|
50
|
+
### Added
|
|
51
|
+
|
|
52
|
+
- Provenance widened from 2 tiers to a 4-tier trust hierarchy: `observed` (commits, diffs, shell
|
|
53
|
+
exit codes) > `authored` (doc sections — human-written claims) > `recorded` (conversation turns —
|
|
54
|
+
verbatim discourse) > `derived` (session summaries — a model's distillation). Schema V7 backfills
|
|
55
|
+
existing databases by kind. The ranker decays each tier at its own rate (lower trust fades
|
|
56
|
+
faster); the ordering is the design claim, the exact ratios are documented judgment calls.
|
|
57
|
+
- Contradiction checking now runs automatically during `sync`: at most 3 new SLM judgments per run
|
|
58
|
+
(`contradictions.maxPerSync`; `contradictions.autoCheck: false` turns it off), gated on the
|
|
59
|
+
embedding provider already being reachable. Every judgment — either verdict — is memoized in a new
|
|
60
|
+
`contradiction_checks` table (schema V8), so a judged pair is never sent to the model again and
|
|
61
|
+
repeat syncs converge to zero model calls. Measured live against this repo's own database: 5.4s
|
|
62
|
+
for the first 10 judgments, 0.5s for the identical re-run. Still suggest-only: nothing ever writes
|
|
63
|
+
`supersedes` automatically.
|
|
64
|
+
- Standing suggestions now surface everywhere without a model in the loop: plain `nexusmem stale`
|
|
65
|
+
decorates flagged candidates from the memoized judgments (instant, offline), `nexusmem status`
|
|
66
|
+
gains a `flagged` line, and the sync summary reports new/open suggestion counts.
|
|
67
|
+
- `stale --check-contradictions` reuses each candidate's stored embedding instead of re-embedding
|
|
68
|
+
it, and stops after two consecutive null SLM replies so a down provider costs at most two timeouts
|
|
69
|
+
rather than one per candidate.
|
|
70
|
+
|
|
14
71
|
## [0.7.0] — 2026-08-21
|
|
15
72
|
|
|
16
73
|
### Added
|
|
@@ -481,7 +538,9 @@ First public release.
|
|
|
481
538
|
there is no local-model summarization pass, and the conversation collector has never been audited
|
|
482
539
|
for the stale-node bug that was found and fixed in the docs collector.
|
|
483
540
|
|
|
484
|
-
[Unreleased]: https://github.com/yaminbkk/NexusMem/compare/v0.
|
|
541
|
+
[Unreleased]: https://github.com/yaminbkk/NexusMem/compare/v0.9.0...HEAD
|
|
542
|
+
[0.9.0]: https://github.com/yaminbkk/NexusMem/compare/v0.8.0...v0.9.0
|
|
543
|
+
[0.8.0]: https://github.com/yaminbkk/NexusMem/compare/v0.7.0...v0.8.0
|
|
485
544
|
[0.7.0]: https://github.com/yaminbkk/NexusMem/compare/v0.6.0...v0.7.0
|
|
486
545
|
[0.6.0]: https://github.com/yaminbkk/NexusMem/compare/v0.5.4...v0.6.0
|
|
487
546
|
[0.5.4]: https://github.com/yaminbkk/NexusMem/compare/v0.5.3...v0.5.4
|
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ exists nowhere else, and it disappears when your terminal scrollback rolls over.
|
|
|
24
24
|
**Contents:** [Try it](#try-it) · [Exact shell capture](#optional-exact-shell-capture) ·
|
|
25
25
|
[Failure → fix chains](#failure--fix-chains-opt-in) · [How retrieval works](#how-retrieval-works) ·
|
|
26
26
|
[Session summaries](#session-summaries-optional-local-model) · [Use it from an agent](#use-it-from-an-agent)
|
|
27
|
-
· [What it costs you](#what-it-costs-you) · [
|
|
27
|
+
· [What it costs you](#what-it-costs-you) · [Staleness & provenance](#staleness--provenance) ·
|
|
28
28
|
[Where it breaks](#where-it-breaks) · [Commands](#commands) · [Cross-project recall](#recall-across-projects)
|
|
29
29
|
· [On disk](#on-disk) · [Development](#development)
|
|
30
30
|
|
|
@@ -48,11 +48,11 @@ Relevant history for: windows spawn failure
|
|
|
48
48
|
readRepoInfo collapsed three unrelated failures into one error: git running and reporting
|
|
49
49
|
the path is not a work tree, git not being installed, and the process failing to spawn at
|
|
50
50
|
all. Dogfooding hit the third case in two separate sessions...
|
|
51
|
-
- 2026-08-09 [
|
|
51
|
+
- 2026-08-09 [authored] README.md — Before a tagged release
|
|
52
52
|
- [ ] Retry on transient process-spawn failures on Windows
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
-
`[observed]`/`[
|
|
55
|
+
`[observed]`/`[authored]` is the provenance tag (see [Staleness & provenance](#staleness--provenance))
|
|
56
56
|
— a commit is a directly observed event, a doc section is a written claim that could go stale.
|
|
57
57
|
|
|
58
58
|
A commit and a docs section, ranked against each other, inside whatever token budget you gave it.
|
|
@@ -248,7 +248,9 @@ One thing that is not a percentage: shell commands and conversation turns have n
|
|
|
248
248
|
equivalent. Without something recording them, they are gone, not merely more expensive to find.
|
|
249
249
|
|
|
250
250
|
For how these numbers compare to a similar tool's own claims, see
|
|
251
|
-
[`docs/competitor-comparison.md`](docs/competitor-comparison.md).
|
|
251
|
+
[`docs/competitor-comparison.md`](docs/competitor-comparison.md) (vs. projectmem) and
|
|
252
|
+
[`docs/competitor-comparison-yesmem.md`](docs/competitor-comparison-yesmem.md) (vs. YesMem, including
|
|
253
|
+
native Windows support vs. its documented WSL2 requirement).
|
|
252
254
|
|
|
253
255
|
Latency on a ~530-node corpus, warm, p50 over 10 runs:
|
|
254
256
|
|
|
@@ -269,19 +271,23 @@ Two things a memory layer needs and this one only partly has: a way to tell an o
|
|
|
269
271
|
guess, and a way to retire a conclusion once something contradicts it. This section is what exists
|
|
270
272
|
and what doesn't.
|
|
271
273
|
|
|
272
|
-
Every node carries a `provenance
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
274
|
+
Every node carries a `provenance`, a four-tier trust hierarchy set once per collector at ingest
|
|
275
|
+
time: `observed` (a commit that landed, a shell command's real exit code) > `authored` (a doc
|
|
276
|
+
section — a human's own written claim) > `recorded` (a conversation turn — verbatim, but talk about
|
|
277
|
+
events rather than the events) > `derived` (a session summary — a model's distillation). The tier is
|
|
278
|
+
shown as a tag on every query result and decays retrieval weight — the lower the trust, the faster a
|
|
279
|
+
node fades from ranking as it ages. The ordering is the design claim; the exact decay ratios are
|
|
280
|
+
judgment calls, not measured optima.
|
|
277
281
|
|
|
278
282
|
```bash
|
|
279
283
|
nexusmem stale
|
|
280
284
|
```
|
|
281
285
|
|
|
282
|
-
Lists `
|
|
283
|
-
a heuristic on age and provenance, not on content. It writes nothing; you decide which
|
|
284
|
-
actually wrong.
|
|
286
|
+
Lists non-`observed` nodes old enough (45+ days by default) that nothing has confirmed they still
|
|
287
|
+
hold — a heuristic on age and provenance, not on content. It writes nothing; you decide which
|
|
288
|
+
candidates are actually wrong. Any candidate the SLM has already flagged (see below) is decorated
|
|
289
|
+
with its standing `likely superseded by` suggestion — reading those costs nothing, so the plain
|
|
290
|
+
command stays instant and offline.
|
|
285
291
|
|
|
286
292
|
```bash
|
|
287
293
|
nexusmem mark-stale <oldNodeId> --supersedes <newNodeId>
|
|
@@ -297,15 +303,35 @@ nexusmem stale --check-contradictions
|
|
|
297
303
|
For each candidate, finds the most similar newer node (local embedding search) and asks a local SLM
|
|
298
304
|
(Ollama, `qwen2.5:3b` by default) whether it actually contradicts the older one — real content
|
|
299
305
|
comparison, not just age. A match is printed as `likely superseded by <id> <title> -- <reason>`
|
|
300
|
-
under the candidate
|
|
301
|
-
|
|
302
|
-
|
|
306
|
+
under the candidate. Every judgment (either verdict) is memoized, so a judged pair is never sent to
|
|
307
|
+
the model again; nothing else is written — `supersedes` stays yours to set via `mark-stale`.
|
|
308
|
+
|
|
309
|
+
**This also runs automatically during `sync`** — at most 3 new judgments per run (configurable via
|
|
310
|
+
the `contradictions` block in `.nexusmem/config.json`; set `autoCheck: false` to turn it off), only
|
|
311
|
+
when the embedding provider was reachable anyway, and free on repeat syncs thanks to the
|
|
312
|
+
memoization. New and open suggestions show up in the sync summary, `nexusmem status` (a `flagged`
|
|
313
|
+
line), and plain `nexusmem stale`.
|
|
303
314
|
|
|
304
315
|
**What this doesn't do:** it is one small model's yes/no judgment on one older/newer pair, not a
|
|
305
316
|
verified fact — treat a match as a lead to check, not a conclusion. It also only ever compares a
|
|
306
317
|
candidate against nodes *found by embedding similarity*; a contradiction from an unrelated-sounding
|
|
307
|
-
node would never surface.
|
|
308
|
-
|
|
318
|
+
node would never surface. Comprehensive contradiction detection (not just for the pair the vector
|
|
319
|
+
search happens to surface) is still an open problem, and nothing here supersedes a node on its own.
|
|
320
|
+
|
|
321
|
+
`provenance` is a separate question from `trust_state`: provenance says where a claim came from,
|
|
322
|
+
never whether anyone checked it.
|
|
323
|
+
|
|
324
|
+
```bash
|
|
325
|
+
nexusmem review <nodeId> --verify
|
|
326
|
+
nexusmem review <nodeId> --reject
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
Records your own verdict on one node, independent of the SLM contradiction checker above (which only
|
|
330
|
+
ever writes a suggestion, never a verdict). `--reject` down-weights the node in ranking — same
|
|
331
|
+
demote-not-delete rule as `mark-stale`, it stays queryable, just usually loses to better matches —
|
|
332
|
+
and both verdicts are shown as a `[verified]`/`[rejected]` tag on every query result that returns the
|
|
333
|
+
node afterward. `--verify` is a label only; it does not boost ranking. Every node starts `candidate`
|
|
334
|
+
(untagged) until reviewed, and a re-sync never overwrites a verdict once one is set.
|
|
309
335
|
|
|
310
336
|
## Where it breaks
|
|
311
337
|
|
|
@@ -372,16 +398,20 @@ vector search happens to surface) is still an open problem.
|
|
|
372
398
|
|
|
373
399
|
## Commands
|
|
374
400
|
|
|
375
|
-
`init`, `sync`, `query <text
|
|
376
|
-
somewhere), `projects`, `mcp`, `forget <value>`,
|
|
377
|
-
content check, see above), `mark-stale
|
|
378
|
-
`
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
`
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
401
|
+
`init`, `sync`, `query <text>` (add `--as-of <date>` for a bi-temporal read, see below), `status` (add
|
|
402
|
+
`--share` for a plain-text summary worth pasting somewhere), `projects`, `mcp`, `forget <value>`,
|
|
403
|
+
`stale` (add `--check-contradictions` for a local-SLM content check, see above), `mark-stale
|
|
404
|
+
<nodeId> --supersedes <newNodeId>`, `review <nodeId> --verify|--reject` (record a human verdict on
|
|
405
|
+
one node, see above), `precheck` (advisory — warns about staged files with an unresolved past
|
|
406
|
+
failure or high recent churn; exits 0 unless `--strict`), `hook install|remove|status` (the
|
|
407
|
+
PowerShell exit-code hook), and `hook git install|remove|status` (a git pre-commit hook that runs
|
|
408
|
+
`precheck` before each commit).
|
|
409
|
+
|
|
410
|
+
There are also seven dry-run previews (`scan-git`, `scan-diff`, `scan-shell`, `scan-docs`,
|
|
411
|
+
`scan-conversation`, `scan-session`, `scan-structure`) that write nothing and print what ingestion
|
|
412
|
+
*would* produce — nodes and their signal scores for the first six, import-graph edges for
|
|
413
|
+
`scan-structure`. That is the intended way to tune scoring against a real repository before
|
|
414
|
+
committing to a change. Add `--json` to pipe them somewhere.
|
|
385
415
|
|
|
386
416
|
Every command takes `-C <path>` to target another repository. On `sync`, `--conversation` opts the
|
|
387
417
|
transcript source in for one run without persisting it, `--no-embed` skips the vector pass,
|
|
@@ -414,6 +444,24 @@ scope 2 project(s): NexusMem, uploader
|
|
|
414
444
|
- 2026-08-09 [observed] [NexusMem] fix(git): retry a transient failure to spawn git
|
|
415
445
|
```
|
|
416
446
|
|
|
447
|
+
## Bi-temporal reads
|
|
448
|
+
|
|
449
|
+
Every node carries two clocks: `ts`, the event's own time ("what happened then"), and `created_at`,
|
|
450
|
+
the moment the store actually recorded it ("what did the store hold then") — normally the same
|
|
451
|
+
question, but not when a sync runs late, a backfill lands weeks after the events it describes, or a
|
|
452
|
+
teammate's clone catches up all at once. `query`/`search_memory` answer the first by default;
|
|
453
|
+
`--as-of <date>` switches to the second:
|
|
454
|
+
|
|
455
|
+
```bash
|
|
456
|
+
nexusmem query "why does the ranker cap joint priors" --as-of 2026-08-10
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
Only nodes recorded at or before that instant are considered, even if the events they describe are
|
|
460
|
+
older still. There is no equivalent write — this is a read-time filter over `created_at`, not a
|
|
461
|
+
snapshot or a way to query a value that has since changed, since nodes are write-once (see
|
|
462
|
+
[Staleness & provenance](#staleness--provenance) for what changes a node's *weight*, not its
|
|
463
|
+
record).
|
|
464
|
+
|
|
417
465
|
Databases stay per-repository — there is no shared global store, and deleting one repo's
|
|
418
466
|
`.nexusmem/` still removes exactly that repo's memory. What makes the others findable is a plain
|
|
419
467
|
index at `~/.nexusmem/projects.json`, written by `init` and refreshed by every `sync`. `nexusmem
|
|
@@ -449,7 +497,7 @@ Deleting `.nexusmem/` loses nothing that `sync` cannot rebuild.
|
|
|
449
497
|
|
|
450
498
|
## Status
|
|
451
499
|
|
|
452
|
-
Ingestion, hybrid retrieval, budgeted packing and the MCP server all work and are covered by
|
|
500
|
+
Ingestion, hybrid retrieval, budgeted packing and the MCP server all work and are covered by 701
|
|
453
501
|
tests running on Linux and Windows across Node 22 and 24.
|
|
454
502
|
|
|
455
503
|
## Development
|