@vaur94/agz-memory 0.4.0-beta.1 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,39 +2,55 @@
2
2
 
3
3
  English | [Türkçe](README.tr.md)
4
4
 
5
- Project-scoped persistent memory for OpenCode V2. The repository publishes two
6
- lockstep packages:
7
-
8
- - `@vaur94/agz-memory`: the nine-tool stdio MCP server, reusable core, and
9
- recovery-oriented admin CLI.
10
- - `@vaur94/agz-memory-plugin`: optional safe capture and bounded context
11
- injection for an exact OpenCode V2 beta.
12
-
13
- SQLite schema v9 is the canonical source of truth. Optional semantic services
14
- are disposable derived indexes and are disabled unless their isolation,
15
- deletion, purge, and quality contracts pass the benchmark gates.
5
+ AGZ Memory gives OpenCode V2 a durable, project-scoped linked memory. It ships
6
+ as two independently usable packages that advance at the same version:
7
+
8
+ - `@vaur94/agz-memory`: a nine-tool MCP server, TypeScript core, and recovery
9
+ CLI backed by SQLite.
10
+ - `@vaur94/agz-memory-plugin`: an optional OpenCode V2 adapter for bounded
11
+ retrieval and deliberately staged automatic capture.
12
+
13
+ The MCP server is ready for normal use. The plugin starts inert: no project is
14
+ created, no session is captured, and no context is injected until an explicit
15
+ binding and rollout mode are configured.
16
+
17
+ ## Why AGZ Memory
18
+
19
+ - Every read and mutation is scoped by an immutable project UUID or unique
20
+ project name.
21
+ - Notes can be pinned, linked, superseded, revised, searched, and inspected
22
+ without mixing projects.
23
+ - SQLite schema v10 is the canonical source of truth; optional semantic indexes
24
+ are replaceable derivatives.
25
+ - Destructive project deletion requires the immutable ID, exact current name,
26
+ and a fixed confirmation phrase.
27
+ - Backup manifests include row counts, SQLite integrity results, size, and
28
+ SHA-256 before restore is allowed.
29
+ - Automatic capture is redacted, bounded, idempotent, and disabled by default.
16
30
 
17
31
  ## Compatibility
18
32
 
19
- | Component | Version |
33
+ | Component | Supported version |
20
34
  |---|---|
21
- | Core/MCP | `0.4.0-beta.1` |
22
- | Plugin | `0.4.0-beta.1` |
35
+ | Core and MCP | `0.4.1` |
36
+ | OpenCode plugin | `0.4.1` |
23
37
  | OpenCode V2 | `0.0.0-beta-18743` |
24
38
  | `@opencode-ai/plugin` | `0.0.0-beta-18743` |
25
39
  | Bun | `>=1.3.14` |
26
- | SQLite schema | `9` |
40
+ | SQLite schema | `10` |
27
41
 
28
- The plugin disables itself when the running OpenCode version does not exactly
29
- match its supported beta. The MCP server remains independently usable.
42
+ The MCP server is not tied to an OpenCode beta. The optional plugin disables
43
+ itself unless the running OpenCode version exactly matches the supported beta.
30
44
 
31
- ## MCP Server
45
+ ## Install The MCP Server
46
+
47
+ Run the server directly:
32
48
 
33
49
  ```sh
34
- bunx @vaur94/agz-memory@0.4.0-beta.1
50
+ bunx @vaur94/agz-memory@0.4.1
35
51
  ```
36
52
 
37
- OpenCode V2 configuration uses `mcp.servers`:
53
+ Or register it in OpenCode V2 under `mcp.servers`:
38
54
 
