memorio 4.9.35 → 5.0.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.
Files changed (76) hide show
  1. package/AGENTS.md +3 -3
  2. package/README.md +307 -359
  3. package/SECURITY.md +17 -1
  4. package/SUMMARY.md +59 -45
  5. package/adr/001-state-proxy-model.md +96 -0
  6. package/adr/002-observer-semantics.md +180 -0
  7. package/adr/003-deep-mutation-semantics.md +129 -0
  8. package/adr/004-array-mutation-semantics.md +128 -0
  9. package/adr/005-scheduler-contract.md +149 -0
  10. package/adr/006-context-isolation.md +92 -0
  11. package/adr/007-mutation-records.md +118 -0
  12. package/adr/008-transactions.md +106 -0
  13. package/adr/009-history-model.md +110 -0
  14. package/adr/README.md +46 -0
  15. package/adr/template.md +49 -0
  16. package/examples/basic.ts +115 -115
  17. package/examples/browser-vanilla.html +358 -358
  18. package/examples/cache.ts +72 -72
  19. package/examples/cross-platform-guards.ts +57 -57
  20. package/examples/history.ts +104 -0
  21. package/examples/idb.ts +109 -109
  22. package/examples/multi-tenant-context.ts +44 -44
  23. package/examples/node-server.ts +308 -308
  24. package/examples/observer.ts +60 -60
  25. package/examples/platform.ts +115 -115
  26. package/examples/react-app.tsx +362 -362
  27. package/examples/react-observer.tsx +63 -63
  28. package/examples/semantic-memory.ts +60 -60
  29. package/examples/session-advanced.ts +91 -91
  30. package/examples/sqlite-batched-writes.ts +57 -57
  31. package/examples/state-advanced.ts +89 -89
  32. package/examples/store-advanced.ts +117 -117
  33. package/examples/sync.ts +90 -0
  34. package/examples/typed-and-schema.ts +102 -100
  35. package/examples/useObserver.tsx +140 -141
  36. package/global.cjs +4594 -0
  37. package/global.d.ts +8 -0
  38. package/global.js +4532 -0
  39. package/index.cjs +700 -678
  40. package/index.d.ts +1 -0
  41. package/index.js +680 -677
  42. package/llms.txt +72 -4
  43. package/markdown/AUDIT-REPORT.md +135 -0
  44. package/markdown/CACHE.md +100 -0
  45. package/markdown/CHANGELOG.md +243 -0
  46. package/markdown/DEVTOOLS.md +129 -0
  47. package/markdown/DISPATCH.md +177 -0
  48. package/markdown/HISTORY.md +199 -0
  49. package/markdown/IDB.md +178 -0
  50. package/markdown/IMPORT.md +153 -0
  51. package/markdown/INSPECT.md +123 -0
  52. package/markdown/LOGGER.md +154 -0
  53. package/markdown/MEMORY-ATTACHMENT.md +96 -0
  54. package/markdown/MEMORY.md +162 -0
  55. package/markdown/OBSERVER.md +209 -0
  56. package/markdown/PLATFORM.md +271 -0
  57. package/markdown/PROJECT.md +311 -0
  58. package/markdown/SCHEMA.md +176 -0
  59. package/markdown/SECURITY.md +330 -0
  60. package/markdown/SESSION.md +165 -0
  61. package/markdown/SQLITE.md +190 -0
  62. package/markdown/STATE.md +160 -0
  63. package/markdown/STORE.md +171 -0
  64. package/markdown/SYNC.md +319 -0
  65. package/markdown/TYPED.md +165 -0
  66. package/markdown/USEOBSERVER.md +257 -0
  67. package/modules/redux.cjs +320 -167
  68. package/modules/redux.cjs.map +1 -1
  69. package/modules/redux.js +320 -167
  70. package/modules/redux.js.map +1 -1
  71. package/package.json +13 -3
  72. package/types/env.d.ts +19 -9
  73. package/types/exports.d.ts +20 -0
  74. package/types/history.d.ts +13 -1
  75. package/types/memorio.d.ts +17 -5
  76. package/types/mutation.d.ts +75 -0
