dotmem 0.0.2 → 0.0.3

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/MEMORY.md ADDED
@@ -0,0 +1,518 @@
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 ADDED
@@ -0,0 +1,59 @@
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