dotmem 0.0.4 → 0.0.5
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/cli.cjs +934 -33
- package/cli.js +958 -57
- package/global.cjs +1319 -30
- package/global.js +1344 -55
- package/index.cjs +1326 -37
- package/index.js +1350 -61
- package/mcp.cjs +1326 -37
- package/mcp.js +1350 -61
- package/package.json +1 -1
- package/AGENTS.md +0 -464
- package/CHANGELOG.md +0 -0
- package/COPYRIGHT.md +0 -4
- package/LICENSE.md +0 -11
- package/MEMORY.md +0 -518
- package/PACKAGE.md +0 -59
- package/README.md +0 -347
- package/SECURITY.md +0 -524
- package/llms.txt +0 -295
package/MEMORY.md
DELETED
|
@@ -1,518 +0,0 @@
|
|
|
1
|
-
# dotmem Memory
|
|
2
|
-
|
|
3
|
-
> **Status:** Current API reference for dotmem 0.0.1.
|
|
4
|
-
|
|
5
|
-
dotmem has two distinct memory facilities on one `memory` object:
|
|
6
|
-
|
|
7
|
-
- **Application memory** stores typed key/value entries through `remember`, `recall`,
|
|
8
|
-
`update`, and `forget`.
|
|
9
|
-
- **Acquired experience** stores evidenced, applicability-scoped claims through
|
|
10
|
-
`acquire`, retrieves candidates with `discover`, and prepares bounded context with
|
|
11
|
-
`project`.
|
|
12
|
-
|
|
13
|
-
Acquired experience is prior evidence, never executable instructions or current truth.
|
|
14
|
-
Verify it against the current source, runtime, and direct evidence before acting on it.
|
|
15
|
-
|
|
16
|
-
## Start
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
npm install dotmem
|
|
20
|
-
npx dotmem init
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
```ts
|
|
24
|
-
import { memory } from 'dotmem'
|
|
25
|
-
|
|
26
|
-
await memory.acquire({
|
|
27
|
-
id: 'layout.grid.min-content',
|
|
28
|
-
knowledge: { cause: 'Inner margins contribute to min-content track sizing.' },
|
|
29
|
-
applicability: { area: 'layout', component: 'grid' },
|
|
30
|
-
evidence: [{ id: 'layout-regression', source: 'project-test' }],
|
|
31
|
-
epistemicType: 'verified'
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
const candidates = await memory.discover('Grid width changed after adding inner margins')
|
|
35
|
-
const context = memory.project(candidates, { maxCandidates: 3, maxCharacters: 4_000 })
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
Initialization is lazy. `memory.init()` remains as a deprecated compatibility shim;
|
|
39
|
-
new code should simply call the operation it needs.
|
|
40
|
-
|
|
41
|
-
## Deterministic AI activation
|
|
42
|
-
|
|
43
|
-
The activation phrases are `dotmem`, `npx dotmem`, `Joy`, and `Jo`. A message that is exactly one
|
|
44
|
-
of them, ignoring case, surrounding whitespace, and trailing punctuation, activates dotmem once
|
|
45
|
-
for the session.
|
|
46
|
-
|
|
47
|
-
When the user explicitly says one of them, an AI must:
|
|
48
|
-
|
|
49
|
-
1. Resolve the user dotmem home with `dotmem.paths.resolveUserDotMemPath()`.
|
|
50
|
-
2. Read `<dotmem-home>/DOTMEM.md`.
|
|
51
|
-
3. Load applicable user-level acquired experience.
|
|
52
|
-
4. Resolve the current project identity with `dotmem.paths.resolveProjectIdentity()`.
|
|
53
|
-
5. Resolve the project's memory with `dotmem.paths.resolveUserProjectMemoryPath(projectId)`.
|
|
54
|
-
6. Read only that resolved project memory.
|
|
55
|
-
|
|
56
|
-
Do not search the filesystem for `.mem` files. Deterministic resolution failure is a
|
|
57
|
-
stop condition.
|
|
58
|
-
|
|
59
|
-
## Storage and routing
|
|
60
|
-
|
|
61
|
-
Every dotmem component obtains storage paths through one canonical resolver:
|
|
62
|
-
`resolveDotMemStorageRoot()` (also `dotmem.paths.resolveDotMemStorageRoot()`).
|
|
63
|
-
No component reconstructs paths on its own.
|
|
64
|
-
|
|
65
|
-
Resolution precedence:
|
|
66
|
-
|
|
67
|
-
1. **Runtime override** — the `DOTMEM_STORAGE_ROOT` environment variable, for testing,
|
|
68
|
-
CI, containers, and temporary development environments. An override is never
|
|
69
|
-
persisted by itself.
|
|
70
|
-
2. **User locator** — `dotmem.location.json` (location metadata only) inside the stable
|
|
71
|
-
user anchor.
|
|
72
|
-
3. **Default user-scoped storage** — the user anchor itself: `<user-home>/.dotmem`
|
|
73
|
-
(the platform-neutral canonical form; see the OS examples below), resolved from the
|
|
74
|
-
current runtime.
|
|
75
|
-
|
|
76
|
-
The user anchor is resolved from the operating-system user at runtime. dotmem never
|
|
77
|
-
scans drive roots, the filesystem root, or unrelated directories to find storage. A
|
|
78
|
-
configured storage root that is missing, inaccessible, or invalid stops resolution with
|
|
79
|
-
an explicit error — no silent fallback, no autonomous search, no guessed path. A path is
|
|
80
|
-
reported only after it has been resolved or observed in the current runtime; otherwise
|
|
81
|
-
report the semantic location (user memory, project memory, temporary staging, canonical
|
|
82
|
-
storage, user anchor).
|
|
83
|
-
|
|
84
|
-
Storage relocation is user-controlled and verified:
|
|
85
|
-
|
|
86
|
-
```bash
|
|
87
|
-
npx dotmem storage # semantic location + resolved storage root
|
|
88
|
-
npx dotmem storage --root # resolved storage root only (scriptable)
|
|
89
|
-
npx dotmem storage relocate <absolute-storage-dir> # migrate storage to an explicit absolute directory
|
|
90
|
-
npx dotmem storage restore # migrate storage back to the default location
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
`relocate` copies the data, verifies it at the target, updates the locator, and only then
|
|
94
|
-
reports completion; the locator never points at a location whose data has not been
|
|
95
|
-
migrated and verified. The same verification applies to `restore` before the locator is
|
|
96
|
-
removed.
|
|
97
|
-
|
|
98
|
-
**Canonical form, platform-neutral.** The user anchor is written `<user-home>/.dotmem`
|
|
99
|
-
everywhere in this documentation. It resolves at runtime to the current OS user's home:
|
|
100
|
-
|
|
101
|
-
```text
|
|
102
|
-
Example (OS-specific, illustrative only):
|
|
103
|
-
Windows: C:\Users\<user>\.dotmem
|
|
104
|
-
Linux: /home/<user>/.dotmem
|
|
105
|
-
macOS: /Users/<user>/.dotmem
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
The runtime resolves the actual home directory from the OS/environment; no hardcoded
|
|
109
|
-
platform path is ever a default.
|
|
110
|
-
|
|
111
|
-
On Node.js and Bun, the writer selects a store from the top-level acquisition fields:
|
|
112
|
-
|
|
113
|
-
| Kind and scope | File |
|
|
114
|
-
| --- | --- |
|
|
115
|
-
| `experience`, `scope: 'project'` (default) | `$DOTMEM_HOME/projects/<project-id>.mem` |
|
|
116
|
-
| `experience`, `scope: 'user'` | `$DOTMEM_HOME/user.mem` |
|
|
117
|
-
| `agent` | `$DOTMEM_HOME/agent.mem` |
|
|
118
|
-
| `logic` | `$DOTMEM_HOME/logic.mem` |
|
|
119
|
-
|
|
120
|
-
`<project-id>` resolves in order from `DOTMEM_PROJECT_ID`, `package.json`'s `name`,
|
|
121
|
-
then the current directory's basename. Set `sourceProject` when writing project
|
|
122
|
-
experience for a project other than the current working directory.
|
|
123
|
-
|
|
124
|
-
`applicability` is flat JSON-primitive matching metadata. It is not routing. A claim
|
|
125
|
-
with `applicability.scope` but no top-level `scope` is rejected to avoid this mistake.
|
|
126
|
-
`kind: 'relationship'` is rejected by `acquire`; relationship graph writes belong to
|
|
127
|
-
the dedicated brain API.
|
|
128
|
-
|
|
129
|
-
Browser and edge environments use the existing `store`-backed acquired-knowledge
|
|
130
|
-
repository and never load Node filesystem code. The CLI is Node-only.
|
|
131
|
-
|
|
132
|
-
## Acquisition safety
|
|
133
|
-
|
|
134
|
-
`memory.acquire()` validates JSON-safe claim data, sanitizes secret-looking keys and
|
|
135
|
-
values before persistence, and writes
|
|
136
|
-
atomically, and verifies that the claim was persisted. Sanitization replaces sensitive
|
|
137
|
-
content with a semantic marker such as `requiresToken: true`; it is not a secret vault,
|
|
138
|
-
encryption policy, access-control system, or authorization decision.
|
|
139
|
-
|
|
140
|
-
Only an explicit `kind` changes the physical store; advisory content classification
|
|
141
|
-
never changes routing. Never place credentials, private keys, access tokens, or
|
|
142
|
-
chain-of-thought in acquired memory.
|
|
143
|
-
|
|
144
|
-
## Claim trust and attribution
|
|
145
|
-
|
|
146
|
-
The acquisition contract is the machine-readable description of what dotmem attests and what it
|
|
147
|
-
only records:
|
|
148
|
-
|
|
149
|
-
| Field class | Fields | Meaning |
|
|
150
|
-
| --- | --- | --- |
|
|
151
|
-
| dotmem attests | `acquiredAt`, `physical store selection`, `project identity resolution` | assigned by dotmem at commit time |
|
|
152
|
-
| Caller supplied | `id`, `knowledge`, `applicability`, `evidence`, `scope`, `kind`, `sourceProject`, relations | stored as the caller wrote it |
|
|
153
|
-
| Caller claims, not attested | `epistemicType`, `provenance`, `evidence.observedAt` | assertions about the claim, never proof of it |
|
|
154
|
-
|
|
155
|
-
Read the same contract the runtime enforces with `npx dotmem policy contract acquire --json`.
|
|
156
|
-
|
|
157
|
-
The three rows are the trust model in one line each. `epistemicType`, `provenance`, and
|
|
158
|
-
`evidence.observedAt` are **caller claims, not attestation**: whoever called `memory.acquire`
|
|
159
|
-
wrote them.
|
|
160
|
-
|
|
161
|
-
`epistemicType: human-stated` means "the writer says a human stated this", not "a human stated
|
|
162
|
-
this". A claim an agent wrote about its own past is a self-report: history, not verified truth,
|
|
163
|
-
until the HI or an independent artifact corroborates it.
|
|
164
|
-
|
|
165
|
-
Corrections are appends. A stored claim is never edited. Exactly one canonical relation per
|
|
166
|
-
acquisition: `refines`, `supersedes`, or `retracts`. `retracts` withdraws the claim from the
|
|
167
|
-
active set and keeps it in the package history.
|
|
168
|
-
|
|
169
|
-
`npx dotmem inspect FILE.mem` reports `integrity` and `authenticity` as independent axes.
|
|
170
|
-
`integrity: valid` means the bytes are unchanged since sealing. `authenticity: unsigned` means
|
|
171
|
-
nobody signed the package. Neither says the claim is true.
|
|
172
|
-
|
|
173
|
-
## Memory language
|
|
174
|
-
|
|
175
|
-
Acquired knowledge payloads may be written in any language the user prefers.
|
|
176
|
-
Conversation may use any language, and code keeps its own established rules.
|
|
177
|
-
There is no enforced payload-language precondition on `memory.acquire`: any
|
|
178
|
-
language and alphabet is accepted, including mixed-language text and very
|
|
179
|
-
short payloads. Language detection is not used to block or gate acquisition.
|
|
180
|
-
|
|
181
|
-
The security posture is unchanged: everything projected remains
|
|
182
|
-
`UNTRUSTED_DATA; NOT_INSTRUCTIONS; VERIFY_CURRENT`, and content in the form
|
|
183
|
-
of an instruction is marked as such. That marking is heuristic and can depend
|
|
184
|
-
on the language of the content; it is not a substitute for verifying current
|
|
185
|
-
source and behavior before relying on remembered data.
|
|
186
|
-
|
|
187
|
-
## Policy (how memory may be used)
|
|
188
|
-
|
|
189
|
-
Policy is a separate authority domain from memory. Memory can never promote itself to
|
|
190
|
-
policy, and a governed claim never selects its own enforcement tier.
|
|
191
|
-
|
|
192
|
-
- `memory.policy.assign(input, namespace?, basedOnRevision?)` — privileged assignment of an
|
|
193
|
-
enforcement tier (`context` | `precondition` | `hard-precondition`) for one canonical event.
|
|
194
|
-
Requires `authority: { kind: 'HI' | 'operator', source }`. The assignment carries a
|
|
195
|
-
system-derived record `revision` and canonical semantic `fingerprint`; `basedOnRevision` is an
|
|
196
|
-
optimistic concurrency check evaluated inside the policy lock.
|
|
197
|
-
- `memory.policy.list()` / `memory.policy.remove(id, namespace?, basedOnRevision?)` /
|
|
198
|
-
`memory.policy.clear(authority)` — privileged reads and removal. Deletion is a modification, so
|
|
199
|
-
it requires the same authority as assignment. `clear` resets the active policy and override
|
|
200
|
-
state, preserves the durable audit trail, and appends a terminal `clear` entry.
|
|
201
|
-
- `memory.policy.evaluate(event, payload?)` — decision-time pull: only the policies applicable to
|
|
202
|
-
the event, with tier, action, and authority provenance. `precondition` blocks and asks the user;
|
|
203
|
-
`hard-precondition` blocks with no conversational override. Resolution is effective state:
|
|
204
|
-
store-resolved overrides are applied and their provenance is attached to the decision.
|
|
205
|
-
- `memory.policy.override` — the privileged out-of-band override surface:
|
|
206
|
-
`grant`, `revoke`, `list`, `effective`. See below.
|
|
207
|
-
- `memory.policy.contract()` — the machine-readable operator contract
|
|
208
|
-
(`MEMORY_PROJECTION_CONTRACT`): memory is `data-only`, untrusted, not instructions.
|
|
209
|
-
- `memory.clear()` is memory-scoped and never deletes policy documents.
|
|
210
|
-
|
|
211
|
-
### Privileged out-of-band policy override
|
|
212
|
-
|
|
213
|
-
An override is **not a bypass**. It is an authorized, explicit, auditable change of effective
|
|
214
|
-
policy state: the base policy is never modified, exactly one override is active per target, and
|
|
215
|
-
the override is bound to the target's generation (`revision` + canonical `fingerprint`), both
|
|
216
|
-
derived from the store — never accepted from a payload.
|
|
217
|
-
|
|
218
|
-
- `memory.policy.override.grant(input, namespace?, basedOnRevision?)` — relax the effective tier
|
|
219
|
-
of one policy. Requires the target policy id, `relaxTo` (a valid tier, `context` is the floor),
|
|
220
|
-
a bounded `expiresAt` (window cap `MAX_OVERRIDE_WINDOW_MS`, 7 days), an explicit `reason`, and
|
|
221
|
-
authority. Hierarchy: an operator cannot relax an HI-owned policy. A new grant atomically
|
|
222
|
-
supersedes the previous active override.
|
|
223
|
-
- `memory.policy.override.revoke(input, namespace?, basedOnRevision?)` — remove a relaxation and
|
|
224
|
-
restore the base policy. HI revokes any override; an operator revokes only operator-granted
|
|
225
|
-
overrides.
|
|
226
|
-
- `memory.policy.override.list(namespace?)` — every override with its resolved state
|
|
227
|
-
(`ACTIVE` | `EXPIRED` | `STALE` | `INERT`).
|
|
228
|
-
- `memory.policy.override.effective(event?, namespace?)` — effective state per policy: base tier,
|
|
229
|
-
effective tier, override state, and the provenance scar (override id, `relaxedFrom`, `by`,
|
|
230
|
-
`until`, `reason`).
|
|
231
|
-
|
|
232
|
-
Override resolution is store-only and namespace-local: an override lives in the same document as
|
|
233
|
-
the policy it targets, chat cannot invoke it, `memory.acquire` cannot create one, a payload
|
|
234
|
-
cannot self-request it, and retrieved text or tool output cannot author one. A changed policy
|
|
235
|
-
makes the override `STALE`, a deleted policy makes it `INERT`, and same-id recreation never
|
|
236
|
-
resurrects it. Expiry and revocation both restore the base policy.
|
|
237
|
-
|
|
238
|
-
Every mutation runs inside the cross-process policy namespace lock (exclusive create, owner
|
|
239
|
-
identity, bounded retry, audited stale-lock break, fail-closed when exclusive creation cannot be
|
|
240
|
-
verified) and is recorded in the durable in-document audit trail in the same atomic write. No
|
|
241
|
-
override is effective without a recoverable durable audit record.
|
|
242
|
-
|
|
243
|
-
## One canonical acquisition boundary
|
|
244
|
-
|
|
245
|
-
Every path capable of producing durable memory crosses the same boundary
|
|
246
|
-
(`core/knowledge/acquisition-boundary.ts`) before persistence: sanitize, strip
|
|
247
|
-
non-authoritative fields and evaluate the `memory.acquire` policy against the
|
|
248
|
-
payload. `memory.acquire` and the staged path
|
|
249
|
-
(`memory.acquireStaged` → `commitStageFile`) both cross it, so direct and
|
|
250
|
-
staged writes cannot diverge in enforcement. The staged commit additionally
|
|
251
|
-
refuses a stage file that still contains secret shapes after the boundary
|
|
252
|
-
re-sanitization. Equivalence tests pin the two paths to identical outcomes.
|
|
253
|
-
|
|
254
|
-
Policy conditions are evaluated against the action payload, not merely discovered:
|
|
255
|
-
|
|
256
|
-
| Condition outcome | Meaning | `precondition` behavior |
|
|
257
|
-
| --- | --- | --- |
|
|
258
|
-
| `satisfied` | the payload deterministically meets the condition | allow |
|
|
259
|
-
| `violated` | the payload deterministically fails the condition | block and ask the user |
|
|
260
|
-
| `unresolved` | the condition cannot be established (no payload) | block and ask the user — never assumed satisfied |
|
|
261
|
-
|
|
262
|
-
`memory.acquire()` itself evaluates the policies applicable to the `memory.acquire` event against
|
|
263
|
-
the payload about to be written and blocks with `PolicyPreconditionViolationError` when a
|
|
264
|
-
precondition is violated or unresolved. Without any policy, acquisition behaves exactly as before.
|
|
265
|
-
|
|
266
|
-
CLI: `npx dotmem policy <assign|list|remove|clear|eval|contract>`;
|
|
267
|
-
`policy eval --event <event> [--payload <json>]` exits with code 2 when the event is blocked.
|
|
268
|
-
Privileged override commands: `policy override grant|revoke|list` and `policy effective`
|
|
269
|
-
(see `policy --help`). Canonical events so far: `artifact.write`, `memory.acquire`.
|
|
270
|
-
|
|
271
|
-
Policy documents live under `policy/operator.policy.json` and `policy/security.policy.json`
|
|
272
|
-
in the storage root, each carrying its records, overrides, and durable audit trail. Filesystem-level
|
|
273
|
-
tamper isolation and policy signing remain open work (see `docs/SECURITY.md`).
|
|
274
|
-
|
|
275
|
-
## Retrieval semantics
|
|
276
|
-
|
|
277
|
-
- `memory.context({ acquired: query })` does exact applicability selection.
|
|
278
|
-
- `memory.discover(situation)` performs deterministic lexical and structured candidate
|
|
279
|
-
retrieval. It is not embedding or semantic-vector search.
|
|
280
|
-
- `memory.project(discovery)` returns bounded candidates and `text` marked as
|
|
281
|
-
untrusted prior context; it may omit candidates to meet its limits.
|
|
282
|
-
|
|
283
|
-
`DISCOVERED != APPLICABLE` and `PROJECTED != CURRENT FACT`.
|
|
284
|
-
|
|
285
|
-
`LABELLED != ATTESTED`: the epistemic label of a claim is written by the caller, never attested
|
|
286
|
-
by dotmem. See [Claim trust and attribution](#claim-trust-attribution-and-correction).
|
|
287
|
-
|
|
288
|
-
## Public API
|
|
289
|
-
|
|
290
|
-
| API | Purpose |
|
|
291
|
-
| --- | --- |
|
|
292
|
-
| `init()` | Deprecated compatibility shim that prepares the runtime lazily. |
|
|
293
|
-
| `acquire(opts)` | Persist an evidenced acquired claim using scope/kind routing. |
|
|
294
|
-
| `discover(situation, options?)` | Find lexical/structured active candidates. |
|
|
295
|
-
| `project(discovery, options?)` | Produce bounded, untrusted AI context. |
|
|
296
|
-
| `context(opts)` | Exact acquired-context selection or ranked key/value retrieval. |
|
|
297
|
-
| `policy.assign/list/remove/clear/evaluate/contract` | Privileged policy authority surface; see the Policy section. |
|
|
298
|
-
| `policy.override.grant/revoke/list/effective` | Privileged out-of-band override surface; see the Policy section. |
|
|
299
|
-
| `remember`, `recall`, `update`, `forget`, `patch` | Application key/value memory lifecycle. |
|
|
300
|
-
| `stats`, `forgetExpired`, `clear` | Maintenance; `clear()` is destructive and memory-scoped. |
|
|
301
|
-
| `createAgentMemory(agentId)` (`dotmem/agent`) | Agent-facing memory API with an isolated namespace per agent. |
|
|
302
|
-
|
|
303
|
-
`AcquireOptions` includes `id`, `knowledge`, `applicability`, and `evidence`; optional
|
|
304
|
-
fields are `epistemicType`, `provenance`, revision links, `scope`, `kind`, and
|
|
305
|
-
`sourceProject`. See the checked-in type declaration at `types/memory.d.ts` for the
|
|
306
|
-
precise TypeScript contract.
|
|
307
|
-
|
|
308
|
-
`memory.context({ acquired })` returns `{ knowledgeVersion, claims: AcquiredClaim[] }`
|
|
309
|
-
(the low-level acquired-context selection). The CLI `npx dotmem context --json` goes
|
|
310
|
-
through `discover` + `project` and returns a `ContextProjection` envelope with
|
|
311
|
-
`totalCandidates`, `omittedCandidates`, `experiences`, and `text`. The two surfaces are
|
|
312
|
-
intentionally different: the API returns raw claims, the CLI returns bounded, projected
|
|
313
|
-
context. `totalCandidates` is present on the CLI projection envelope, not on the raw
|
|
314
|
-
`AcquiredContext` returned by `memory.context({ acquired })`.
|
|
315
|
-
|
|
316
|
-
### Built-in seed claims
|
|
317
|
-
|
|
318
|
-
dotmem ships with a small set of built-in seed claims that describe the
|
|
319
|
-
acquisition logic itself. They are part of the product (`core/knowledge/logic-seed.ts`)
|
|
320
|
-
and are loaded into the logic knowledge store on every installation:
|
|
321
|
-
|
|
322
|
-
- `acquisition.experience-not-activity` — when to acquire (checkpoint principle)
|
|
323
|
-
- `acquisition.value-sources` — where useful memory comes from
|
|
324
|
-
- `acquisition.boundaries` — what to filter out, epistemic statuses
|
|
325
|
-
- `acquisition.project-specific` — project-specific experience candidates
|
|
326
|
-
- `relationship.continuity-pattern` — generalized AI-HI relationship pattern
|
|
327
|
-
|
|
328
|
-
They are marked as `source: built-in seed (dotmem acquisition logic seed)` in
|
|
329
|
-
`npx dotmem context --explain` output. They carry `epistemicType: inferred` and
|
|
330
|
-
`provenance.source: 'dotmem acquisition logic seed'`. They are read-only reference
|
|
331
|
-
material for the acquisition logic; they do not count as user-acquired experience.
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
The same memory is reachable from three surfaces: the CLI (`npx dotmem`), the MCP server
|
|
335
|
-
(`dotmem-mcp`, exposing `dotmem_context`, `dotmem_acquire`, and `dotmem_rules`), and
|
|
336
|
-
the JavaScript API. The MCP server writes through the same acquisition path as the CLI and
|
|
337
|
-
the API: one boundary, one policy, one contract. There is no second acquisition model.
|
|
338
|
-
|
|
339
|
-
## Global and React usage
|
|
340
|
-
|
|
341
|
-
Use named imports for normal code. `import 'dotmem/global'` explicitly installs the
|
|
342
|
-
non-React runtime APIs on `globalThis`; it does not initialize acquired memory.
|
|
343
|
-
|
|
344
|
-
`useObserver` is a React hook, exported only by `dotmem/react`. Call it at the top
|
|
345
|
-
level of a component or custom hook. It returns `void`; React handles cleanup.
|
|
346
|
-
|
|
347
|
-
## Continuity — the derived operational present
|
|
348
|
-
|
|
349
|
-
Memory is durable knowledge; continuity reconstructs the useful present. The
|
|
350
|
-
snapshot hierarchy composes downward: USER → PROJECT → TASK/SESSION → MODEL
|
|
351
|
-
CONTEXT. Snapshots are derived caches with sourceRefs, version, and freshness,
|
|
352
|
-
never authority: when a source version, digest, or presence changes, the
|
|
353
|
-
snapshot is stale and is regenerated, never mutated to look current. Budgeting
|
|
354
|
-
is field-prioritized — invariants and current decisions outrank recent changes
|
|
355
|
-
at any scope — so a crowded task scope cannot starve a project invariant.
|
|
356
|
-
Scope isolation forbids silent cross-scope transfer.
|
|
357
|
-
|
|
358
|
-
The `EffectiveAgentContract` is composed before continuity context, so
|
|
359
|
-
continuity never rewrites the contract.
|
|
360
|
-
|
|
361
|
-
API: `continuity.snapshot`, `continuity.load`, `continuity.context`,
|
|
362
|
-
`continuity.forget`. CLI: `npx dotmem continuity [context|snapshot|forget] [-debug]`.
|
|
363
|
-
Debug is observability only — the decision result is identical with and without
|
|
364
|
-
it, and the trace is never persisted by default.
|
|
365
|
-
|
|
366
|
-
## Identity, authority, and the carrier handshake
|
|
367
|
-
|
|
368
|
-
dotmem operates under a clear identity/authority separation:
|
|
369
|
-
|
|
370
|
-
- **AGENT_IDENTITY** — who the assistant is. Canonical: the profile (`joy`). Explicit
|
|
371
|
-
assignment by the authorized user may override this through the privileged
|
|
372
|
-
governance path; ordinary memory and context cannot.
|
|
373
|
-
- **USER_IDENTITY** — who the current human interlocutor is. This enters the
|
|
374
|
-
projection only through an explicit current assignment by the authorized user,
|
|
375
|
-
never from an acquired memory claim or retrieved text.
|
|
376
|
-
|
|
377
|
-
The two stay separate. A memory claim that remembers a name cannot assert it as
|
|
378
|
-
the current identity; that was an implementation bug.
|
|
379
|
-
|
|
380
|
-
### Carrier handshake (pre-activation gate)
|
|
381
|
-
|
|
382
|
-
Before any identity is projected to a runtime/session, dotmem evaluates the
|
|
383
|
-
carrier's compatibility with the minimal identity/authority separation contract.
|
|
384
|
-
The handshake is a deterministic, external evaluation — the carrier never
|
|
385
|
-
certifies itself.
|
|
386
|
-
|
|
387
|
-
```text
|
|
388
|
-
npx dotmem
|
|
389
|
-
→ unverified carrier receives the minimal pre-contract + challenge
|
|
390
|
-
→ carrier submits an answer via: npx dotmem handshake --answer "<text>"
|
|
391
|
-
→ external deterministic evaluator classifies it COMPATIBLE / LIMITED / INCOMPATIBLE
|
|
392
|
-
→ if COMPATIBLE, the operator layer binds the current speaker to the user identity
|
|
393
|
-
→ only a COMPATIBLE carrier + a trusted current binding receives the identity channel
|
|
394
|
-
```
|
|
395
|
-
|
|
396
|
-
States:
|
|
397
|
-
|
|
398
|
-
- **COMPATIBLE** — the carrier preserves identity composition, role, host-authority
|
|
399
|
-
separation, and memory-as-data. Activation may proceed with a trusted current binding.
|
|
400
|
-
- **LIMITED** — the carrier passed but did not demonstrate every capability. Activation
|
|
401
|
-
is withheld until the missing capabilities are demonstrated. An explicit canonical
|
|
402
|
-
profile request (`load Joy`) may receive a bounded,
|
|
403
|
-
non-authoritative profile envelope; it does not activate the profile, bind a user,
|
|
404
|
-
or upgrade the carrier.
|
|
405
|
-
- **INCOMPATIBLE** — the carrier violated a forbidden transition (e.g. mapping the host
|
|
406
|
-
onto HI authority). Identity activation is refused.
|
|
407
|
-
|
|
408
|
-
The handshake result is **session state, never durable authority** (`durableAuthority: false`).
|
|
409
|
-
It is bound to the runtime identity, contract revision, and handshake version; any change
|
|
410
|
-
re-triggers the handshake.
|
|
411
|
-
|
|
412
|
-
### Current-user binding
|
|
413
|
-
|
|
414
|
-
Carrier compatibility and current-user authority are **separate events**:
|
|
415
|
-
|
|
416
|
-
- A COMPATIBLE carrier still does not bind authority. It must be bound explicitly by
|
|
417
|
-
the operator layer (the trusted current channel):
|
|
418
|
-
|
|
419
|
-
```bash
|
|
420
|
-
npx dotmem handshake --bind-hi "<user name>" --scope "<scope>"
|
|
421
|
-
```
|
|
422
|
-
|
|
423
|
-
- The bind is scoped and current: it records `boundHIIdentity` (the identity bound to
|
|
424
|
-
this session) and `authorizationScope` (the scope of that binding). It is never
|
|
425
|
-
inferred from memory, history, files, or conversation.
|
|
426
|
-
- `--unbind` clears the current binding; the remembered identity stays informational.
|
|
427
|
-
- `--reset` invalidates the session state (recovery step 3); `--status` reports the
|
|
428
|
-
current session without evaluating anything.
|
|
429
|
-
|
|
430
|
-
### Identity/runtime separation
|
|
431
|
-
|
|
432
|
-
Host, provider, runtime, and model names are implementation metadata:
|
|
433
|
-
|
|
434
|
-
- The operational role name (`Joy`) comes from the profile, not from the runtime.
|
|
435
|
-
- The canonical identity is never fused with runtime/model metadata into a hybrid name
|
|
436
|
-
(e.g. `Joy` or `HI`). dotmem detects and rejects such fusion
|
|
437
|
-
attempts.
|
|
438
|
-
- `knownHIIdentity` (the remembered user identity) is informational only and never
|
|
439
|
-
authenticates the current speaker. Only `boundHIIdentity` (set by a trusted current
|
|
440
|
-
binding) authorizes activation.
|
|
441
|
-
|
|
442
|
-
See [`SECURITY.md`](./SECURITY.md)
|
|
443
|
-
|
|
444
|
-
## Boundaries
|
|
445
|
-
|
|
446
|
-
- `.mem` integrity and optional signatures do not make claims true or trustworthy.
|
|
447
|
-
- A claim's `epistemicType` and `provenance` are caller claims, not attestation.
|
|
448
|
-
- Namespaces and contexts are not authorization boundaries.
|
|
449
|
-
- Encryption is opt-in; key management belongs to the application.
|
|
450
|
-
- dotmem does not provide vector search, an IAM system, or secret management. Policy
|
|
451
|
-
authority separation for acquired experience is implemented (see Policy); OS-level
|
|
452
|
-
tamper isolation and policy signing remain open work.
|
|
453
|
-
|
|
454
|
-
## MCP server (`dotmem-mcp`)
|
|
455
|
-
|
|
456
|
-
dotmem ships a stdio MCP server (`dotmem-mcp`) so an AI host and the terminal share the same store. It exposes two read tools always, and a write tool only when the operator opts in via `DOTMEM_MCP_WRITE=1`:
|
|
457
|
-
|
|
458
|
-
| Tool | Direction | Registered when | Use it when |
|
|
459
|
-
| --- | --- | --- | --- |
|
|
460
|
-
| `dotmem_context` | read | always | You need the acquired experience relevant to the current situation. |
|
|
461
|
-
| `dotmem_rules` | read | always | You need the iron rules that constrain every session. |
|
|
462
|
-
| `dotmem_acquire` | write | `DOTMEM_MCP_WRITE=1` | The work produced reusable, project-specific experience worth keeping. |
|
|
463
|
-
|
|
464
|
-
Without `DOTMEM_MCP_WRITE=1`, `dotmem_acquire` is absent from `tools/list`: it does not appear, and calling it by name returns the transport's own "not found". The server never leaks the store path in error messages. `serverInfo.version` reports the package version, and `instructions` are built from boolean state only (write enabled / has experience), never from project-derived strings.
|
|
465
|
-
|
|
466
|
-
See [README.md](./README.md) for host registration examples (Kilo/OpenCode, Claude Desktop).
|
|
467
|
-
|
|
468
|
-
### Extra commands: proposed MCP exposure (no implementation yet)
|
|
469
|
-
|
|
470
|
-
The following CLI commands exist but are **not** exposed as MCP tools. This table records the proposal only; no command below becomes an MCP tool without a decision from Dario.
|
|
471
|
-
|
|
472
|
-
| Command | MCP Exposure | Risk |
|
|
473
|
-
| --- | --- | --- |
|
|
474
|
-
| `session` | none | Local session state; no need for remote exposure. |
|
|
475
|
-
| `loop` | none | Operator open loops; local management. |
|
|
476
|
-
| `vault` | none | Secrets: never exposed via MCP (untrusted channel). |
|
|
477
|
-
| `verify` | read-only | Freshness probes; read-only, low risk, but not high priority. |
|
|
478
|
-
| `guard` | none | Pre-execution policy evaluation: requires event context, not suitable for MCP. |
|
|
479
|
-
| `rule` / `rules` | read-only | Iron rules: already covered by `dotmem_rules`. |
|
|
480
|
-
| `violation` | none | Violation log: write-side, do not expose. |
|
|
481
|
-
| `violation clear` | none | Log deletion: destructive privileged operation. |
|
|
482
|
-
| `policy assign/remove/clear` | none | Policy assignments: require HI/operator authority; never via MCP. |
|
|
483
|
-
| `policy override grant/revoke` | none | Privileged override: requires explicit authority and audit. |
|
|
484
|
-
| `install-extension` | removed | Extension removed from the project (see point 4). |
|
|
485
|
-
|
|
486
|
-
### CLI command reference
|
|
487
|
-
|
|
488
|
-
| Command | Purpose | Example | Type |
|
|
489
|
-
| --- | --- | --- | --- |
|
|
490
|
-
| `context "<situation>"` | Project the acquired experience for the given situation | `npx dotmem context "css grid layout" --json --claims-only` | read |
|
|
491
|
-
| `init` | Create the project anchor in user storage | `npx dotmem init` | write |
|
|
492
|
-
| `acquire` | Acquire a durable claim from JSON on stdin | `cat claim.json \| npx dotmem acquire` | write |
|
|
493
|
-
| `learn "<text>"` | Acquisition from shorthand text | `npx dotmem learn "CSS rule" --id "css.1"` | write |
|
|
494
|
-
| `inspect FILE.mem` | Validate and decode a `.mem` package | `npx dotmem inspect user.mem` | read |
|
|
495
|
-
| `continuity` | Compose USER+PROJECT+TASK continuity | `npx dotmem continuity context` | read |
|
|
496
|
-
| `handshake` | Carrier compatibility gate and authority binding | `npx dotmem handshake --answer "..."` | privileged |
|
|
497
|
-
| `storage` | Show/relocate/restore the storage root | `npx dotmem storage --root` | read/write |
|
|
498
|
-
| `policy` | Manage policy assignments and contracts | `npx dotmem policy list` | privileged |
|
|
499
|
-
| `doctor [--json] [--fix]` | Duplicate and integrity audit | `npx dotmem doctor` | read |
|
|
500
|
-
| `session [show\|doing]` | Current task state of the session | `npx dotmem session doing "task"` | read/write |
|
|
501
|
-
| `loop <subcommand>` | Manage open loops (add\|list\|close\|show) | `npx dotmem loop add lp-1 "task"` | write |
|
|
502
|
-
| `vault <subcommand>` | Local handle→value vault (put\|resolve\|list\|forget) | `npx dotmem vault put val --handle h1` | write |
|
|
503
|
-
| `verify` | Freshness probes on claims | `npx dotmem verify` | read |
|
|
504
|
-
| `guard <event> [--payload]` | Policy evaluation before a tool action | `npx dotmem guard tool.git-commit` | read |
|
|
505
|
-
| `rule` / `rules` | Print the iron rules | `npx dotmem rules` | read |
|
|
506
|
-
| `violation` | Violation log (list\|clear) | `npx dotmem violation list` | read/write |
|
|
507
|
-
| `feedback <id> <type>` | Record operator feedback on a claim | `npx dotmem feedback id helped` | write |
|
|
508
|
-
| `codenames` | Print reserved codenames | `npx dotmem codenames` | read |
|
|
509
|
-
| `render <view>` | Render a markdown view from the store | `npx dotmem render agent-rules` | read |
|
|
510
|
-
| `spark --verify` | Verify the scintilla block in docs/AGENTS.md | `npx dotmem spark --verify` | read |
|
|
511
|
-
| `--version` / `-v` | Show the package version | `npx dotmem --version` | read |
|
|
512
|
-
|
|
513
|
-
`guard --payload`: pass the JSON as a string argument. On PowerShell the double quotes in arguments are stripped, so use a file: save the JSON in `payload.json`, then read the file and use its contents, or use stdin where supported.
|
|
514
|
-
|
|
515
|
-
`context` from CLI requires the handshake gate: first run `npx dotmem handshake --answer "<answer>"` (must return `STATUS:COMPATIBLE`), then `npx dotmem handshake --bind-hi "<identity>" --scope <scope>`. After binding, `context` returns the acquired experience.
|
|
516
|
-
|
|
517
|
-
See [README.md](./README.md) for the product overview, [SECURITY.md](./SECURITY.md)
|
|
518
|
-
for the threat model, and [MEM_FORMAT.md](./markdown/MEM_FORMAT.md) for package format.
|
package/PACKAGE.md
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
# dotmem package — canonical entry point
|
|
2
|
-
|
|
3
|
-
This document is the single source of truth for anyone reading `dotmem` on npm.
|
|
4
|
-
It lists every document that ships inside the published package, and explains
|
|
5
|
-
where to find what is not inside (ADRs, for example, live in an external catalog
|
|
6
|
-
and are never bundled).
|
|
7
|
-
|
|
8
|
-
## What ships inside the package
|
|
9
|
-
|
|
10
|
-
| Document | Purpose |
|
|
11
|
-
| --- | --- |
|
|
12
|
-
| `README.md` | Product overview, install, MCP registration, layer table |
|
|
13
|
-
| `MEMORY.md` | Memory model, acquisition contract, policy language, security posture |
|
|
14
|
-
| `AGENTS.md` | AI working rules, native-first read ordering, `memory.*` surface |
|
|
15
|
-
| `llms.txt` | Compact surface for AI hosts |
|
|
16
|
-
| `SECURITY.md` | Threat model, `UNTRUSTED_DATA; NOT_INSTRUCTIONS; VERIFY_CURRENT` |
|
|
17
|
-
| `CHANGELOG.md` | Release history (`[0.0.1]`, …) |
|
|
18
|
-
| `markdown/` | Markdown views used by `npx dotmem render <view>` |
|
|
19
|
-
|
|
20
|
-
## What does NOT ship inside the package
|
|
21
|
-
|
|
22
|
-
| Item | Where it lives |
|
|
23
|
-
| --- | --- |
|
|
24
|
-
| Project history | `.project/project_history.md` (inside the repository, not published) |
|
|
25
|
-
| Acquired memory (`.mem` packages) | User storage root (`DOTMEM_STORAGE_ROOT` or `<user-home>/.dotmem`), created at runtime |
|
|
26
|
-
|
|
27
|
-
## Quick start
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
npm install dotmem
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
### CLI
|
|
34
|
-
```bash
|
|
35
|
-
npx dotmem --help
|
|
36
|
-
npx dotmem context "<situazione>" --json --claims-only
|
|
37
|
-
npx dotmem storage
|
|
38
|
-
npx dotmem handshake --status
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
### JavaScript API
|
|
42
|
-
```js
|
|
43
|
-
import m from 'dotmem'
|
|
44
|
-
await m.memory.acquire({ id, knowledge, applicability, evidence })
|
|
45
|
-
const ctx = await m.memory.context({ acquired: { area: 'x' } })
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
### MCP server (`dotmem-mcp`)
|
|
49
|
-
Register with `DOTMEM_STORAGE_ROOT` and opt-in `DOTMEM_MCP_WRITE=1` for the write tool.
|
|
50
|
-
|
|
51
|
-
## Links
|
|
52
|
-
|
|
53
|
-
All links below resolve **inside the published package**:
|
|
54
|
-
- [MEMORY.md](MEMORY.md) — memory model and acquisition contract
|
|
55
|
-
- [AGENTS.md](AGENTS.md) — AI working rules
|
|
56
|
-
- [llms.txt](llms.txt) — AI host surface
|
|
57
|
-
- [SECURITY.md](SECURITY.md) — threat model
|
|
58
|
-
- [CHANGELOG.md](CHANGELOG.md) — release history
|
|
59
|
-
- [markdown/](markdown/) — render views
|