@@ -0,0 +1,153 @@
1
+ > **Status:** Published
2
+ > **Date:** 2026-09-12
3
+ > **Deciders:** Memorio 5.x Core Team
4
+ > **Scope**: API Reference
5
+ > **Standard**: Memorio API Specification v5
6
+ >
7
+ ---
8
+ # Classic `import` support
9
+
10
+ Memorio supports two styles: the explicit named-import style (recommended),
11
+ and the global side-effect entrypoint for when global access is explicitly desired.
12
+ Both share the same instances (one source of truth).
13
+
14
+ ```typescript
15
+ // Explicit named imports (recommended for normal usage)
16
+ import { state } from 'memorio'
17
+ state.user = { name: 'Sara' }
18
+
19
+ // Global entrypoint (opt-in for global access)
20
+ import 'memorio/global'
21
+ state.user = { name: 'Sara' }
22
+ ```
23
+
24
+ `state` in both examples is the exact same Proxy object.
25
+
26
+ ---
27
+
28
+ ## Why two styles?
29
+
30
+ | Style | When to use |
31
+ |-------|-------------|
32
+ | `import { state } from 'memorio'` | Explicit dependencies, tree-shakeable bundles, TypeScript IntelliSense |
33
+ | `import 'memorio/global'` | When global access is explicitly desired (legacy scripts, shell-style usage) |
34
+
35
+ ---
36
+
37
+ ## ESM named imports
38
+
39
+ All modules are available as named exports:
40
+
41
+ ```typescript
42
+ import {
43
+ state,
44
+ store,
45
+ session,
46
+ cache,
47
+ idb,
48
+ observer,
49
+ useObserver,
50
+ dispatch,
51
+ message,
52
+ devtools,
53
+ logger
54
+ } from 'memorio'
55
+ ```
56
+
57
+ Platform helpers:
58
+
59
+ ```typescript
60
+ import {
61
+ isBrowser,
62
+ isNode,
63
+ isDeno,
64
+ isEdge,
65
+ getCapabilities,
66
+ createContext,
67
+ listContexts,
68
+ deleteContext
69
+ } from 'memorio'
70
+ ```
71
+
72
+ Internal utilities (for tests/debug):
73
+
74
+ ```typescript
75
+ import internal, { propertyName } from 'memorio'
76
+ import { setContext, getContext } from 'memorio'
77
+ ```
78
+
79
+ Default export (the public `memorio` namespace):
80
+
81
+ ```typescript
82
+ import memorio from 'memorio'
83
+ memorio.help() // dev-only introspection
84
+ ```
85
+
86
+ ---
87
+
88
+ ## CJS usage
89
+
90
+ ```javascript
91
+ const { state, store, memorio } = require('memorio')
92
+ ```
93
+
94
+ ---
95
+
96
+ ## React / useObserver
97
+
98
+ `useObserver` works the same way via named import:
99
+
100
+ ```tsx
101
+ import { useObserver, state } from 'memorio'
102
+
103
+ function Counter() {
104
+ const [, forceUpdate] = useReducer(x => x + 1, 0)
105
+
106
+ useObserver(forceUpdate, [state.counter])
107
+
108
+ return <div>Count: {state.counter}</div>
109
+ }
110
+ ```
111
+
112
+ ---
113
+
114
+ ## Context isolation
115
+
116
+ ```typescript
117
+ import { createContext, listContexts, deleteContext, isolate } from 'memorio'
118
+
119
+ const ctx = createContext('tenant-123')
120
+ ctx.state.user = { name: 'Isolated' }
121
+ ctx.store.set('settings', { theme: 'dark' })
122
+
123
+ listContexts() // ['tenant-123']
124
+ deleteContext('tenant-123')
125
+ ```
126
+
127
+ ---
128
+
129
+ ## Same-instance guarantee
130
+
131
+ Named exports point to the same instances as the global entrypoint. Mutating via a named export mutates the same proxy instance that `import 'memorio/global'` would install on `globalThis`, and vice versa.
132
+
133
+ ```typescript
134
+ import { state } from 'memorio'
135
+
136
+ state.importedFlag = true
137
+ console.debug(globalThis.state?.importedFlag) // true (when global entrypoint is loaded)
138
+ ```
139
+
140
+ ---
141
+
142
+ ## Migration to explicit imports
143
+
144
+ If you previously used `import 'memorio'` for global access, migrate to either:
145
+
146
+ ```typescript
147
+ // Option A: named imports (recommended)
148
+ import { state, store } from 'memorio'
149
+
150
+ // Option B: explicit global entrypoint (opt-in)
151
+ import 'memorio/global'
152
+ // state, store, etc. are now on globalThis
153
+ ```
@@ -0,0 +1,123 @@
1
+ > **Status:** Published
2
+ > **Date:** 2026-09-12
3
+ > **Deciders:** Memorio 5.x Core Team
4
+ > **Scope**: API Reference
5
+ > **Standard**: Memorio API Specification v5
6
+ >
7
+ ---
8
+ # Introspection & Inspection - Memorio
9
+
10
+ > ✅ **Universal**: Works in Browser, Node.js, Deno, and Edge Workers
11
+
12
+ Introspection utilities let you programmatically discover, verify, and read the shape of the global `state` proxy. Essential for AI agents that need to check whether a path exists before writing, or enumerate available keys before reading.
13
+
14
+ ---
15
+
16
+ ## stateKeys()
17
+
18
+ Returns all top-level keys currently on the `state` proxy. Excludes internal properties.
19
+
20
+ ```javascript
21
+ import { state, memorio } from 'memorio'
22
+
23
+ state.user = { name: 'Sara' }
24
+ state.counter = 42
25
+
26
+ memorio.stateKeys() // ['user', 'counter']
27
+ ```
28
+
29
+ ---
30
+
31
+ ## pathExists(path)
32
+
33
+ Checks whether a dotted path exists in state. Returns `true` if the path resolves to a non-undefined value.
34
+
35
+ ```javascript
36
+ state.user = { name: 'Sara', profile: { age: 30 } }
37
+
38
+ memorio.pathExists('user') // true
39
+ memorio.pathExists('user.name') // true
40
+ memorio.pathExists('user.profile') // true
41
+ memorio.pathExists('user.profile.age') // true
42
+ memorio.pathExists('user.age') // false
43
+ memorio.pathExists('nonexistent') // false
44
+ ```
45
+
46
+ This is critical for AI agents: always check `pathExists` before writing to a nested path to avoid creating unintended intermediate objects.
47
+
48
+ ---
49
+
50
+ ## stateType(path)
51
+
52
+ Returns the runtime type of the value at a given state path.
53
+
54
+ ```javascript
55
+ state.count = 42
56
+ state.name = 'Sara'
57
+ state.items = [1, 2, 3]
58
+
59
+ memorio.stateType('count') // 'number'
60
+ memorio.stateType('name') // 'string'
61
+ memorio.stateType('items') // 'array'
62
+ memorio.stateType('missing') // 'undefined'
63
+ ```
64
+
65
+ ---
66
+
67
+ ## stateGet(path)
68
+
69
+ Returns the value at a dotted path, deep-cloned to prevent accidental mutation of state.
70
+
71
+ ```javascript
72
+ state.user = { name: 'Sara', tags: ['admin'] }
73
+
74
+ const user = memorio.stateGet('user') // { name: 'Sara', tags: ['admin'] }
75
+ user.name = 'Luigi' // mutates the clone, not state
76
+ state.user.name // still 'Sara'
77
+ ```
78
+
79
+ ---
80
+
81
+ ## stateSchema()
82
+
83
+ Generates a full schema report of the current state tree - every path with its type and whether it's defined.
84
+
85
+ ```javascript
86
+ state.user = { name: 'Sara', age: 30 }
87
+ state.theme = 'dark'
88
+
89
+ memorio.stateSchema()
90
+ // [
91
+ // { path: 'user', type: 'object', defined: true },
92
+ // { path: 'user.name', type: 'string', defined: true },
93
+ // { path: 'user.age', type: 'number', defined: true },
94
+ // { path: 'theme', type: 'string', defined: true }
95
+ // ]
96
+ ```
97
+
98
+ This is the **most useful for AI agents** - it gives a complete picture of what's in state and what types the values are, in a single call. Perfect for:
99
+ - Discovering available state before generating code
100
+ - Validating that expected paths exist
101
+ - Understanding the shape of nested objects
102
+
103
+ ---
104
+
105
+ ## Full API
106
+
107
+ | Method | Parameters | Returns | Description |
108
+ |--------|-----------|---------|-------------|
109
+ | `memorio.stateKeys()` | none | `string[]` | Top-level state keys |
110
+ | `memorio.pathExists(path)` | `string` | `boolean` | Whether a path resolves to a value |
111
+ | `memorio.stateType(path)` | `string` | `string` | Runtime type at path |
112
+ | `memorio.stateGet(path)` | `string` | `any` | Deep-cloned value at path |
113
+ | `memorio.stateSchema()` | none | `SchemaEntry[]` | Full state tree report |
114
+
115
+ ---
116
+
117
+ ## How It Works
118
+
119
+ All introspection functions read from the global `state` proxy via `deepRaw()` - the same function used internally by the state proxy to unwrap itself before storing. This ensures consistent, non-proxied values are returned.
120
+
121
+ - `pathExists` and `stateGet` split the path on `.` and traverse the state tree.
122
+ - `stateSchema` recursively walks the state object, collecting every path and its type.
123
+ - All returned values from `stateGet` and `snapshot` are deep clones (via JSON round-trip) to prevent accidental mutation.
@@ -0,0 +1,154 @@
1
+ > **Status:** Published
2
+ > **Date:** 2026-09-12
3
+ > **Deciders:** Memorio 5.x Core Team
4
+ > **Scope**: API Reference
5
+ > **Standard**: Memorio API Specification v5
6
+ >
7
+ ---
8
+ # Memorio Logger
9
+
10
+ > 🖥️ **Browser Only**: This feature is only available in browser console
11
+
12
+ Automatic logging middleware for tracking all state changes in Memorio.
13
+
14
+ ## Overview
15
+
16
+ The logger automatically tracks all operations (set, delete, clear) across all modules:
17
+ - State
18
+ - Store
19
+ - Session
20
+ - Cache
21
+
22
+ ## Configuration
23
+
24
+ ### configure(options)
25
+
26
+ Configure the logger.
27
+
28
+ ```javascript
29
+ memorio.logger.configure({
30
+ enabled: true, // Enable/disable logging
31
+ logToConsole: true, // Log to browser console
32
+ customHandler: function(entry) { ... }, // Custom handler
33
+ modules: ['state', 'store', 'session', 'cache'], // Modules to log
34
+ maxEntries: 1000 // Maximum log history size
35
+ })
36
+ ```
37
+
38
+ ### enable()
39
+
40
+ Enable logging.
41
+
42
+ ```javascript
43
+ memorio.logger.enable()
44
+ ```
45
+
46
+ ### disable()
47
+
48
+ Disable logging.
49
+
50
+ ```javascript
51
+ memorio.logger.disable()
52
+ ```
53
+
54
+ ## Methods
55
+
56
+ ### getHistory()
57
+
58
+ Get all log entries.
59
+
60
+ ```javascript
61
+ const history = memorio.logger.getHistory()
62
+ // Returns array of LogEntry objects
63
+ ```
64
+
65
+ ### getStats()
66
+
67
+ Get statistics about logged operations.
68
+
69
+ ```javascript
70
+ const stats = memorio.logger.getStats()
71
+ // Returns: { total, state, store, session, cache, set, get, delete, clear }
72
+ ```
73
+
74
+ ### clearHistory()
75
+
76
+ Clear log history.
77
+
78
+ ```javascript
79
+ memorio.logger.clearHistory()
80
+ ```
81
+
82
+ ### exportLogs()
83
+
84
+ Export logs as JSON string.
85
+
86
+ ```javascript
87
+ const json = memorio.logger.exportLogs()
88
+ ```
89
+
90
+ ## Log Entry Structure
91
+
92
+ ```javascript
93
+ {
94
+ timestamp: "2026-02-18T12:00:00.000Z",
95
+ module: "state",
96
+ action: "set",
97
+ path: "user.name",
98
+ value: "John",
99
+ previousValue: "Jane"
100
+ }
101
+ ```
102
+
103
+ ## Examples
104
+
105
+ ### Basic usage
106
+
107
+ ```javascript
108
+ // Logging is enabled by default
109
+ state.user = { name: 'John' }
110
+ // Console: [Memorio:STATE] set user → value: { name: 'John' }
111
+ ```
112
+
113
+ ### Get statistics
114
+
115
+ ```javascript
116
+ const stats = memorio.logger.getStats()
117
+ console.debug(stats)
118
+ // { total: 15, state: 5, store: 3, session: 2, cache: 5, set: 10, get: 0, delete: 3, clear: 2 }
119
+ ```
120
+
121
+ ### Disable specific modules
122
+
123
+ ```javascript
124
+ memorio.logger.configure({
125
+ modules: ['state'] // Only log state changes
126
+ })
127
+ ```
128
+
129
+ ### Custom handler
130
+
131
+ ```javascript
132
+ memorio.logger.configure({
133
+ customHandler: (entry) => {
134
+ // Send to analytics
135
+ analytics.track('memorio_change', entry)
136
+ }
137
+ })
138
+ ```
139
+
140
+ ### Export and analyze
141
+
142
+ ```javascript
143
+ // Get all logs
144
+ const logs = memorio.logger.getHistory()
145
+
146
+ // Filter by module
147
+ const stateLogs = logs.filter(l => l.module === 'state')
148
+
149
+ // Filter by action
150
+ const setOperations = logs.filter(l => l.action === 'set')
151
+
152
+ // Export for debugging
153
+ console.debug(memorio.logger.exportLogs())
154
+ ```
@@ -0,0 +1,96 @@
1
+ > **Status:** Published
2
+ > **Date:** 2026-09-12
3
+ > **Deciders:** Memorio 5.x Core Team
4
+ > **Scope**: API Reference
5
+ > **Standard**: Memorio API Specification v5
6
+ >
7
+ ---
8
+ # Node Attachment System
9
+
10
+ `memorio.memory` extends with a **Node Attachment System** allowing memory elements to dynamically attach, reference, or connect to other memory elements at runtime.
11
+
12
+ This is an **extension**, not a replacement, of existing memory semantics.
13
+
14
+ ## Concepts
15
+
16
+ ```text
17
+ Memory
18
+ └── Node
19
+ ├── identity
20
+ ├── value
21
+ ├── metadata
22
+ └── relationships
23
+ └── Edge
24
+ ├── target
25
+ ├── relation
26
+ ├── metadata
27
+ ├── confidence
28
+ └── lifecycle
29
+ ```
30
+
31
+ ## API
32
+
33
+ ```ts
34
+ const user = await memory.remember("user", { name: "Alice" })
35
+ const project = await memory.remember("project", { name: "Memorio" })
36
+
37
+ await user.connect(project, { relation: "works-on", confidence: 0.95 })
38
+ await user.attach(project) // → connect with relation "attached-to"
39
+
40
+ const related = await user.related({ direction: "both", relation: "works-on" })
41
+ const tree = await user.traverse({ depth: 3 })
42
+ ```
43
+
44
+ ### Methods
45
+
46
+ | Method | Description |
47
+ |--------|-------------|
48
+ | `node.connect(target, opts?)` | Create a directed relationship |
49
+ | `node.disconnect(target, opts?)` | Remove a relationship |
50
+ | `node.related(opts?)` | Query related nodes |
51
+ | `node.traverse(opts?)` | Bounded graph traversal |
52
+ | `memory.connect(source, target, opts?)` | Low-level connect |
53
+ | `memory.disconnect(source, target, opts?)` | Low-level disconnect |
54
+
55
+ ## Scopes
56
+
57
+ Relationship visibility respects memory scopes - a query in one scope cannot leak inaccessible nodes from another.
58
+
59
+ ## Persistence
60
+
61
+ Relationships use **IDs**, never embedded objects:
62
+
63
+ ```json
64
+ {
65
+ "id": "user",
66
+ "relationships": [
67
+ { "target": "project", "relation": "works-on" }
68
+ ]
69
+ }
70
+ ```
71
+
72
+ ## Lifecycle
73
+
74
+ - **TTL**: independent per node/edge - does not propagate
75
+ - **Confidence**: independent - node and edge have separate confidence values
76
+ - **Deletion**: deleting a node removes its edges (default policy)
77
+ - **Cycles**: supported with visited-set protection during traversal
78
+ - **Dangling references**: `retain` by default (configurable)
79
+
80
+ ## Security
81
+
82
+ Relationship traversal inherits the same scope/access rules as direct retrieval. A user cannot gain access to Node B merely because Node A connects to it.
83
+
84
+ ## Serialization
85
+
86
+ Nodes serialize to IDs only - never recursively embedded graphs.
87
+
88
+ ## Performance
89
+
90
+ - `O(1)` indexed lookup for direct node retrieval
91
+ - Graph traversal only on explicit request
92
+ - Indexable by `source`, `target`, `relation`
93
+
94
+ ## Backward Compatibility
95
+
96
+ Existing APIs (`remember`, `get`, `forget`, `search`) continue to work unchanged. A node-enabled memory entry remains usable as a normal memory entry.
@@ -0,0 +1,162 @@
1
+ > **Status:** Published
2
+ > **Date:** 2026-09-12
3
+ > **Deciders:** Memorio 5.x Core Team
4
+ > **Scope**: API Reference
5
+ > **Standard**: Memorio API Specification v5
6
+ >
7
+ ---
8
+ # Memory System
9
+
10
+ `memorio.memory` provides a semantic memory layer - a key/value store with type safety, TTL, confidence scoring, tagging, and scope-based persistence.
11
+
12
+ ## Core API
13
+
14
+ ### `memorio.memory.remember(key, value, opts?)`
15
+
16
+ Stores a memory entry.
17
+
18
+ ```ts
19
+ await memorio.memory.remember('user.name', 'Dario', {
20
+ type: 'preference',
21
+ confidence: 0.92,
22
+ scope: 'local',
23
+ ttl: null,
24
+ tags: ['user', 'profile'],
25
+ source: 'conversation'
26
+ })
27
+ ```
28
+
29
+ | Option | Type | Default | Description |
30
+ |--------|------|---------|-------------|
31
+ | `id` | `string` | `key` | Custom entry ID |
32
+ | `type` | `'fact' \| 'preference' \| 'decision' \| 'task' \| 'context'` | `'fact'` | Semantic classification |
33
+ | `confidence` | `number` | `1.0` | Trust score 0.0–1.0 |
34
+ | `scope` | `'hot' \| 'session' \| 'local' \| 'durable'` | auto | Storage backend (see below) |
35
+ | `ttl` | `number \| null` | `null` | Milliseconds before expiry (`null` = never) |
36
+ | `tags` | `string \| string[]` | `[]` | Metadata for filtering |
37
+ | `source` | `string` | `undefined` | Origin of the memory |
38
+
39
+ ### `memorio.memory.recall(query, opts?)`
40
+
41
+ Retrieves a memory by key.
42
+
43
+ ```ts
44
+ const name = await memorio.memory.recall('user.name')
45
+ const highConfidence = await memorio.memory.recall('project', {
46
+ minConfidence: 0.8
47
+ })
48
+ ```
49
+
50
+ | Option | Type | Default | Description |
51
+ |--------|------|---------|-------------|
52
+ | `type` | `MemoryType \| MemoryType[]` | `*` | Filter by type |
53
+ | `tags` | `string \| string[]` | `*` | Filter by tags |
54
+ | `minConfidence` | `number` | `0` | Minimum confidence threshold |
55
+ | `includeObsolete` | `boolean` | `false` | Include expired/superseded entries |
56
+
57
+ ### `memorio.memory.update(key, value, opts?)`
58
+
59
+ Updates an existing memory. Creates a **superseded copy** of the old entry (preserving history).
60
+
61
+ ```ts
62
+ await memorio.memory.update('user.name', 'Alice', { confidence: 0.95 })
63
+ ```
64
+
65
+ ### `memorio.memory.forget(key)`
66
+
67
+ Permanently removes a memory.
68
+
69
+ ```ts
70
+ await memorio.memory.forget('user.temp')
71
+ ```
72
+
73
+ ### `memorio.memory.context(opts?)`
74
+
75
+ Returns ranked, relevant memories. Uses recency × confidence × type/scope boost algorithm.
76
+
77
+ ```ts
78
+ const ctx = await memorio.memory.context({
79
+ tags: 'project',
80
+ types: ['decision', 'preference'],
81
+ minConfidence: 0.7,
82
+ maxEntries: 10,
83
+ scopes: ['local', 'durable']
84
+ })
85
+ ```
86
+
87
+ Returns:
88
+ ```ts
89
+ Array<{
90
+ key: string
91
+ value: any
92
+ type: MemoryType
93
+ confidence: number
94
+ scope: MemoryScope
95
+ tags: string[]
96
+ age: number // milliseconds since createdAt
97
+ accessCount: number
98
+ lastAccessedAt: number
99
+ }>
100
+ ```
101
+
102
+ ### `memorio.memory.stats()`
103
+
104
+ Returns usage statistics:
105
+
106
+ ```ts
107
+ {
108
+ total: number
109
+ byScope: Record<MemoryScope, number>
110
+ byType: Partial<Record<MemoryType, number>>
111
+ expired: number
112
+ }
113
+ ```
114
+
115
+ ### `memorio.memory.forgetExpired()`
116
+
117
+ Cleans all expired entries. Returns count removed.
118
+
119
+ ### `memorio.memory.clear()`
120
+
121
+ Wipes all memories and the index.
122
+
123
+ ## Memory Entry Model
124
+
125
+ ```ts
126
+ interface MemoryEntry<T = any> {
127
+ id: string
128
+ key: string
129
+ value: T
130
+ type: 'fact' | 'preference' | 'decision' | 'task' | 'context'
131
+ confidence: number
132
+ scope: 'hot' | 'session' | 'local' | 'durable'
133
+ ttl?: number | null
134
+ tags: string[]
135
+ source?: string
136
+ status: 'active' | 'obsolete' | 'superseded'
137
+ createdAt: number
138
+ lastConfirmedAt: number
139
+ supersededId?: string | null
140
+ }
141
+ ```
142
+
143
+ ## Scopes
144
+
145
+ | Scope | Storage | TTL | Cross-session | Size limit |
146
+ |-------|---------|-----|---------------|------------|
147
+ | `hot` | `state` proxy | ✅ | ❌ | ~5MB (RAM) |
148
+ | `session` | `sessionStorage` | ✅ | Tab only | ~5MB |
149
+ | `local` | `localStorage` | ✅ | ✅ | ~10MB |
150
+ | `durable` | `IndexedDB` | ✅ | ✅ | ~1GB+ |
151
+
152
+ Default scope is `local` for values ≤100KB, `durable` for larger values.
153
+
154
+ ## Memory Lifecycle
155
+
156
+ | Event | Behavior |
157
+ |-------|----------|
158
+ | `remember()` on existing key | Old entry → `superseded`, new entry → `active` |
159
+ | Entry with TTL expires | Status → `obsolete` (cleaned by `forgetExpired()`) |
160
+ | `recall()` expired entry | Returns `null` unless `includeObsolete: true` |
161
+ | `update()` | Creates superseded copy + updated active entry |
162
+ | `clear()` | Wipes all memories + index |