39
55
  ```jsonc
40
56
  {
@@ -42,7 +58,7 @@ OpenCode V2 configuration uses `mcp.servers`:
42
58
  "servers": {
43
59
  "agz-memory": {
44
60
  "type": "local",
45
- "command": ["bunx", "@vaur94/agz-memory@0.4.0-beta.1"],
61
+ "command": ["bunx", "@vaur94/agz-memory@0.4.1"],
46
62
  "environment": {
47
63
  "OPENCODE_MEMORY_DATABASE_PATH": "{env:OPENCODE_MEMORY_DATABASE_PATH}"
48
64
  },
@@ -53,50 +69,51 @@ OpenCode V2 configuration uses `mcp.servers`:
53
69
  }
54
70
  ```
55
71
 
56
- The default database path is
57
- `~/.local/share/opencode-memory/memory.sqlite`. Override it with
58
- `OPENCODE_MEMORY_DATABASE_PATH` before starting OpenCode.
72
+ The default database is
73
+ `~/.local/share/opencode-memory/memory.sqlite`. Set
74
+ `OPENCODE_MEMORY_DATABASE_PATH` before OpenCode starts to use another path.
75
+ The database file is created with user-only permissions.
59
76
 
60
- ### Tools
77
+ ## Use The Nine Tools
61
78
 
62
- The external MCP contract remains exactly nine tools:
79
+ OpenCode exposes the tools with the configured server prefix, for example
80
+ `agz-memory_project_list`. The MCP protocol names remain:
63
81
 
64
82
  | Tool | Purpose |
65
83
  |---|---|
66
- | `project_list` | List immutable project IDs and current names |
67
- | `project_create` | Create an empty project |
68
- | `project_update` | Rename a project without changing its ID |
69
- | `project_delete` | Permanently delete one confirmed project |
70
- | `memory_recall` | Project-filtered FTS5 and one-hop graph recall |
71
- | `memory_update` | Create, patch, or permanently delete notes |
72
- | `memory_pin` | Set note priority inside one project |
73
- | `memory_link` | Add same-project graph edges |
74
- | `memory_read` | Read full note bodies and graph edges |
75
-
76
- Every `memory_*` request selects exactly one `projectID` or `projectName`.
77
- Cross-project reads, updates, deletes, links, and recall are rejected. Ordered
78
- batches are intentionally non-atomic, so inspect every item result.
79
-
80
- Project deletion requires all three values:
81
-
82
- ```json
83
- {
84
- "projectID": "<immutable UUID>",
85
- "confirmProjectName": "<exact current case-sensitive name>",
86
- "confirmation": "DELETE_PROJECT_AND_ALL_MEMORY"
87
- }
88
- ```
89
-
90
- ## Optional OpenCode Plugin
91
-
92
- The plugin is a separate package so the moving OpenCode beta dependency never
93
- enters the MCP-only runtime. Its safe default is `off`.
84
+ | `project_list` | List project identities and note counts. |
85
+ | `project_create` | Create an empty project with a unique name. |
86
+ | `project_update` | Rename a project without changing its UUID. |
87
+ | `project_delete` | Permanently delete one confirmed project and all owned data. |
88
+ | `memory_recall` | Search one project with one or up to ten queries. |
89
+ | `memory_update` | Create, patch, or explicitly delete notes in one project. |
90
+ | `memory_pin` | Prioritize or unprioritize one active note. |
91
+ | `memory_link` | Add typed links between notes in the same project. |
92
+ | `memory_read` | Read full notes, pin state, project identity, and graph neighbors. |
93
+
94
+ Recommended sequence:
95
+
96
+ 1. Call `project_list` and reuse an existing project when it represents the
97
+ same durable workspace.
98
+ 2. Call `project_create` only when no matching project exists.
99
+ 3. Keep the returned `projectID`; names can change, UUIDs cannot.
100
+ 4. Call `memory_recall` before relying on historical decisions.
101
+ 5. Store only durable, verified facts, decisions, procedures, preferences,
102
+ research, context, or tasks. Do not store transcripts, secrets, or guesses.
103
+
104
+ All multi-item mutations are ordered and non-atomic. Inspect every result:
105
+ earlier items remain applied when a later item fails.
106
+
107
+ ## Add The Optional Plugin
108
+
109
+ Keep the MCP server configured, then add the exact plugin package with inert
110
+ options:
94
111
 
