memgrid 0.5.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 +80 -0
- package/LICENSE +21 -0
- package/README.md +251 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/learn/index.d.ts +44 -0
- package/dist/learn/index.d.ts.map +1 -0
- package/dist/learn/index.js +234 -0
- package/dist/learn/index.js.map +1 -0
- package/dist/memgrid.d.ts +50 -0
- package/dist/memgrid.d.ts.map +1 -0
- package/dist/memgrid.js +175 -0
- package/dist/memgrid.js.map +1 -0
- package/dist/retrieve/index.d.ts +27 -0
- package/dist/retrieve/index.d.ts.map +1 -0
- package/dist/retrieve/index.js +209 -0
- package/dist/retrieve/index.js.map +1 -0
- package/dist/retrieve/semantic.d.ts +67 -0
- package/dist/retrieve/semantic.d.ts.map +1 -0
- package/dist/retrieve/semantic.js +240 -0
- package/dist/retrieve/semantic.js.map +1 -0
- package/dist/scanner/composite.d.ts +27 -0
- package/dist/scanner/composite.d.ts.map +1 -0
- package/dist/scanner/composite.js +58 -0
- package/dist/scanner/composite.js.map +1 -0
- package/dist/scanner/config.d.ts +15 -0
- package/dist/scanner/config.d.ts.map +1 -0
- package/dist/scanner/config.js +167 -0
- package/dist/scanner/config.js.map +1 -0
- package/dist/scanner/golang.d.ts +19 -0
- package/dist/scanner/golang.d.ts.map +1 -0
- package/dist/scanner/golang.js +190 -0
- package/dist/scanner/golang.js.map +1 -0
- package/dist/scanner/index.d.ts +11 -0
- package/dist/scanner/index.d.ts.map +1 -0
- package/dist/scanner/index.js +10 -0
- package/dist/scanner/index.js.map +1 -0
- package/dist/scanner/javascript.d.ts +20 -0
- package/dist/scanner/javascript.d.ts.map +1 -0
- package/dist/scanner/javascript.js +167 -0
- package/dist/scanner/javascript.js.map +1 -0
- package/dist/scanner/markdown.d.ts +17 -0
- package/dist/scanner/markdown.d.ts.map +1 -0
- package/dist/scanner/markdown.js +106 -0
- package/dist/scanner/markdown.js.map +1 -0
- package/dist/scanner/python.d.ts +19 -0
- package/dist/scanner/python.d.ts.map +1 -0
- package/dist/scanner/python.js +177 -0
- package/dist/scanner/python.js.map +1 -0
- package/dist/scanner/rules.d.ts +15 -0
- package/dist/scanner/rules.d.ts.map +1 -0
- package/dist/scanner/rules.js +86 -0
- package/dist/scanner/rules.js.map +1 -0
- package/dist/scanner/rust.d.ts +18 -0
- package/dist/scanner/rust.d.ts.map +1 -0
- package/dist/scanner/rust.js +178 -0
- package/dist/scanner/rust.js.map +1 -0
- package/dist/scanner/scanner.d.ts +33 -0
- package/dist/scanner/scanner.d.ts.map +1 -0
- package/dist/scanner/scanner.js +2 -0
- package/dist/scanner/scanner.js.map +1 -0
- package/dist/scanner/typescript.d.ts +28 -0
- package/dist/scanner/typescript.d.ts.map +1 -0
- package/dist/scanner/typescript.js +522 -0
- package/dist/scanner/typescript.js.map +1 -0
- package/dist/serve/cli.d.ts +3 -0
- package/dist/serve/cli.d.ts.map +1 -0
- package/dist/serve/cli.js +145 -0
- package/dist/serve/cli.js.map +1 -0
- package/dist/serve/mcp-server.d.ts +11 -0
- package/dist/serve/mcp-server.d.ts.map +1 -0
- package/dist/serve/mcp-server.js +276 -0
- package/dist/serve/mcp-server.js.map +1 -0
- package/dist/shared/constants.d.ts +2 -0
- package/dist/shared/constants.d.ts.map +1 -0
- package/dist/shared/constants.js +2 -0
- package/dist/shared/constants.js.map +1 -0
- package/dist/shared/types.d.ts +99 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/types.js +3 -0
- package/dist/shared/types.js.map +1 -0
- package/dist/store/file-store.d.ts +62 -0
- package/dist/store/file-store.d.ts.map +1 -0
- package/dist/store/file-store.js +241 -0
- package/dist/store/file-store.js.map +1 -0
- package/dist/store/index.d.ts +3 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +2 -0
- package/dist/store/index.js.map +1 -0
- package/dist/sync/index.d.ts +56 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +580 -0
- package/dist/sync/index.js.map +1 -0
- package/package.json +51 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to MemGrid.
|
|
4
|
+
|
|
5
|
+
## v0.5.0 — Multi-Language + Incremental Sync (2026-06-28)
|
|
6
|
+
|
|
7
|
+
### Added — Language-Agnostic Scanner Architecture
|
|
8
|
+
- `Scanner` interface: `name`, `scan()`, `scanFiles?()`, `detect()`
|
|
9
|
+
- `CompositeScanner`: auto-detects and composes multiple language scanners
|
|
10
|
+
- **TypeScript** — `ts-morph` AST (classes, methods, exported functions, call graph associations)
|
|
11
|
+
- **JavaScript** — regex (exported functions, classes, arrow functions)
|
|
12
|
+
- **Python** — regex (functions, classes, decorators, docstrings)
|
|
13
|
+
- **Go** — regex (functions, methods, structs, interfaces)
|
|
14
|
+
- **Rust** — regex (functions, structs, enums, traits, impl blocks)
|
|
15
|
+
- **Markdown** — headings as knowledge units from any `.md` file
|
|
16
|
+
- **Rules** — `.claude/rules/*.md` → pattern + trigger units (universal, extracted from TS scanner)
|
|
17
|
+
- **Config** — `package.json`, `pyproject.toml`, `go.mod`, `Cargo.toml`, `docker-compose.yml` (universal)
|
|
18
|
+
|
|
19
|
+
### Added — Incremental Sync
|
|
20
|
+
- `memgrid sync` CLI command for incremental re-scan after code changes
|
|
21
|
+
- `mg.sync()` API: hash-based file diff against baseline snapshot
|
|
22
|
+
- File snapshots stored in `mesh.json.fileSnapshot` (SHA-256 per scanned file)
|
|
23
|
+
- Fuzzy match repair: Jaccard + Dice similarity for fixing broken associations
|
|
24
|
+
- Stale detection: marks orphaned units when source files are deleted
|
|
25
|
+
- Fast path: 0 changes detected in ~5ms (hash compare only)
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
- `mg.init()` now records initial file snapshot for future syncs
|
|
29
|
+
- `MemoryGrid` type extended with optional `fileSnapshot`
|
|
30
|
+
|
|
31
|
+
### Performance
|
|
32
|
+
| Scenario | Time |
|
|
33
|
+
|----------|------|
|
|
34
|
+
| Sync 0 changes | ~5ms |
|
|
35
|
+
| Sync 1 file | ~2s |
|
|
36
|
+
| Sync 5 files (typical PR) | ~2-3s |
|
|
37
|
+
| Full init (150 units) | ~10s |
|
|
38
|
+
|
|
39
|
+
## v0.4.0 — Hybrid Semantic Search (2026-06-27)
|
|
40
|
+
|
|
41
|
+
### Added
|
|
42
|
+
- Hybrid search: combines MiniSearch (keyword) with semantic similarity
|
|
43
|
+
- Configurable `semanticWeight` (0.0 = pure keyword, 1.0 = pure semantic)
|
|
44
|
+
- Keyword embedding provider built-in (no external API required)
|
|
45
|
+
- `--semantic` flag on CLI search command
|
|
46
|
+
|
|
47
|
+
### Performance
|
|
48
|
+
- 10 searches: 670ms → 3ms (223x improvement)
|
|
49
|
+
- Repeated queries: 0ms (LRU cache)
|
|
50
|
+
- Disk reload: 45ms → 5ms (9x, switched from YAML to JSON)
|
|
51
|
+
|
|
52
|
+
## v0.3.0 — Auto-Learning Engine (2026-06-27)
|
|
53
|
+
|
|
54
|
+
### Added
|
|
55
|
+
- Post-task analysis: `mg.analyzeTask()` detects new methods, patterns, errors, decisions
|
|
56
|
+
- `mg.applySuggestions()` writes learning results back to grid
|
|
57
|
+
- `mg.formatSuggestions()` renders diff for human review
|
|
58
|
+
- Learning suggestion types: `add`, `archive`, `update_confidence`
|
|
59
|
+
|
|
60
|
+
### Changed
|
|
61
|
+
- Memory unit meta fields: `confidence` (0.0-1.0) and `status` (active/stale/archived)
|
|
62
|
+
|
|
63
|
+
## v0.2.0 — MCP Server + Tests (2026-06-26)
|
|
64
|
+
|
|
65
|
+
### Added
|
|
66
|
+
- Full MCP (Model Context Protocol) server via `memgrid serve`
|
|
67
|
+
- MCP tools: `memgrid_search`, `memgrid_context`
|
|
68
|
+
- Test suite with Vitest
|
|
69
|
+
- Septonir project integration test
|
|
70
|
+
|
|
71
|
+
## v0.1.0 — Core Engine (2026-06-26)
|
|
72
|
+
|
|
73
|
+
### Added
|
|
74
|
+
- TypeScript AST scanning with `ts-morph`: extracts methods, classes, exported functions
|
|
75
|
+
- Rule extraction from `.claude/rules/*.md` (sections → pattern/trigger units)
|
|
76
|
+
- Example extraction from `.claude/examples/` (good/bad patterns)
|
|
77
|
+
- Config extraction from `package.json`, `docker-compose.yml`
|
|
78
|
+
- Association graph building (call graph, pattern matching)
|
|
79
|
+
- CLI: `init`, `search`, `add`, `stats`
|
|
80
|
+
- File-based storage in `.claude/memory-grid/`
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 wenliangw
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
# MemGrid
|
|
2
|
+
|
|
3
|
+
> Project-level semantic memory for AI coding agents. Replaces full-codebase context loading with a self-evolving knowledge-mesh.
|
|
4
|
+
|
|
5
|
+
## 🧠 What is MemGrid?
|
|
6
|
+
|
|
7
|
+
MemGrid builds a **memory mesh** of your project — not as flat documents, but as interconnected **knowledge units**. Each unit represents one thing: a method, a component, a design pattern, a bug fix, a coding style preference, or a tooling rule.
|
|
8
|
+
|
|
9
|
+
When an AI coding agent starts a task, instead of dumping your entire codebase into context, MemGrid retrieves only the relevant units — and traverses their associations to pull in related context.
|
|
10
|
+
|
|
11
|
+
Think of it as **your project's persistent brain** that gets sharper with every task.
|
|
12
|
+
|
|
13
|
+
## 🎯 The Problem
|
|
14
|
+
|
|
15
|
+
AI coding tools today face a context dilemma:
|
|
16
|
+
|
|
17
|
+
- Load the whole project → massive token waste, slow responses, OOM
|
|
18
|
+
- Load only open files → no context, generic output, repeated mistakes
|
|
19
|
+
- Start fresh every session → no learning, inconsistent style
|
|
20
|
+
|
|
21
|
+
MemGrid solves this by giving the agent exactly what it needs, nothing it doesn't.
|
|
22
|
+
|
|
23
|
+
## 📐 Architecture
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
┌─────────────────────────────────────────┐
|
|
27
|
+
│ MemGrid (Agent Brain) │
|
|
28
|
+
│ │
|
|
29
|
+
│ ┌────────────────────────────────────┐ │
|
|
30
|
+
│ │ Scheduler Layer (Meta-Cognition) │ │
|
|
31
|
+
│ │ skill_trigger / mcp_trigger │ │
|
|
32
|
+
│ │ rule_trigger │ │
|
|
33
|
+
│ │ "What tool for what task" │ │
|
|
34
|
+
│ └──────────┬─────────────────────────┘ │
|
|
35
|
+
│ │ drives │
|
|
36
|
+
│ ┌──────────▼─────────────────────────┐ │
|
|
37
|
+
│ │ Knowledge Layer (Semantics) │ │
|
|
38
|
+
│ │ method / component / pattern │ │
|
|
39
|
+
│ │ config / error_solution │ │
|
|
40
|
+
│ │ "What this project is" │ │
|
|
41
|
+
│ └──────────┬─────────────────────────┘ │
|
|
42
|
+
│ │ shapes │
|
|
43
|
+
│ ┌──────────▼─────────────────────────┐ │
|
|
44
|
+
│ │ Style Layer (Your DNA) │ │
|
|
45
|
+
│ │ style_preference │ │
|
|
46
|
+
│ │ architecture_principle │ │
|
|
47
|
+
│ │ decision (why we did this) │ │
|
|
48
|
+
│ │ "What your code looks like" │ │
|
|
49
|
+
│ └────────────────────────────────────┘ │
|
|
50
|
+
└─────────────────────────────────────────┘
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## 🚀 Quick Start
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npm install -g memgrid
|
|
57
|
+
# or
|
|
58
|
+
pnpm add -g memgrid
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Initialize
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
cd your-project
|
|
65
|
+
memgrid init
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
MemGrid auto-detects your project's languages and scans all relevant source files.
|
|
69
|
+
|
|
70
|
+
**Supported languages:** TypeScript, JavaScript, Python, Go, Rust, and any Markdown documentation.
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# Example output for a TypeScript + Markdown + Rules project:
|
|
74
|
+
# 🔍 Scanning project (typescript, markdown, rules, config)...
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
The grid is stored in `.claude/memory-grid/`.
|
|
78
|
+
|
|
79
|
+
### Search
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# Hybrid search (keyword + semantic, configurable weight)
|
|
83
|
+
memgrid search "add file upload to creation endpoint"
|
|
84
|
+
|
|
85
|
+
# With options
|
|
86
|
+
memgrid search "error handling pattern" --semantic 0.6 --max 5 --hops 2
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Incremental Sync
|
|
90
|
+
|
|
91
|
+
Fast sync after code changes — only re-scans changed files:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
memgrid sync
|
|
95
|
+
# Output:
|
|
96
|
+
# 📁 Changed files: 3
|
|
97
|
+
# 🗑️ Removed files: 0
|
|
98
|
+
# 📝 Updated units: 12
|
|
99
|
+
# ⚠️ Stale units: 0
|
|
100
|
+
# 🔗 Repaired links: 2
|
|
101
|
+
# ⏱️ Done in 1834ms
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Add Custom Units
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
memgrid add \
|
|
108
|
+
--type decision \
|
|
109
|
+
--summary "Why we chose PostgreSQL over MongoDB" \
|
|
110
|
+
--description "ACID compliance for financial data, team expertise, $REASON" \
|
|
111
|
+
--file docs/decisions/database.md
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Stats
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
memgrid stats
|
|
118
|
+
# 📊 MemGrid Statistics
|
|
119
|
+
# Total units: 150
|
|
120
|
+
# Active: 142
|
|
121
|
+
# Archived: 8
|
|
122
|
+
# Last scan: 2026-06-28T10:00:00.000Z
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### MCP Server
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
memgrid serve
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Exposes MemGrid as an MCP tool — plug into Claude Desktop, VS Code, or any MCP-compatible agent.
|
|
132
|
+
|
|
133
|
+
## 📦 Memory Unit Types
|
|
134
|
+
|
|
135
|
+
| Type | What it stores | Example |
|
|
136
|
+
|------|---------------|---------|
|
|
137
|
+
| `method` | A function/class method | `CreationDomainService.create()` |
|
|
138
|
+
| `component` | A UI component | `CreationCard` |
|
|
139
|
+
| `pattern` | Design pattern or convention | ResponseBuilder chain pattern |
|
|
140
|
+
| `config` | Configuration/env | Docker services, tech stack |
|
|
141
|
+
| `error_solution` | A bug + how it was fixed | "GLM OOM → switch to DeepSeek" |
|
|
142
|
+
| `decision` | A code decision + rationale | "Why delete returns true, not null" |
|
|
143
|
+
| `skill_trigger` | When to use which skill | "Figma work → enable chakra MCP" |
|
|
144
|
+
| `mcp_trigger` | When to call which MCP | "New Chakra component → get_component_example" |
|
|
145
|
+
| `rule_trigger` | When to load which rule | "Server code → load coding-philosophy" |
|
|
146
|
+
| `style_preference` | Your coding style | "functional pipes over for-loops" |
|
|
147
|
+
| `architecture_principle` | Architecture red lines | "Controller never calls Repository directly" |
|
|
148
|
+
|
|
149
|
+
## 🆚 vs Alternatives
|
|
150
|
+
|
|
151
|
+
| | Claude Auto Memory | Mem0 | Cursor Indexing | **MemGrid** |
|
|
152
|
+
|---|---|---|---|---|
|
|
153
|
+
| Granularity | Documents | Conversations | Files | **Knowledge units** |
|
|
154
|
+
| Structure | Flat text | Flat | File tree | **Mesh (graph)** |
|
|
155
|
+
| Retrieval | Full load | Semantic | Semantic | **Hybrid + Traverse** |
|
|
156
|
+
| Learning | Linear append | None | None | **Post-task self-evolution** |
|
|
157
|
+
| Incremental sync | No | No | Full re-index | **Hash-diff incremental** |
|
|
158
|
+
| Tool-aware | No | No | No | **Trigger units** |
|
|
159
|
+
| Style-aware | Rules only | No | No | **Style layer** |
|
|
160
|
+
|
|
161
|
+
## 📊 Performance
|
|
162
|
+
|
|
163
|
+
| Scenario | Time |
|
|
164
|
+
|----------|------|
|
|
165
|
+
| Search (keyword) | < 3ms |
|
|
166
|
+
| Search (repeated, LRU) | 0ms |
|
|
167
|
+
| Sync (0 changes) | ~5ms |
|
|
168
|
+
| Sync (1 file changed) | ~2s |
|
|
169
|
+
| Full init (150 units) | ~10s |
|
|
170
|
+
|
|
171
|
+
## 📁 File Format
|
|
172
|
+
|
|
173
|
+
Memory units are stored as JSON in `.claude/memory-grid/units/` — **Git-friendly and human-readable**.
|
|
174
|
+
|
|
175
|
+
```json
|
|
176
|
+
{
|
|
177
|
+
"id": "method_creation_create",
|
|
178
|
+
"type": "method",
|
|
179
|
+
"summary": "CreationDomainService.create — Create a new work",
|
|
180
|
+
"source": {
|
|
181
|
+
"file": "apps/server/src/creation/creation.domain-service.ts",
|
|
182
|
+
"lines": "45-67"
|
|
183
|
+
},
|
|
184
|
+
"signatures": ["CreationDomainService.create"],
|
|
185
|
+
"content": {
|
|
186
|
+
"description": "Creates a new work, verifies ownership, saves to DB",
|
|
187
|
+
"inputs": "userId: string, dto: Partial<CreationEntity>",
|
|
188
|
+
"outputs": "ApiResponse{ value: savedEntity }"
|
|
189
|
+
},
|
|
190
|
+
"associations": [
|
|
191
|
+
{
|
|
192
|
+
"to": "pattern_response_builder",
|
|
193
|
+
"relation": "implements_pattern",
|
|
194
|
+
"weight": 0.9
|
|
195
|
+
}
|
|
196
|
+
],
|
|
197
|
+
"meta": {
|
|
198
|
+
"created": "2026-06-28T00:00:00.000Z",
|
|
199
|
+
"updated": "2026-06-28T00:00:00.000Z",
|
|
200
|
+
"confidence": 0.8,
|
|
201
|
+
"usage_count": 0,
|
|
202
|
+
"status": "active"
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
`mesh.json` stores the grid metadata including `fileSnapshot` for incremental sync and `edgeIndex` for fast association traversal.
|
|
208
|
+
|
|
209
|
+
## 🌐 Language Support
|
|
210
|
+
|
|
211
|
+
MemGrid is **language-agnostic** at its core. Scanners are swappable plugins:
|
|
212
|
+
|
|
213
|
+
| Scanner | Detects | Extracts |
|
|
214
|
+
|---------|---------|----------|
|
|
215
|
+
| **TypeScript** | `tsconfig.json`, `.ts` files | Classes, methods, exported functions (AST via ts-morph) |
|
|
216
|
+
| **JavaScript** | `package.json` (no tsconfig), `.js` files | Exported functions, classes, arrow functions (regex) |
|
|
217
|
+
| **Python** | `pyproject.toml`, `.py` files | Functions, classes, decorators, docstrings (regex) |
|
|
218
|
+
| **Go** | `go.mod`, `.go` files | Functions, methods, structs, interfaces (regex) |
|
|
219
|
+
| **Rust** | `Cargo.toml`, `.rs` files | Functions, structs, enums, traits, impl blocks (regex) |
|
|
220
|
+
| **Markdown** | Any `.md` files | Headings as knowledge units |
|
|
221
|
+
| **Rules** | `.claude/rules/*.md` | Design patterns, coding rules, trigger units |
|
|
222
|
+
| **Config** | `package.json`, `pyproject.toml`, `go.mod`, `Cargo.toml`, `docker-compose.yml` | Tech stack, dependencies, infrastructure |
|
|
223
|
+
|
|
224
|
+
**Adding a new language** means implementing the `Scanner` interface — the core engine (storage, retrieval, learning, sync) stays untouched.
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
// src/scanner/python.ts (example)
|
|
228
|
+
export class PythonScanner implements Scanner {
|
|
229
|
+
readonly name = 'python';
|
|
230
|
+
detect(projectRoot: string): boolean { ... }
|
|
231
|
+
async scan(options: ScanOptions): Promise<MemoryUnit[]> { ... }
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## 🔌 Integration
|
|
236
|
+
|
|
237
|
+
MemGrid outputs **standardized Markdown context** consumable by any AI coding tool:
|
|
238
|
+
|
|
239
|
+
- **Claude Code** — via MCP Server or Hook
|
|
240
|
+
- **Cursor / Windsurf** — via Rules file injection
|
|
241
|
+
- **GitHub Copilot** — via `.github/copilot-instructions.md`
|
|
242
|
+
- **Aider / Cline / Continue** — via custom prompt templates
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
# Start MCP Server
|
|
246
|
+
memgrid serve
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## License
|
|
250
|
+
|
|
251
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { MemoryUnit } from '../shared/types.js';
|
|
2
|
+
import type { FileStore } from '../store/file-store.js';
|
|
3
|
+
export interface TaskResult {
|
|
4
|
+
summary: string;
|
|
5
|
+
outcome: string;
|
|
6
|
+
filesModified: string[];
|
|
7
|
+
errorsEncountered?: string[];
|
|
8
|
+
decisions?: string[];
|
|
9
|
+
toolsUsed?: string[];
|
|
10
|
+
styleObservations?: string[];
|
|
11
|
+
}
|
|
12
|
+
export interface LearningSuggestions {
|
|
13
|
+
add: Partial<MemoryUnit>[];
|
|
14
|
+
update: {
|
|
15
|
+
id: string;
|
|
16
|
+
patch: Partial<MemoryUnit>;
|
|
17
|
+
}[];
|
|
18
|
+
archive: string[];
|
|
19
|
+
summary: string;
|
|
20
|
+
}
|
|
21
|
+
export declare class LearnEngine {
|
|
22
|
+
private store;
|
|
23
|
+
private retrieve;
|
|
24
|
+
constructor(store: FileStore);
|
|
25
|
+
/**
|
|
26
|
+
* Analyze a completed task and suggest memory grid updates.
|
|
27
|
+
* This is the core "self-learning" loop — called after every task.
|
|
28
|
+
*/
|
|
29
|
+
analyze(task: TaskResult): Promise<LearningSuggestions>;
|
|
30
|
+
/**
|
|
31
|
+
* Apply the learning suggestions to the grid.
|
|
32
|
+
* Only applies units with confidence >= 0.7 by default.
|
|
33
|
+
*/
|
|
34
|
+
apply(suggestions: LearningSuggestions, minConfidence?: number): Promise<string[]>;
|
|
35
|
+
/**
|
|
36
|
+
* Generate a plain text summary of suggestions for display/copy.
|
|
37
|
+
*/
|
|
38
|
+
formatSuggestions(suggestions: LearningSuggestions): string;
|
|
39
|
+
/**
|
|
40
|
+
* Infer the domain/subject area from a task summary.
|
|
41
|
+
*/
|
|
42
|
+
private inferDomain;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/learn/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAkB,MAAM,oBAAoB,CAAC;AACrE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAGxD,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;IAC3B,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,CAAA;KAAE,EAAE,CAAC;IACrD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,KAAK,CAAY;IACzB,OAAO,CAAC,QAAQ,CAAiB;gBAErB,KAAK,EAAE,SAAS;IAK5B;;;OAGG;IACG,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAyI7D;;;OAGG;IACG,KAAK,CAAC,WAAW,EAAE,mBAAmB,EAAE,aAAa,SAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAkDrF;;OAEG;IACH,iBAAiB,CAAC,WAAW,EAAE,mBAAmB,GAAG,MAAM;IAgC3D;;OAEG;IACH,OAAO,CAAC,WAAW;CAoBpB"}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { RetrieveEngine } from '../retrieve/index.js';
|
|
2
|
+
export class LearnEngine {
|
|
3
|
+
store;
|
|
4
|
+
retrieve;
|
|
5
|
+
constructor(store) {
|
|
6
|
+
this.store = store;
|
|
7
|
+
this.retrieve = new RetrieveEngine(store);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Analyze a completed task and suggest memory grid updates.
|
|
11
|
+
* This is the core "self-learning" loop — called after every task.
|
|
12
|
+
*/
|
|
13
|
+
async analyze(task) {
|
|
14
|
+
const suggestions = {
|
|
15
|
+
add: [],
|
|
16
|
+
update: [],
|
|
17
|
+
archive: [],
|
|
18
|
+
summary: '',
|
|
19
|
+
};
|
|
20
|
+
const summaries = [];
|
|
21
|
+
// 1. Suggest new method units for modified files
|
|
22
|
+
if (task.filesModified.length > 0) {
|
|
23
|
+
const existingUnits = await this.store.listUnits();
|
|
24
|
+
const existingFiles = new Set(existingUnits
|
|
25
|
+
.filter((u) => u.source?.file)
|
|
26
|
+
.map((u) => u.source.file));
|
|
27
|
+
const newFiles = task.filesModified.filter((f) => !existingFiles.has(f));
|
|
28
|
+
if (newFiles.length > 0) {
|
|
29
|
+
summaries.push(`🆕 ${newFiles.length} new files to scan`);
|
|
30
|
+
// Don't actually scan here — just flag for memgrid init
|
|
31
|
+
for (const file of newFiles) {
|
|
32
|
+
suggestions.add.push({
|
|
33
|
+
type: 'method',
|
|
34
|
+
summary: `[TODO] New file: ${file}`,
|
|
35
|
+
content: {
|
|
36
|
+
description: `This file was created/modified in task: "${task.summary}". Run \`memgrid init\` to scan for method units.`,
|
|
37
|
+
trigger: `When working near ${file}`,
|
|
38
|
+
action: `Rescan with memgrid init`,
|
|
39
|
+
},
|
|
40
|
+
source: { file },
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// 2. Suggest error_solution units
|
|
46
|
+
if (task.errorsEncountered && task.errorsEncountered.length > 0) {
|
|
47
|
+
for (const error of task.errorsEncountered) {
|
|
48
|
+
const id = `error_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
49
|
+
suggestions.add.push({
|
|
50
|
+
type: 'error_solution',
|
|
51
|
+
summary: `Error fix: ${error.slice(0, 80)}`,
|
|
52
|
+
content: {
|
|
53
|
+
description: error,
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
summaries.push(`🐛 ${task.errorsEncountered.length} error(s) recorded as error_solution units`);
|
|
58
|
+
}
|
|
59
|
+
// 3. Suggest decision units
|
|
60
|
+
if (task.decisions && task.decisions.length > 0) {
|
|
61
|
+
for (const decision of task.decisions) {
|
|
62
|
+
const id = `decision_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
63
|
+
suggestions.add.push({
|
|
64
|
+
type: 'decision',
|
|
65
|
+
summary: decision.slice(0, 80),
|
|
66
|
+
content: {
|
|
67
|
+
description: `Design decision from task "${task.summary}": ${decision}`,
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
summaries.push(`🎯 ${task.decisions.length} decision(s) recorded`);
|
|
72
|
+
}
|
|
73
|
+
// 4. Suggest trigger units based on tools used
|
|
74
|
+
if (task.toolsUsed && task.toolsUsed.length > 0) {
|
|
75
|
+
for (const tool of task.toolsUsed) {
|
|
76
|
+
// Check if a similar trigger already exists
|
|
77
|
+
const existing = (await this.store.listUnits()).find((u) => u.type === 'skill_trigger' && u.summary.includes(tool));
|
|
78
|
+
if (!existing) {
|
|
79
|
+
const id = `trigger_skill_${tool.replace(/[^a-z0-9_]/g, '_')}_${Date.now()}`;
|
|
80
|
+
suggestions.add.push({
|
|
81
|
+
type: 'skill_trigger',
|
|
82
|
+
summary: `When working on ${this.inferDomain(task.summary)} → use ${tool}`,
|
|
83
|
+
content: {
|
|
84
|
+
description: `Task "${task.summary}" successfully used ${tool}`,
|
|
85
|
+
trigger: this.inferDomain(task.summary),
|
|
86
|
+
action: `Enable and use ${tool}`,
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
summaries.push(`🔧 ${task.toolsUsed.length} tool trigger(s) suggested`);
|
|
92
|
+
}
|
|
93
|
+
// 5. Suggest style_preference units based on observations
|
|
94
|
+
if (task.styleObservations && task.styleObservations.length > 0) {
|
|
95
|
+
for (const style of task.styleObservations) {
|
|
96
|
+
const id = `style_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
97
|
+
suggestions.add.push({
|
|
98
|
+
type: 'style_preference',
|
|
99
|
+
summary: style.slice(0, 80),
|
|
100
|
+
content: {
|
|
101
|
+
description: `Observed in task "${task.summary}": ${style}`,
|
|
102
|
+
style_notes: style,
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
summaries.push(`🎨 ${task.styleObservations.length} style preference(s) recorded`);
|
|
107
|
+
}
|
|
108
|
+
// 6. Check for units that might need archiving (stale — referenced files deleted)
|
|
109
|
+
const allUnits = await this.store.listUnits();
|
|
110
|
+
for (const unit of allUnits.filter((u) => u.type === 'method')) {
|
|
111
|
+
if (unit.source?.file && task.filesModified.includes(unit.source.file)) {
|
|
112
|
+
// File was modified — flag for review
|
|
113
|
+
suggestions.update.push({
|
|
114
|
+
id: unit.id,
|
|
115
|
+
patch: {
|
|
116
|
+
meta: {
|
|
117
|
+
...unit.meta,
|
|
118
|
+
status: 'stale',
|
|
119
|
+
updated: new Date().toISOString(),
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// 7. Build summary
|
|
126
|
+
if (summaries.length === 0) {
|
|
127
|
+
suggestions.summary = 'No significant new knowledge to add. Grid is stable for this task.';
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
suggestions.summary = summaries.join('\n');
|
|
131
|
+
}
|
|
132
|
+
return suggestions;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Apply the learning suggestions to the grid.
|
|
136
|
+
* Only applies units with confidence >= 0.7 by default.
|
|
137
|
+
*/
|
|
138
|
+
async apply(suggestions, minConfidence = 0.7) {
|
|
139
|
+
const applied = [];
|
|
140
|
+
for (const unit of suggestions.add) {
|
|
141
|
+
const fullUnit = {
|
|
142
|
+
id: `auto_${unit.type}_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`,
|
|
143
|
+
type: unit.type,
|
|
144
|
+
summary: unit.summary || 'Unknown',
|
|
145
|
+
signatures: unit.signatures || [],
|
|
146
|
+
content: unit.content || { description: '' },
|
|
147
|
+
source: unit.source,
|
|
148
|
+
associations: [],
|
|
149
|
+
meta: {
|
|
150
|
+
created: new Date().toISOString(),
|
|
151
|
+
updated: new Date().toISOString(),
|
|
152
|
+
confidence: 0.6, // Auto-generated, lower confidence
|
|
153
|
+
usage_count: 0,
|
|
154
|
+
status: 'active',
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
if (fullUnit.meta.confidence >= minConfidence) {
|
|
158
|
+
this.store.saveUnit(fullUnit);
|
|
159
|
+
applied.push(`+ ${fullUnit.id}`);
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
// Save anyway but mark as needs-review
|
|
163
|
+
fullUnit.meta.status = 'stale'; // stale here means "pending human review"
|
|
164
|
+
this.store.saveUnit(fullUnit);
|
|
165
|
+
applied.push(`? ${fullUnit.id} (needs review, confidence: ${fullUnit.meta.confidence})`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
for (const { id, patch } of suggestions.update) {
|
|
169
|
+
const existing = this.store.getUnit(id);
|
|
170
|
+
if (existing) {
|
|
171
|
+
Object.assign(existing, patch);
|
|
172
|
+
existing.meta.updated = new Date().toISOString();
|
|
173
|
+
this.store.saveUnit(existing);
|
|
174
|
+
applied.push(`~ ${id} (updated)`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
for (const id of suggestions.archive) {
|
|
178
|
+
this.store.archiveUnit(id);
|
|
179
|
+
applied.push(`- ${id} (archived)`);
|
|
180
|
+
}
|
|
181
|
+
return applied;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Generate a plain text summary of suggestions for display/copy.
|
|
185
|
+
*/
|
|
186
|
+
formatSuggestions(suggestions) {
|
|
187
|
+
const lines = ['## 📋 Learning Suggestions', '', suggestions.summary, ''];
|
|
188
|
+
if (suggestions.add.length > 0) {
|
|
189
|
+
lines.push(`### Add (${suggestions.add.length})`, '');
|
|
190
|
+
for (const unit of suggestions.add) {
|
|
191
|
+
lines.push(`- [${unit.type}] ${unit.summary}`);
|
|
192
|
+
}
|
|
193
|
+
lines.push('');
|
|
194
|
+
}
|
|
195
|
+
if (suggestions.update.length > 0) {
|
|
196
|
+
lines.push(`### Update (${suggestions.update.length})`, '');
|
|
197
|
+
for (const { id, patch } of suggestions.update) {
|
|
198
|
+
const status = patch.meta?.status || 'changed';
|
|
199
|
+
lines.push(`- \`${id}\` → ${status}`);
|
|
200
|
+
}
|
|
201
|
+
lines.push('');
|
|
202
|
+
}
|
|
203
|
+
if (suggestions.archive.length > 0) {
|
|
204
|
+
lines.push(`### Archive (${suggestions.archive.length})`, '');
|
|
205
|
+
for (const id of suggestions.archive) {
|
|
206
|
+
lines.push(`- \`${id}\``);
|
|
207
|
+
}
|
|
208
|
+
lines.push('');
|
|
209
|
+
}
|
|
210
|
+
lines.push('---', 'Run `memgrid apply-suggestions` to apply all changes.');
|
|
211
|
+
return lines.join('\n');
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Infer the domain/subject area from a task summary.
|
|
215
|
+
*/
|
|
216
|
+
inferDomain(summary) {
|
|
217
|
+
const domains = {
|
|
218
|
+
'server code': ['server', 'api', 'controller', 'service', 'nest', 'typeorm', 'postgres', 'database', 'auth'],
|
|
219
|
+
'frontend': ['web', 'ui', 'component', 'page', 'chakra', 'react', 'next', 'figma', 'style', 'css'],
|
|
220
|
+
'config': ['config', 'env', 'docker', 'ci', 'deploy', 'package'],
|
|
221
|
+
'review': ['pr', 'review', 'merge', 'branch'],
|
|
222
|
+
'docs': ['docs', 'readme', 'documentation'],
|
|
223
|
+
'memory': ['memory', 'grid', 'atom'],
|
|
224
|
+
};
|
|
225
|
+
const lower = summary.toLowerCase();
|
|
226
|
+
for (const [domain, keywords] of Object.entries(domains)) {
|
|
227
|
+
if (keywords.some((k) => lower.includes(k))) {
|
|
228
|
+
return domain;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return 'generic development tasks';
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/learn/index.ts"],"names":[],"mappings":"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"}
|