memorix 1.4.1 → 1.4.2
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 +19 -0
- package/dist/cli/index.js +1165 -464
- package/dist/index.js +933 -316
- package/dist/maintenance-runner.js +514 -159
- package/dist/media-video-runner.js +514 -159
- package/dist/memcode-runtime/CHANGELOG.md +19 -0
- package/dist/sdk.js +932 -315
- package/dist/vector-backfill-runner.js +514 -159
- package/docs/1.4.2-EVIDENCE-GOVERNED-MEMORY-SPEC.md +434 -0
- package/package.json +1 -1
- package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/copilot/memorix/plugin.json +1 -1
- package/plugins/gemini/memorix/gemini-extension.json +1 -1
- package/plugins/omp/memorix/package.json +1 -1
- package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/pi/memorix/package.json +1 -1
- package/server.json +2 -2
- package/src/cli/commands/codegraph.ts +83 -2
- package/src/codegraph/auto-context.ts +20 -0
- package/src/codegraph/external-provider.ts +1 -0
- package/src/codegraph/store.ts +216 -5
- package/src/codegraph/types.ts +42 -0
- package/src/knowledge/context-assembly.ts +25 -0
- package/src/knowledge/governor.ts +156 -0
- package/src/knowledge/outcome-store.ts +102 -0
- package/src/knowledge/outcome-types.ts +49 -0
- package/src/knowledge/workflows.ts +32 -1
- package/src/knowledge/workset.ts +203 -13
- package/src/store/sqlite-db.ts +42 -0
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
# Memorix 1.4.2: Evidence-Governed Memory and CodeGraph
|
|
2
|
+
|
|
3
|
+
Status: implementation complete; release verification recorded in v1.4.2
|
|
4
|
+
Branch: `codex/1.4.2-evidence-governor`
|
|
5
|
+
Baseline: `v1.4.1`
|
|
6
|
+
Updated: 2026-08-06
|
|
7
|
+
|
|
8
|
+
## One-Sentence Product Contract
|
|
9
|
+
|
|
10
|
+
Memorix should give an agent the smallest useful set of **current, source-backed
|
|
11
|
+
project knowledge**, and should say "do not use memory here" when it cannot
|
|
12
|
+
justify a useful answer.
|
|
13
|
+
|
|
14
|
+
This is not a new prompt wrapper or a second knowledge store. It is the policy
|
|
15
|
+
layer that unifies existing observations, claims, workflows, CodeGraph evidence,
|
|
16
|
+
Git state, and verification results before they reach an agent.
|
|
17
|
+
|
|
18
|
+
## Why This Release Exists
|
|
19
|
+
|
|
20
|
+
The product already has much of the necessary foundation:
|
|
21
|
+
|
|
22
|
+
- source-backed claims and code-reference freshness;
|
|
23
|
+
- versioned CodeGraph snapshots and bounded Worksets;
|
|
24
|
+
- retention, archive, workflow, and background-maintenance primitives;
|
|
25
|
+
- project context through MCP and CLI.
|
|
26
|
+
|
|
27
|
+
Those pieces currently answer related questions in different modules. A memory
|
|
28
|
+
can be relevant but old, source-backed but never verified, or compact but still
|
|
29
|
+
harmful for the current task. 1.4.2 makes the final decision explicit,
|
|
30
|
+
consistent, inspectable, and shared by CLI, MCP, hooks, and dashboard surfaces.
|
|
31
|
+
|
|
32
|
+
## Research Constraints
|
|
33
|
+
|
|
34
|
+
This release follows published findings without overstating what they prove.
|
|
35
|
+
|
|
36
|
+
1. Similar retrieved experiences can cause agents to imitate prior outputs,
|
|
37
|
+
including wrong or misaligned ones. Memory quality and deletion policy are
|
|
38
|
+
product safety concerns, not cleanup cosmetics.
|
|
39
|
+
2. Long-horizon memory needs indexing, retrieval, reading, temporal updates,
|
|
40
|
+
and abstention. Retrieval quality alone is not enough.
|
|
41
|
+
3. Dynamic note links and hierarchical storage are useful only when the source,
|
|
42
|
+
freshness, and revision path remain visible.
|
|
43
|
+
4. Persistent memory is a privacy boundary. Retrieval must preserve scope,
|
|
44
|
+
visibility, and provenance instead of treating all stored text as promptable.
|
|
45
|
+
|
|
46
|
+
The primary research references are listed at the end of this document. Recent
|
|
47
|
+
2026 preprints may guide investigation but do not become product truth without
|
|
48
|
+
reproducible local tests.
|
|
49
|
+
|
|
50
|
+
## Terms
|
|
51
|
+
|
|
52
|
+
| Term | Meaning |
|
|
53
|
+
| --- | --- |
|
|
54
|
+
| Candidate | Any possible context item: observation, claim, workflow, code fact, Git fact, test result, or wiki page. |
|
|
55
|
+
| Evidence | A source that can be checked later: file/symbol hash, CodeGraph snapshot, commit, test/run result, document, or explicit user action. |
|
|
56
|
+
| Qualification | The deterministic check that decides whether a candidate is current enough, visible to this caller, and safe enough to use. |
|
|
57
|
+
| Context plan | The bounded answer to: inject nothing, inject a compact card, inject selected evidence, or schedule more work. |
|
|
58
|
+
| Outcome signal | A later, auditable fact such as a focused test passing, a claim being corrected, or a memory helping a verified task. |
|
|
59
|
+
| Observation period | The period after capture before a memory is promoted to trusted reusable knowledge. |
|
|
60
|
+
|
|
61
|
+
## Non-Negotiable Invariants
|
|
62
|
+
|
|
63
|
+
1. **No automatic context dump.** Existing memory is not a reason to inject it.
|
|
64
|
+
2. **No silent truth rewrite.** A model may propose a link, summary, or
|
|
65
|
+
promotion; it cannot overwrite evidence-backed claims without an auditable
|
|
66
|
+
transition.
|
|
67
|
+
3. **No model-only authority.** Test, Git, code, and explicit user signals outrank
|
|
68
|
+
a generated confidence score.
|
|
69
|
+
4. **No new default MCP tool explosion.** `memorix_project_context` remains the
|
|
70
|
+
primary agent surface. Advanced diagnostics stay grouped and opt-in.
|
|
71
|
+
5. **CLI and MCP parity.** Both construct the same context plan from the same
|
|
72
|
+
policy. Hooks only trigger the plan; they do not own a separate policy.
|
|
73
|
+
6. **Foreground stays fast.** Context assembly may schedule refresh or analysis,
|
|
74
|
+
but never waits for a corpus scan, remote provider, or LLM synthesis.
|
|
75
|
+
7. **Code facts are versioned.** A narrative cannot claim that code is current
|
|
76
|
+
without a matching snapshot or an explicit caution.
|
|
77
|
+
8. **Scope is enforced before relevance.** Personal, project, team, and public
|
|
78
|
+
knowledge do not mix merely because embeddings are similar.
|
|
79
|
+
|
|
80
|
+
## Target Architecture
|
|
81
|
+
|
|
82
|
+
```text
|
|
83
|
+
observations / claims / workflows / wiki / Git / tests / CodeGraph
|
|
84
|
+
|
|
|
85
|
+
v
|
|
86
|
+
candidate collection
|
|
87
|
+
|
|
|
88
|
+
v
|
|
89
|
+
evidence qualification gate
|
|
90
|
+
scope -> provenance -> freshness -> conflict -> quality
|
|
91
|
+
|
|
|
92
|
+
v
|
|
93
|
+
budgeted context planner
|
|
94
|
+
abstain | compact card | selected detail
|
|
95
|
+
|
|
|
96
|
+
v
|
|
97
|
+
MCP / CLI / hook / dashboard explain view
|
|
98
|
+
|
|
|
99
|
+
v
|
|
100
|
+
verified outcomes feed lifecycle and CodeGraph links
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
The governor is deliberately a pure, deterministic core. Storage adapters and
|
|
104
|
+
renderers call it; it does not import an MCP server, hook implementation, or UI.
|
|
105
|
+
|
|
106
|
+
## Data Contracts
|
|
107
|
+
|
|
108
|
+
### 1. Context Candidate
|
|
109
|
+
|
|
110
|
+
```text
|
|
111
|
+
ContextCandidate
|
|
112
|
+
id, kind, projectId, scope, visibility
|
|
113
|
+
title, compactText, sourceRefs
|
|
114
|
+
capturedAt, observedAt
|
|
115
|
+
freshness current | suspect | stale | unknown
|
|
116
|
+
conflict none | possible | confirmed
|
|
117
|
+
quality probation | verified | degraded | blocked
|
|
118
|
+
relevanceSignals lexical, semantic, task-lens, code-link
|
|
119
|
+
estimatedTokens
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Existing records are adapted into candidates. This is not a duplicated store.
|
|
123
|
+
|
|
124
|
+
### 2. Qualification Result
|
|
125
|
+
|
|
126
|
+
```text
|
|
127
|
+
QualificationResult
|
|
128
|
+
candidateId
|
|
129
|
+
disposition include | compact | defer | exclude
|
|
130
|
+
reasons[] stable machine-readable reason codes
|
|
131
|
+
evidenceSummary[] source type, id, snapshot/revision, locator
|
|
132
|
+
qualitySignals[] verified test, successful reuse, user pin, correction
|
|
133
|
+
freshness
|
|
134
|
+
tokenCost
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
An excluded item is visible in diagnostics only. It is never silently presented
|
|
138
|
+
as if it had not existed.
|
|
139
|
+
|
|
140
|
+
### 3. Context Plan
|
|
141
|
+
|
|
142
|
+
```text
|
|
143
|
+
ContextPlan
|
|
144
|
+
task, taskLens, projectState
|
|
145
|
+
mode abstain | card | workset
|
|
146
|
+
selected[] QualificationResult
|
|
147
|
+
deferred[] bounded follow-up suggestions
|
|
148
|
+
cautions[]
|
|
149
|
+
budget requested, used, remaining
|
|
150
|
+
scheduledMaintenance[]
|
|
151
|
+
explanationId
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
`abstain` is a successful result. It means Memorix did not find sufficiently
|
|
155
|
+
qualified context and recommends normal repository inspection instead.
|
|
156
|
+
|
|
157
|
+
### 4. Outcome Signal
|
|
158
|
+
|
|
159
|
+
```text
|
|
160
|
+
MemoryOutcomeSignal
|
|
161
|
+
id, candidateId, projectId, kind
|
|
162
|
+
kind test-pass | test-fail | verified-reuse |
|
|
163
|
+
user-pin | user-correction | source-changed |
|
|
164
|
+
conflict-confirmed | manual-review
|
|
165
|
+
sourceRef, snapshotId, observedAt
|
|
166
|
+
detail sanitized, bounded explanation
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Outcome signals are append-only audit facts. They update a derived quality
|
|
170
|
+
state; they do not erase the original memory. A generic manual review is
|
|
171
|
+
auditable but does not by itself raise quality: verification or an explicit
|
|
172
|
+
user pin is still required.
|
|
173
|
+
|
|
174
|
+
## Lifecycle Policy
|
|
175
|
+
|
|
176
|
+
1. **Capture:** new observations remain usable as local session material but are
|
|
177
|
+
labelled `probation` for durable retrieval.
|
|
178
|
+
2. **Qualify:** source and scope are checked. Code-bound items are matched to a
|
|
179
|
+
snapshot; unbound assertions remain lower confidence.
|
|
180
|
+
3. **Promote:** explicit user pin, review approval, successful verified reuse,
|
|
181
|
+
or source-backed test/Git evidence can promote a candidate.
|
|
182
|
+
4. **Degrade:** changed/deleted source, failing verification, contradiction, or
|
|
183
|
+
a user correction downgrades the derived quality state.
|
|
184
|
+
5. **Archive:** retention rules continue to govern cleanup, but archive decisions
|
|
185
|
+
consume this shared state instead of copying their own freshness formula.
|
|
186
|
+
6. **Recover:** an archived fact can be revisited with its original evidence;
|
|
187
|
+
archive never means invisible deletion by default.
|
|
188
|
+
|
|
189
|
+
No score alone can cause destructive deletion. A score can only suggest a
|
|
190
|
+
review or make a candidate ineligible for automatic injection.
|
|
191
|
+
|
|
192
|
+
## CodeGraph Upgrade
|
|
193
|
+
|
|
194
|
+
### Product Goal
|
|
195
|
+
|
|
196
|
+
CodeGraph becomes the code evidence service for the governor. It should answer
|
|
197
|
+
four practical questions quickly:
|
|
198
|
+
|
|
199
|
+
1. What files and symbols are relevant to this task now?
|
|
200
|
+
2. What changed since this memory or workflow was formed?
|
|
201
|
+
3. What may be affected if this symbol or file changes?
|
|
202
|
+
4. How complete and trustworthy is that structural answer?
|
|
203
|
+
|
|
204
|
+
### New Capabilities
|
|
205
|
+
|
|
206
|
+
#### A. Snapshot Diff
|
|
207
|
+
|
|
208
|
+
The first 1.4.2 slice adds a hash-only **file** manifest to each completed
|
|
209
|
+
snapshot. It can report added, modified, and removed indexed files between two
|
|
210
|
+
complete snapshots. It stores paths and hashes, never a second copy of source.
|
|
211
|
+
|
|
212
|
+
Symbol and relation history are not yet retained per snapshot, so this release
|
|
213
|
+
does **not** pretend to provide historical symbol/edge diffs. Current graph
|
|
214
|
+
relations are used only for the bounded impact slice below.
|
|
215
|
+
|
|
216
|
+
Target shape for later schema evolution:
|
|
217
|
+
|
|
218
|
+
```text
|
|
219
|
+
CodeStateDiff
|
|
220
|
+
fromSnapshotId, toSnapshotId
|
|
221
|
+
added/changed/removed files
|
|
222
|
+
added/changed/removed symbols
|
|
223
|
+
added/changed/removed relations
|
|
224
|
+
completeness delta
|
|
225
|
+
affected observation/claim/workflow references
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
This must report unknowns from incomplete scans. It is not allowed to label an
|
|
229
|
+
unscanned path as unchanged.
|
|
230
|
+
|
|
231
|
+
#### B. Impact Slice
|
|
232
|
+
|
|
233
|
+
Given a file or symbol, return a bounded, explainable graph slice:
|
|
234
|
+
|
|
235
|
+
```text
|
|
236
|
+
ImpactSlice
|
|
237
|
+
root references
|
|
238
|
+
inbound and outbound relations
|
|
239
|
+
direct test/config/workflow references when available
|
|
240
|
+
confidence, coverage, traversal limit, and reasons
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
The first release supports direct edges and a small bounded traversal only. It
|
|
244
|
+
does not claim whole-program call-graph precision.
|
|
245
|
+
|
|
246
|
+
#### Implemented Slice
|
|
247
|
+
|
|
248
|
+
- `memorix codegraph diff` compares the newest two snapshots by default, or
|
|
249
|
+
accepts explicit `--from` and `--to` snapshot ids.
|
|
250
|
+
- `memorix codegraph impact --path <relative-source-path>` exposes the same
|
|
251
|
+
bounded current one-hop graph slice to CLI-only agents. It rejects paths that
|
|
252
|
+
are not in the current index instead of reporting a misleading empty result.
|
|
253
|
+
- A diff is refused when either snapshot is incomplete or predates the manifest
|
|
254
|
+
schema. The result explains why instead of treating absent data as unchanged.
|
|
255
|
+
- The impact view resolves both file edges and symbol edges to current files,
|
|
256
|
+
follows only one hop, and caps relation traversal. It is an inspection aid,
|
|
257
|
+
not a guarantee of complete impact coverage.
|
|
258
|
+
- Lite deterministically resolves local relative import paths, including the
|
|
259
|
+
Node ESM `.js`-from-`.ts` convention. It still does not claim semantic symbol
|
|
260
|
+
resolution or whole-program call-graph precision.
|
|
261
|
+
- A continuation Workset reports how many stale memory bindings point directly
|
|
262
|
+
at the changed snapshot files. It does not attribute unrelated old stale
|
|
263
|
+
memory to the current change.
|
|
264
|
+
- The Workset governor now filters optional claims, workflows, durable memory,
|
|
265
|
+
and code-bound memory before prompt rendering. Its receipt records the safe
|
|
266
|
+
disposition and reason without exposing hidden content. In this first slice,
|
|
267
|
+
task facts, Git state, current code state, and safety cautions remain outside
|
|
268
|
+
the optional-evidence gate so an abstention never hides current source facts.
|
|
269
|
+
|
|
270
|
+
#### C. Test and Verification Links
|
|
271
|
+
|
|
272
|
+
Workflow runs now record an append-only pass/fail signal for their selected
|
|
273
|
+
claims and durable memories. The newest signal is applied only as a delivery
|
|
274
|
+
qualification: a failed verification degrades optional context instead of
|
|
275
|
+
silently rewriting or deleting the original record. A later code change can
|
|
276
|
+
then downgrade the confidence of a memory that says "this is verified" rather
|
|
277
|
+
than leaving an old green test as permanent proof. File/symbol references on
|
|
278
|
+
individual test outcomes remain a later extension.
|
|
279
|
+
|
|
280
|
+
#### D. Provider Coverage Contract
|
|
281
|
+
|
|
282
|
+
Every provider returns:
|
|
283
|
+
|
|
284
|
+
```text
|
|
285
|
+
ProviderCoverage
|
|
286
|
+
provider, parserMode, supportedLanguages
|
|
287
|
+
indexedFiles, skippedFiles, skippedReasons
|
|
288
|
+
relationTypes, confidencePolicy
|
|
289
|
+
snapshotCompleteness
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
CodeGraph Lite remains a mandatory local fallback. Parser-backed or external
|
|
293
|
+
providers are optional accelerators and may only add normalized facts through
|
|
294
|
+
this contract. They cannot bypass project scope, source epoch, or secret rules.
|
|
295
|
+
|
|
296
|
+
#### E. Claim-to-Code Requalification
|
|
297
|
+
|
|
298
|
+
Existing claim and observation code references should consume snapshot diffs:
|
|
299
|
+
|
|
300
|
+
- removed source -> `blocked` or `needs-review`;
|
|
301
|
+
- changed bound source -> `degraded` until rechecked;
|
|
302
|
+
- current source plus fresh verification -> `verified`;
|
|
303
|
+
- incomplete provider coverage -> `unknown`, never falsely `current`.
|
|
304
|
+
|
|
305
|
+
## Retrieval Policy
|
|
306
|
+
|
|
307
|
+
The governor collects candidates first, then applies this order:
|
|
308
|
+
|
|
309
|
+
1. project identity, scope, visibility, and secret policy;
|
|
310
|
+
2. hard exclusions: deleted evidence, forbidden scope, confirmed contradiction;
|
|
311
|
+
3. source freshness and provider completeness;
|
|
312
|
+
4. task lens and direct code/Git/test links;
|
|
313
|
+
5. quality signals and explicit user review;
|
|
314
|
+
6. relevance ranking and diversity;
|
|
315
|
+
7. strict section and total token budgets.
|
|
316
|
+
|
|
317
|
+
Default delivery is progressive:
|
|
318
|
+
|
|
319
|
+
- **abstain:** no qualified advantage; return normal start files only;
|
|
320
|
+
- **card:** one compact "where we were / what changed / what to verify" card;
|
|
321
|
+
- **workset:** selected details with source references and cautions;
|
|
322
|
+
- **defer:** schedule a refresh or requalification without blocking the agent.
|
|
323
|
+
|
|
324
|
+
## Public Experience
|
|
325
|
+
|
|
326
|
+
Normal users still say a natural-language task, for example:
|
|
327
|
+
|
|
328
|
+
> Continue the auth migration. What remains and what must be checked first?
|
|
329
|
+
|
|
330
|
+
They receive a short, useful answer. They do not see score arithmetic.
|
|
331
|
+
|
|
332
|
+
An explicit diagnostic path can answer:
|
|
333
|
+
|
|
334
|
+
```text
|
|
335
|
+
Why did Memorix include or skip this memory?
|
|
336
|
+
Which code snapshot supports it?
|
|
337
|
+
What changed since it was verified?
|
|
338
|
+
How much context budget did it consume?
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
This diagnostic output is grouped under existing context/knowledge diagnostics;
|
|
342
|
+
it is not a new default tool for every graph operation.
|
|
343
|
+
|
|
344
|
+
## Delivery Phases
|
|
345
|
+
|
|
346
|
+
### Phase 0: Baseline and Compatibility
|
|
347
|
+
|
|
348
|
+
- Inventory all existing context ranking, retention, claim, freshness, and
|
|
349
|
+
CodeGraph paths.
|
|
350
|
+
- Add a behavior matrix covering current output and no-regression fixtures.
|
|
351
|
+
- Establish deterministic context-plan fixtures: abstain, compact card, stale
|
|
352
|
+
code caution, conflict exclusion, and incomplete graph coverage.
|
|
353
|
+
|
|
354
|
+
### Phase 1: Governor Core
|
|
355
|
+
|
|
356
|
+
- Implement candidate adapters and pure qualification/context-plan modules.
|
|
357
|
+
- Route `project_context`, `context_pack`, and CLI context/resume through the
|
|
358
|
+
same plan builder without changing their stable output contracts.
|
|
359
|
+
- Add explicit abstention and reason codes.
|
|
360
|
+
|
|
361
|
+
### Phase 2: Outcome and Lifecycle Unification
|
|
362
|
+
|
|
363
|
+
- Add append-only outcome signals and derived candidate quality.
|
|
364
|
+
- Route retention report, HTTP/dashboard status, archive eligibility, and
|
|
365
|
+
claim requalification through one lifecycle evaluation path.
|
|
366
|
+
- Treat test/Git/source changes as higher-quality signals than model estimates.
|
|
367
|
+
|
|
368
|
+
### Phase 3: CodeGraph Evidence Upgrade
|
|
369
|
+
|
|
370
|
+
- Add snapshot diffs, bounded impact slices, coverage reporting, and test/run
|
|
371
|
+
reference links.
|
|
372
|
+
- Requalify claim/observation references from diffs.
|
|
373
|
+
- Add fixture coverage for changed symbol, removed file, incomplete scan, and
|
|
374
|
+
uncertain relation handling.
|
|
375
|
+
|
|
376
|
+
### Phase 4: Explainability and Operator UX
|
|
377
|
+
|
|
378
|
+
- Add context-plan explanations to CLI JSON and grouped diagnostics.
|
|
379
|
+
- Add dashboard views for quality state, source freshness, impact slice, and
|
|
380
|
+
exclusion reason without leaking hidden/private evidence.
|
|
381
|
+
- Keep the normal agent path quiet.
|
|
382
|
+
|
|
383
|
+
### Phase 5: Verification and Release Gate
|
|
384
|
+
|
|
385
|
+
- Run unit, SQLite reopen, provider fallback, CLI, MCP, hook, and packaged
|
|
386
|
+
installation checks.
|
|
387
|
+
- Run isolated agent smoke tests with qualified context, stale context, and
|
|
388
|
+
abstention scenarios.
|
|
389
|
+
- Measure first-turn latency, token usage, stale-context catches, and false
|
|
390
|
+
inclusion/exclusion rates against Phase 0 fixtures.
|
|
391
|
+
|
|
392
|
+
## Acceptance Criteria
|
|
393
|
+
|
|
394
|
+
1. Every automatic inclusion has a machine-readable reason and at least one
|
|
395
|
+
visible source or explicit `unknown` caution.
|
|
396
|
+
2. A changed or deleted code source changes the retrieval disposition without a
|
|
397
|
+
human rediscovering the mismatch.
|
|
398
|
+
3. A task with no qualified memory returns less context, not a generic summary.
|
|
399
|
+
4. CLI, MCP, and hooks select the same qualified evidence for the same task and
|
|
400
|
+
project state.
|
|
401
|
+
5. An incomplete CodeGraph provider result can never be formatted as complete
|
|
402
|
+
code truth.
|
|
403
|
+
6. Test failure, user correction, and source change can lower reusable-memory
|
|
404
|
+
quality; no score-only path deletes a memory.
|
|
405
|
+
7. Existing stored observations, claims, workflows, context commands, and lite
|
|
406
|
+
MCP profile remain backward compatible.
|
|
407
|
+
8. Default MCP tool count does not increase.
|
|
408
|
+
|
|
409
|
+
## Explicit Non-Goals
|
|
410
|
+
|
|
411
|
+
- A remote graph database requirement.
|
|
412
|
+
- Silent LLM rewriting of a project's wiki or workflow.
|
|
413
|
+
- Claiming exact whole-program impact analysis from CodeGraph Lite.
|
|
414
|
+
- Replacing a real language server, CodeGraph product, Git, or test runner.
|
|
415
|
+
- Auto-capturing all conversations, screenshots, or tool outputs.
|
|
416
|
+
- Treating a visual graph as proof of a maintained semantic knowledge graph.
|
|
417
|
+
|
|
418
|
+
## Research References
|
|
419
|
+
|
|
420
|
+
- Xiong et al., "How Memory Management Impacts LLM Agents: An Empirical Study
|
|
421
|
+
of Experience-Following Behavior," ACL 2026.
|
|
422
|
+
https://aclanthology.org/2026.acl-long.27/
|
|
423
|
+
- Wu et al., "LongMemEval: Benchmarking Chat Assistants on Long-Term
|
|
424
|
+
Interactive Memory," ICLR 2025.
|
|
425
|
+
https://iclr.cc/virtual/2025/poster/28290
|
|
426
|
+
- Xu et al., "A-MEM: Agentic Memory for LLM Agents," NeurIPS 2025.
|
|
427
|
+
https://neurips.cc/virtual/2025/poster/119020
|
|
428
|
+
- Kang et al., "Memory OS of AI Agent," EMNLP 2025.
|
|
429
|
+
https://aclanthology.org/2025.emnlp-main.1318
|
|
430
|
+
- Tan et al., "MemBench: Towards More Comprehensive Evaluation on the Memory
|
|
431
|
+
of LLM-based Agents," Findings of ACL 2025.
|
|
432
|
+
https://aclanthology.org/2025.findings-acl.989.pdf
|
|
433
|
+
- Wang et al., "Unveiling Privacy Risks in LLM Agent Memory," ACL 2025.
|
|
434
|
+
https://aclanthology.org/2025.acl-long.1227.pdf
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "memorix",
|
|
3
3
|
"mcpName": "io.github.AVIDS2/memorix",
|
|
4
|
-
"version": "1.4.
|
|
4
|
+
"version": "1.4.2",
|
|
5
5
|
"description": "Local-first shared memory layer for AI coding agents across MCP clients, Git history, reasoning context, and project sessions.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"sideEffects": false,
|
package/server.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"url": "https://github.com/AVIDS2/memorix",
|
|
8
8
|
"source": "github"
|
|
9
9
|
},
|
|
10
|
-
"version": "1.4.
|
|
10
|
+
"version": "1.4.2",
|
|
11
11
|
"websiteUrl": "https://github.com/AVIDS2/memorix#readme",
|
|
12
12
|
"icons": [
|
|
13
13
|
{
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
{
|
|
23
23
|
"registryType": "npm",
|
|
24
24
|
"identifier": "memorix",
|
|
25
|
-
"version": "1.4.
|
|
25
|
+
"version": "1.4.2",
|
|
26
26
|
"runtimeHint": "npx",
|
|
27
27
|
"packageArguments": [
|
|
28
28
|
{
|
|
@@ -58,12 +58,52 @@ function formatUsageHint(): string {
|
|
|
58
58
|
'Usage:',
|
|
59
59
|
' memorix codegraph refresh',
|
|
60
60
|
' memorix codegraph status --json',
|
|
61
|
+
' memorix codegraph diff [--from <snapshot>] [--to <snapshot>]',
|
|
62
|
+
' memorix codegraph impact --path <relative-source-path>',
|
|
61
63
|
' memorix codegraph context-pack --task "continue auth bug"',
|
|
62
64
|
'',
|
|
63
65
|
'Tip: use `memorix context "..."` for new work or `memorix resume "..."` for prior work.',
|
|
64
66
|
].join('\n');
|
|
65
67
|
}
|
|
66
68
|
|
|
69
|
+
function formatDiff(diff: ReturnType<CodeGraphStore['diffSnapshots']>, impact: ReturnType<CodeGraphStore['impactSlice']>): string {
|
|
70
|
+
if (!diff.available) {
|
|
71
|
+
return `CodeGraph diff is unavailable: ${diff.reason ?? 'unknown reason'}. Refresh twice to establish comparable snapshots.`;
|
|
72
|
+
}
|
|
73
|
+
const summary = diff.changes.reduce((counts, change) => {
|
|
74
|
+
counts[change.kind] += 1;
|
|
75
|
+
return counts;
|
|
76
|
+
}, { added: 0, modified: 0, removed: 0 });
|
|
77
|
+
const lines = [
|
|
78
|
+
`CodeGraph diff: ${diff.fromSnapshotId} -> ${diff.toSnapshotId}`,
|
|
79
|
+
`- Changed files: ${diff.changes.length} (${summary.added} added, ${summary.modified} modified, ${summary.removed} removed)`,
|
|
80
|
+
];
|
|
81
|
+
for (const change of diff.changes.slice(0, 20)) lines.push(`- ${change.kind}: ${change.path}`);
|
|
82
|
+
if (diff.changes.length > 20) lines.push(`- ${diff.changes.length - 20} additional file change(s) omitted`);
|
|
83
|
+
if (impact.directlyConnectedPaths.length > 0) {
|
|
84
|
+
lines.push('', 'Current one-hop structural impact');
|
|
85
|
+
for (const path of impact.directlyConnectedPaths.slice(0, 20)) lines.push(`- ${path}`);
|
|
86
|
+
}
|
|
87
|
+
if (impact.relationCount === 0) lines.push('', 'No current file-edge relation was found for the changed paths.');
|
|
88
|
+
if (impact.truncated) lines.push('- Impact relation limit reached; inspect the graph before assuming coverage.');
|
|
89
|
+
return lines.join('\n');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function formatImpact(impact: ReturnType<CodeGraphStore['impactSlice']>): string {
|
|
93
|
+
const lines = [
|
|
94
|
+
`CodeGraph current one-hop impact: ${impact.changedPaths.join(', ')}`,
|
|
95
|
+
`- Relations inspected: ${impact.relationCount}`,
|
|
96
|
+
];
|
|
97
|
+
if (impact.directlyConnectedPaths.length > 0) {
|
|
98
|
+
lines.push('- Directly connected paths:');
|
|
99
|
+
for (const path of impact.directlyConnectedPaths) lines.push(` - ${path}`);
|
|
100
|
+
} else {
|
|
101
|
+
lines.push('- No current file-edge relation was found for this indexed path.');
|
|
102
|
+
}
|
|
103
|
+
if (impact.truncated) lines.push('- Impact relation limit reached; inspect the graph before assuming coverage.');
|
|
104
|
+
return lines.join('\n');
|
|
105
|
+
}
|
|
106
|
+
|
|
67
107
|
function compactFacts(project: { rootPath: string }): { facts: string[]; dirty: boolean } {
|
|
68
108
|
const current = collectCurrentProjectFacts({ project, now: new Date() });
|
|
69
109
|
const facts: string[] = [];
|
|
@@ -82,9 +122,13 @@ export default defineCommand({
|
|
|
82
122
|
description: 'Inspect and refresh CodeGraph Memory for the current project',
|
|
83
123
|
},
|
|
84
124
|
args: {
|
|
85
|
-
action: { type: 'string', description: 'Action: status, refresh, or context-pack' },
|
|
125
|
+
action: { type: 'string', description: 'Action: status, refresh, diff, impact, or context-pack' },
|
|
86
126
|
task: { type: 'string', description: 'Task text for context-pack' },
|
|
127
|
+
path: { type: 'string', description: 'Indexed relative source path for impact' },
|
|
87
128
|
limit: { type: 'string', description: 'Max active memories to inspect for context-pack' },
|
|
129
|
+
from: { type: 'string', description: 'Earlier CodeGraph snapshot id for diff' },
|
|
130
|
+
to: { type: 'string', description: 'Later CodeGraph snapshot id for diff' },
|
|
131
|
+
impactLimit: { type: 'string', description: 'Maximum graph relations to inspect for diff impact' },
|
|
88
132
|
json: { type: 'boolean', description: 'Emit machine-readable JSON output' },
|
|
89
133
|
},
|
|
90
134
|
run: async ({ args }) => {
|
|
@@ -162,6 +206,43 @@ export default defineCommand({
|
|
|
162
206
|
return;
|
|
163
207
|
}
|
|
164
208
|
|
|
209
|
+
case 'diff': {
|
|
210
|
+
const snapshots = store.listSnapshots(project.id, 2);
|
|
211
|
+
const fromSnapshotId = (args.from as string | undefined)?.trim() || snapshots[1]?.id;
|
|
212
|
+
const toSnapshotId = (args.to as string | undefined)?.trim() || snapshots[0]?.id;
|
|
213
|
+
if (!fromSnapshotId || !toSnapshotId) {
|
|
214
|
+
emitError('two completed CodeGraph snapshots are required; run "memorix codegraph refresh" again after a code change.', asJson);
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
const diff = store.diffSnapshots(project.id, fromSnapshotId, toSnapshotId);
|
|
218
|
+
const impact = store.impactSlice(
|
|
219
|
+
project.id,
|
|
220
|
+
diff.changes.map(change => change.path),
|
|
221
|
+
parsePositiveInt(args.impactLimit as string | undefined, 24),
|
|
222
|
+
);
|
|
223
|
+
emitResult({ project, diff, impact }, formatDiff(diff, impact), asJson);
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
case 'impact': {
|
|
228
|
+
const sourcePath = (args.path as string | undefined)?.trim() || positional.slice(1).join(' ').trim();
|
|
229
|
+
if (!sourcePath) {
|
|
230
|
+
emitError('path is required for "memorix codegraph impact"', asJson);
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
if (!store.getFile(project.id, sourcePath)) {
|
|
234
|
+
emitError(`path is not in the current CodeGraph index: ${sourcePath}. Run "memorix codegraph refresh" and retry.`, asJson);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
const impact = store.impactSlice(
|
|
238
|
+
project.id,
|
|
239
|
+
[sourcePath],
|
|
240
|
+
parsePositiveInt(args.impactLimit as string | undefined, 24),
|
|
241
|
+
);
|
|
242
|
+
emitResult({ project, impact }, formatImpact(impact), asJson);
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
|
|
165
246
|
case 'context-pack': {
|
|
166
247
|
const task = (args.task as string | undefined)?.trim() || positional.slice(1).join(' ').trim();
|
|
167
248
|
if (!task) {
|
|
@@ -224,7 +305,7 @@ export default defineCommand({
|
|
|
224
305
|
}
|
|
225
306
|
|
|
226
307
|
default:
|
|
227
|
-
emitError(`unknown codegraph action "${action}". Use "status", "refresh", or "context-pack".`, asJson);
|
|
308
|
+
emitError(`unknown codegraph action "${action}". Use "status", "refresh", "diff", "impact", or "context-pack".`, asJson);
|
|
228
309
|
}
|
|
229
310
|
} catch (error) {
|
|
230
311
|
emitError(error instanceof Error ? error.message : String(error), asJson);
|
|
@@ -259,6 +259,25 @@ export async function buildAutoProjectContext(input: {
|
|
|
259
259
|
const overview = explain.overview;
|
|
260
260
|
const currentFacts = collectCurrentProjectFacts({ project: input.project, now });
|
|
261
261
|
const latestSnapshot = overview.code.latestSnapshot;
|
|
262
|
+
let codeEvolution: TaskWorkset['codeEvolution'];
|
|
263
|
+
if (continuationRequested && latestSnapshot?.previousSnapshotId && latestSnapshot.changedPathCount > 0) {
|
|
264
|
+
const diff = store.diffSnapshots(input.project.id, latestSnapshot.previousSnapshotId, latestSnapshot.id);
|
|
265
|
+
if (diff.available && diff.changes.length > 0) {
|
|
266
|
+
const impact = store.impactSlice(input.project.id, diff.changes.map(change => change.path));
|
|
267
|
+
const changedFileIds = new Set([
|
|
268
|
+
...store.listSnapshotFiles(diff.fromSnapshotId),
|
|
269
|
+
...store.listSnapshotFiles(diff.toSnapshotId),
|
|
270
|
+
].filter(file => diff.changes.some(change => change.path === file.path)).map(file => file.fileId));
|
|
271
|
+
codeEvolution = {
|
|
272
|
+
fromSnapshotId: diff.fromSnapshotId,
|
|
273
|
+
toSnapshotId: diff.toSnapshotId,
|
|
274
|
+
changes: diff.changes.slice(0, 5).map(change => ({ path: change.path, kind: change.kind })),
|
|
275
|
+
directlyConnectedPaths: impact.directlyConnectedPaths.slice(0, 3),
|
|
276
|
+
affectedMemoryCount: store.countStaleObservationRefsForFiles(input.project.id, [...changedFileIds]),
|
|
277
|
+
truncated: impact.truncated || diff.changes.length > 5,
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
}
|
|
262
281
|
const sourceSets = lensSourceSets({ task, lens, explain });
|
|
263
282
|
let externalOutline: ExternalCodeGraphOutline | undefined;
|
|
264
283
|
let externalCaution: string | undefined;
|
|
@@ -348,6 +367,7 @@ export async function buildAutoProjectContext(input: {
|
|
|
348
367
|
currentFacts: worksetFactLines(currentFacts),
|
|
349
368
|
...(continuation ? { continuation } : {}),
|
|
350
369
|
codeState: codeStateLine(overview),
|
|
370
|
+
...(codeEvolution ? { codeEvolution } : {}),
|
|
351
371
|
reliableMemory: sourceSets.reliableSources
|
|
352
372
|
.slice(0, lens.sourceLimit)
|
|
353
373
|
.map(source => ({
|