95
112
  ```jsonc
96
113
  {
97
114
  "plugins": [
98
115
  {
99
- "package": "@vaur94/agz-memory-plugin@0.4.0-beta.1",
116
+ "package": "@vaur94/agz-memory-plugin@0.4.1",
100
117
  "options": {
101
118
  "mode": "off",
102
119
  "autoCreateProjects": false,
@@ -118,120 +135,119 @@ enters the MCP-only runtime. Its safe default is `off`.
118
135
  }
119
136
  ```
120
137
 
121
- Bindings are explicit allowlist entries. The plugin never selects a memory
122
- project by basename and never auto-creates one:
138
+ The plugin opens the same database path as the MCP server. It rejects unknown
139
+ configuration fields, automatic project creation, unsupported semantic
140
+ backends, oversized limits, and conflicting bindings.
141
+
142
+ ## Bind Projects Explicitly
143
+
144
+ The plugin does nothing without exactly one matching binding. Each binding maps
145
+ an OpenCode project/workspace/location to an existing AGZ Memory project:
123
146
 
124
147
  ```jsonc
125
148
  {
126
- "memoryProjectID": "<UUID from project_list>",
127
- "opencodeProjectID": "<ctx.location.project.id>",
149
+ "memoryProjectID": "11111111-1111-4111-8111-111111111111",
150
+ "opencodeProjectID": "your-opencode-project-id",
128
151
  "canonicalDirectory": "/absolute/canonical/project/path",
129
- "workspaceID": "<optional workspace ID>"
152
+ "workspaceID": ""
130
153
  }
131
154
  ```
132
155
 
133
- The rollout modes are cumulative:
134
-
135
- | Mode | Capture | Retrieval | Injection | Auto-write |
136
- |---|---:|---:|---:|---:|
137
- | `off` | No | No | No | No |
138
- | `shadow-capture` | Redacted audit only | No | No | No |
139
- | `shadow-retrieval` | Yes | Metrics only | No | No |
140
- | `inject` | Yes | Yes | Bounded | No |
141
- | `auto-write` | Yes | Yes | Bounded | Explicit high-confidence decisions/preferences only |
142
-
143
- Injection is fail-open, summary-only, limited to eight cards and 4,800
144
- characters, and wrapped as `trust="untrusted"`. A memory timeout or binding
145
- error does not block the main OpenCode request.
156
+ `memoryProjectID` must come from `project_list`. The directory is resolved with
157
+ the filesystem and compared with the active OpenCode location. Only a hash of
158
+ that canonical path is persisted. A mismatched location or duplicate mapping
159
+ disables the plugin rather than selecting a project heuristically.
146
160
 
147
- ## Capture Safety
161
+ ## Roll Out Safely
148
162
 
149
- The canonical event contract remains `opencode2-memory.capture/1` for database
150
- and event compatibility with earlier releases.
163
+ Modes are intentionally one-way stages:
151
164
 
152
- - Native session/message/ordinal/tool IDs produce deterministic SHA-256
153
- idempotency keys. SQLite uniqueness is the final duplicate guard.
154
- - Projection discards reasoning, tool input/output, attachments, files, system
155
- parts, diffs, environment data, and provider state.
156
- - Text is redacted before extraction and again inside the core before any DB
157
- insert.
158
- - Private keys, credential URIs, multiple high-risk secrets, and canaries are
159
- quarantined without a text payload.
160
- - Event JSON is limited to 16 KiB; automatic content is limited to 4,800
161
- characters.
162
- - `[memory:off]` disables capture for that user message.
163
- - Auto-write initially accepts only explicit `preference` and `decision`
164
- candidates at confidence `>= 0.95`.
165
-
166
- ## Schema V9
167
-
168
- Schema v9 preserves project, note, edge, timestamp, status, and pin identities
169
- while adding:
170
-
171
- - `project_bindings`
172
- - `capture_checkpoints`
173
- - `capture_events`
174
- - `note_provenance`
175
- - `note_revisions`
176
- - `index_outbox`
165
+ | Mode | Capture | Retrieval | Injection | Note writes |
166
+ |---|---|---|---|---|
167
+ | `off` | No | No | No | No |
168
+ | `shadow-capture` | Redacted audit only | No | No | No |
169
+ | `shadow-retrieval` | Optional redacted audit | Measured only | No | No |
170
+ | `inject` | Optional redacted audit | Lexical and graph | Bounded, untrusted | No |
171
+ | `auto-write` | Policy-gated | Lexical and graph | Bounded, untrusted | High-confidence candidates only |
177
172
 
178
- Every committed note state has provenance and a full revision snapshot. Note
179
- create, patch, pin, supersession, FTS triggers, and derived-index outbox writes
180
- share transactions. Normal recall only returns `active` notes.
173
+ Advance one stage at a time and inspect `agz-memory-admin capture status`,
174
+ database growth, retrieval latency, and false matches before proceeding. To
175
+ disable retrieval, injection, and every capture channel for one complete turn,
176
+ include `[memory:off]` in that prompt. Reconciliation reconstructs this boundary
177
+ from session history after a restart.
178
+ Returning to `off` is always safe and does not delete stored data.
181
179
 
182
- FTS5 now uses external content and insert/update/delete triggers rather than
183
- manual synchronization.
180
+ Semantic retrieval remains hard-disabled. `semanticBackend` must be `none`
181
+ until a vendor passes project isolation, delete, purge, rebuild, leakage,
182
+ quality, and latency gates.
184
183
 
185
- ## Backup, Upgrade, And Restore
184
+ ## Operate And Recover
186
185
 
187
- The admin binary writes JSON to stdout and sanitized errors to stderr:
186
+ The admin CLI reads the same `OPENCODE_MEMORY_DATABASE_PATH`:
188
187
 
189
188
  ```sh
190
- bunx --package @vaur94/agz-memory@0.4.0-beta.1 agz-memory-admin doctor
191
- bunx --package @vaur94/agz-memory@0.4.0-beta.1 agz-memory-admin backup
192
- bunx --package @vaur94/agz-memory@0.4.0-beta.1 agz-memory-admin upgrade --to 9
193
- bunx --package @vaur94/agz-memory@0.4.0-beta.1 agz-memory-admin outbox status
194
- bunx --package @vaur94/agz-memory@0.4.0-beta.1 agz-memory-admin capture status
189
+ bunx --package @vaur94/agz-memory@0.4.1 agz-memory-admin doctor
190
+ bunx --package @vaur94/agz-memory@0.4.1 agz-memory-admin backup
191
+ bunx --package @vaur94/agz-memory@0.4.1 agz-memory-admin upgrade --to 10
192
+ bunx --package @vaur94/agz-memory@0.4.1 agz-memory-admin capture status
193
+ bunx --package @vaur94/agz-memory@0.4.1 agz-memory-admin outbox status
195
194
  ```
196
195
 
197
- Every schema upgrade takes an atomic migration lock and creates a verified
198
- `VACUUM INTO` snapshot plus a SHA-256 manifest before DDL runs. Integrity,
199
- foreign keys, table counts, revision invariants, and FTS counts are checked.
196
+ Upgrades take an exclusive migration lock and create a verified backup before
197
+ changing the database. A failed migration attempts an automatic verified
198
+ restore. Restore and backup deletion use dry-run output plus explicit
199
+ confirmation values; never guess them.
200
200
 
201
- Restore is dry-run unless the manifest hash and confirmation are supplied:
201
+ Use [the backup and restore runbook](docs/backup-restore-runbook.md) for a full
202
+ rehearsal. Final `0.4.1` backup manifests use `agz-memory-backup/1`; prerelease
203
+ manifests must be handled by the prerelease that created them.
202
204
 
203
- ```sh
204
- bunx --package @vaur94/agz-memory@0.4.0-beta.1 agz-memory-admin restore \
205
- /path/to/memory.sqlite.backup/<manifest>.manifest.json
205
+ ## Security Model
206
206
 
207
- bunx --package @vaur94/agz-memory@0.4.0-beta.1 agz-memory-admin restore \
208
- /path/to/memory.sqlite.backup/<manifest>.manifest.json \
209
- --sha256 <manifest-database-sha256> \
210
- --confirm RESTORE_DATABASE_FROM_VERIFIED_BACKUP
211
- ```
207
+ - Retrieved notes are wrapped in `<agz-memory-context trust="untrusted">` and
208
+ escaped before injection. Stored text never becomes system policy.
209
+ - Capture projects only terminal user/assistant text and terminal tool status;
210
+ reasoning, tool input, and tool output payloads are excluded.
211
+ - Credential patterns are redacted before persistence and again before note
212
+ materialization. Private-key material is quarantined without a payload.
213
+ - Capture events are idempotent by stable source identity and retained with
214
+ bounded payload lifetimes.
215
+ - Project ownership is enforced in every note and edge query. Cross-project
216
+ links and backend hits are rejected.
217
+ - The SQLite database is canonical. Derived-index outbox rows contain identity
218
+ and hashes, not note payloads.
212
219
 
213
- Stop every MCP/plugin writer before an upgrade or restore. The current database
214
- is preserved as `failed-restore-source-*`; WAL/SHM sidecars are quarantined.
215
- See [`docs/backup-restore-runbook.md`](docs/backup-restore-runbook.md).
220
+ Report vulnerabilities privately as described in [SECURITY.md](SECURITY.md).
216
221
 
217
- ## Semantic Backend Decision
218
-
219
- Production remains `semanticBackend: "none"`. The exact vendor contract review
220
- did not produce a complete live A/B proof for all required server-side project
221
- filter, deterministic delete, purge, leakage, and latency gates. SQLite
222
- lexical+graph retrieval is therefore the production path. See
223
- [`benchmark/baselines/vendor-decision.json`](benchmark/baselines/vendor-decision.json).
224
-
225
- ## Development
222
+ ## Develop And Verify
226
223
 
227
224
  ```sh
228
- bun install
225
+ bun install --frozen-lockfile
226
+ bun run release:verify
229
227
  bun test
230
228
  bun run check
231
229
  bun run build
230
+ bun run benchmark 10000 100
232
231
  npm pack --dry-run --json
233
232
  ```
234
233
 
235
- The test suite includes MCP snapshots, legacy and v8-to-v9 migration fixtures,
236
- backup/restore, revisions, outbox FIFO, capture idempotency, secret quarantine,
237
- retrieval isolation, bounded formatter, and exact-beta plugin hook smoke tests.
234
+ `release:verify` rejects package-version drift, mismatched bilingual sections,
235
+ stale beta pins, and any tracked reintroduction of the retired project name.
236
+ The test suite covers project isolation, destructive confirmation, migration,
237
+ backup/restore, capture safety, revisions, provenance, FTS, retrieval, outbox,
238
+ and the exact nine-tool MCP surface.
239
+
240
+ ## Project Resources
241
+
242
+ - [Architecture](ARCHITECTURE.md)
243
+ - [Changelog](CHANGELOG.md)
244
+ - [Backup and restore runbook](docs/backup-restore-runbook.md)
245
+ - [Contributing](CONTRIBUTING.md)
246
+ - [Security policy](SECURITY.md)
247
+ - [GitHub repository](https://github.com/ugur-murat-alt/agz-memory)
248
+ - [npm core package](https://www.npmjs.com/package/@vaur94/agz-memory)
249
+ - [npm plugin package](https://www.npmjs.com/package/@vaur94/agz-memory-plugin)
250
+
251
+ ## License
252
+
253
+ [MIT](LICENSE)