memorio 5.0.0 → 5.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +98 -435
- package/SECURITY.md +152 -42
- package/SUMMARY.md +1 -1
- package/adr/001-state-proxy-model.md +95 -96
- package/adr/002-observer-semantics.md +179 -180
- package/adr/003-deep-mutation-semantics.md +7 -8
- package/adr/004-array-mutation-semantics.md +127 -128
- package/adr/005-scheduler-contract.md +148 -149
- package/adr/006-context-isolation.md +91 -92
- package/adr/007-mutation-records.md +5 -6
- package/adr/008-transactions.md +6 -7
- package/adr/009-history-model.md +6 -7
- package/adr/README.md +46 -46
- package/adr/template.md +48 -49
- package/bin/cli.js +68 -0
- package/global.cjs +1462 -323
- package/global.js +1459 -324
- package/index.cjs +1462 -323
- package/index.d.ts +1 -0
- package/index.js +1459 -324
- package/llms.txt +42 -5
- package/markdown/AUDIT-REPORT.md +7 -8
- package/markdown/CACHE.md +190 -99
- package/markdown/DEVTOOLS.md +0 -1
- package/markdown/DISPATCH.md +0 -1
- package/markdown/HISTORY.md +0 -1
- package/markdown/IDB.md +0 -1
- package/markdown/IMPORT.md +0 -1
- package/markdown/INSPECT.md +0 -1
- package/markdown/LOGGER.md +0 -1
- package/markdown/MEMORY-ATTACHMENT.md +0 -1
- package/markdown/MEMORY.md +0 -1
- package/markdown/OBSERVER.md +0 -1
- package/markdown/PLATFORM.md +277 -271
- package/markdown/REDUX.md +54 -0
- package/markdown/SCHEMA.md +0 -1
- package/markdown/SESSION.md +0 -1
- package/markdown/SQLITE.md +0 -1
- package/markdown/STATE.md +0 -1
- package/markdown/STORE.md +0 -1
- package/markdown/SYNC.md +0 -1
- package/markdown/TYPED.md +0 -1
- package/markdown/USEOBSERVER.md +0 -1
- package/modules/redux.cjs +381 -10
- package/modules/redux.cjs.map +1 -1
- package/modules/redux.js +381 -10
- package/modules/redux.js.map +1 -1
- package/package.json +14 -2
- package/types/broadcast.d.ts +61 -0
- package/types/computed.d.ts +96 -0
- package/types/encryption.d.ts +129 -0
- package/types/exports.d.ts +9 -0
- package/types/memorio.d.ts +19 -12
- package/types/security.d.ts +67 -0
- package/types/session.d.ts +23 -5
- package/types/store.d.ts +19 -3
- package/vsix/memorio.vsix +0 -0
- package/markdown/CHANGELOG.md +0 -243
- package/markdown/PROJECT.md +0 -311
- package/markdown/SECURITY.md +0 -330
|
@@ -1,92 +1,91 @@
|
|
|
1
|
-
# ADR-006: Context Isolation Model
|
|
2
|
-
|
|
3
|
-
> **Status:** Accepted
|
|
4
|
-
> **Date:** 2026-09-12
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
- Context IDs are
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
- `tests/vitest/tests/contracts/adr-006-context.test.ts`
|
|
1
|
+
# ADR-006: Context Isolation Model
|
|
2
|
+
|
|
3
|
+
> **Status:** Accepted
|
|
4
|
+
> **Date:** 2026-09-12
|
|
5
|
+
|
|
6
|
+
## Context
|
|
7
|
+
|
|
8
|
+
Memorio must support multiple isolated state trees within a single
|
|
9
|
+
process - for tests, micro-frontends, SSR, workers, and multi-tenant
|
|
10
|
+
environments. The 4.7.3 baseline uses `createContext` /
|
|
11
|
+
`memorio.isolate(name)` to create context-prefixed state, but the
|
|
12
|
+
mechanics and guarantees are undocumented.
|
|
13
|
+
|
|
14
|
+
This ADR defines how context isolation works, what the isolation
|
|
15
|
+
boundary is, and how it interacts with the Mutation Engine (ADR-007).
|
|
16
|
+
|
|
17
|
+
## Assumptions
|
|
18
|
+
|
|
19
|
+
- The core `state`, `store`, `session`, `cache` singletons live on
|
|
20
|
+
`globalThis` and are shared across all import paths (ESM, CJS,
|
|
21
|
+
absolute-path imports).
|
|
22
|
+
- A "context" is a string ID that prefixes internal store keys.
|
|
23
|
+
- `memorio.setContext(id)` sets the active context ID at runtime.
|
|
24
|
+
- Server-side code must create per-request contexts from trusted
|
|
25
|
+
server-side data (never client-controlled input).
|
|
26
|
+
|
|
27
|
+
## Decision
|
|
28
|
+
|
|
29
|
+
### Global singleton vs. isolated context
|
|
30
|
+
|
|
31
|
+
- The global `state` / `store` / `session` / `cache` are **singletons**
|
|
32
|
+
on `globalThis`. Importing `memorio` in any module returns the same
|
|
33
|
+
instances. This is the default and is intended for single-instance
|
|
34
|
+
applications (e.g. one browser tab, one Next.js server instance).
|
|
35
|
+
- `memorio.isolate(name)` creates a new context and returns
|
|
36
|
+
context-scoped proxies. These proxies share the same underlying
|
|
37
|
+
engine but read/write to context-prefixed keys in `store`.
|
|
38
|
+
|
|
39
|
+
### Context ID
|
|
40
|
+
|
|
41
|
+
- Context IDs are strings. They must be unique within a process.
|
|
42
|
+
- Context IDs are **organizational**, not a security boundary. They
|
|
43
|
+
do not prevent unauthorized access to another context's data within
|
|
44
|
+
the same process. Server-side authorization must be enforced at the
|
|
45
|
+
application layer.
|
|
46
|
+
- `internal.currentContext` is a module-level string on the singleton
|
|
47
|
+
`internal` object. Mutations record the active context ID.
|
|
48
|
+
|
|
49
|
+
### Context-scoped state
|
|
50
|
+
|
|
51
|
+
When `internal.currentContext` is set to `ctxId`:
|
|
52
|
+
|
|
53
|
+
1. `state.set(key, value)` writes to `state` but records
|
|
54
|
+
`context: ctxId` in the MutationRecord.
|
|
55
|
+
2. `store.set(key, value)` writes to storage with key
|
|
56
|
+
`ctxId:key` (key-prefix isolation).
|
|
57
|
+
3. `session.set(key, value)` writes to storage with key
|
|
58
|
+
`ctxId:key`.
|
|
59
|
+
4. Reads from `store.get(key)` and `session.get(key)` read from
|
|
60
|
+
`ctxId:key`.
|
|
61
|
+
|
|
62
|
+
### Default context
|
|
63
|
+
|
|
64
|
+
When `internal.currentContext` is `null` (the default), all state and
|
|
65
|
+
store operations use the un-prefixed keys. This is the "default" or
|
|
66
|
+
"global" context.
|
|
67
|
+
|
|
68
|
+
### Multi-tenant caveat
|
|
69
|
+
|
|
70
|
+
`state` (the Proxy) is always global - it is a single reactive tree.
|
|
71
|
+
Context isolation applies to **persistence** (`store`, `session`) and
|
|
72
|
+
**mutation records** (`context` field). To achieve true state-tree
|
|
73
|
+
isolation, consumers should use `memorio.isolate(name)` which creates
|
|
74
|
+
a new context, or instantiate isolated Memorio instances.
|
|
75
|
+
|
|
76
|
+
## Consequences
|
|
77
|
+
|
|
78
|
+
- **Positive:** Single global singleton simplifies the common case
|
|
79
|
+
(one app, one state tree).
|
|
80
|
+
- **Positive:** Context-prefixed persistence enables multi-tenant
|
|
81
|
+
server-side usage without separate state trees.
|
|
82
|
+
- **Positive:** Mutation records carry context, enabling causal-graph
|
|
83
|
+
partitioning (Phase 4).
|
|
84
|
+
- **Negative:** `state` itself is not multi-tenant - consumers needing
|
|
85
|
+
isolated state trees must use `isolate()` or separate processes.
|
|
86
|
+
- **Negative:** Context isolation is organizational, not a security
|
|
87
|
+
boundary - documented clearly in AGENTS.md.
|
|
88
|
+
|
|
89
|
+
## Compliance tests
|
|
90
|
+
|
|
91
|
+
- `tests/vitest/tests/contracts/adr-006-context.test.ts`
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
> **Status:** Accepted
|
|
4
4
|
> **Date:** 2026-09-12
|
|
5
|
-
> **Deciders:** Memorio 5.x Core Team
|
|
6
5
|
|
|
7
6
|
## Context
|
|
8
7
|
|
|
@@ -59,12 +58,12 @@ interface MutationRecord {
|
|
|
59
58
|
### Guarantees
|
|
60
59
|
|
|
61
60
|
1. **Every mutation gets a unique ID.** The ID is generated via
|
|
62
|
-
`generateMutationId()` which calls `hlc.tick()`
|
|
61
|
+
`generateMutationId()` which calls `hlc.tick()` - guaranteeing
|
|
63
62
|
causal ordering within a single node. The node suffix ensures
|
|
64
63
|
uniqueness across devices.
|
|
65
64
|
|
|
66
65
|
2. **Before/after are deepRaw'd.** Proxy wrappers are never stored in
|
|
67
|
-
the record
|
|
66
|
+
the record - only plain values. This ensures serializable,
|
|
68
67
|
comparison-safe records.
|
|
69
68
|
|
|
70
69
|
3. **Single write point.** `internal.recordMutation()` is the only
|
|
@@ -73,7 +72,7 @@ interface MutationRecord {
|
|
|
73
72
|
|
|
74
73
|
4. **Redo stack clears on new mutation.** Any mutation (including
|
|
75
74
|
undo/redo inverse writes, since those temporarily disable history)
|
|
76
|
-
must NOT clear the redo stack
|
|
75
|
+
must NOT clear the redo stack - undo/redo use
|
|
77
76
|
`internal.historyEnabled = false` to bypass `recordMutation`.
|
|
78
77
|
|
|
79
78
|
5. **Max history depth.** Both stacks are trimmed to
|
|
@@ -107,8 +106,8 @@ transaction's mutation list.
|
|
|
107
106
|
- **Positive:** Legacy fields maintain full backward compatibility
|
|
108
107
|
with 4.x consumers.
|
|
109
108
|
- **Negative:** Storing both legacy and canonical fields doubles the
|
|
110
|
-
record size
|
|
111
|
-
- **Negative:** No-op mutations are stored
|
|
109
|
+
record size - acceptable for the opt-in history feature.
|
|
110
|
+
- **Negative:** No-op mutations are stored - a future optimization
|
|
112
111
|
could skip them in the set trap, but the Mutation Engine must remain
|
|
113
112
|
the source of truth.
|
|
114
113
|
|
package/adr/008-transactions.md
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
> **Status:** Accepted
|
|
4
4
|
> **Date:** 2026-09-12
|
|
5
|
-
> **Deciders:** Memorio 5.x Core Team
|
|
6
5
|
|
|
7
6
|
## Context
|
|
8
7
|
|
|
@@ -53,7 +52,7 @@ abortTransaction()
|
|
|
53
52
|
|
|
54
53
|
`beginTransaction` called while a transaction is already active
|
|
55
54
|
creates a **new** transaction context (with a new ID). The previous
|
|
56
|
-
transaction remains active in the registry
|
|
55
|
+
transaction remains active in the registry - it is **not** suspended
|
|
57
56
|
or paused. `commitTransaction()` only commits the **most recently
|
|
58
57
|
started** active transaction.
|
|
59
58
|
|
|
@@ -84,20 +83,20 @@ Once committed or aborted, a transaction's `mutations` list is frozen
|
|
|
84
83
|
1. Calls `createMutation(...)` which auto-tags with the active
|
|
85
84
|
transaction ID via `tagForTransaction()`.
|
|
86
85
|
2. Writes to state with `_recording = false` (no double recording).
|
|
87
|
-
3. Calls `recordMutation(mutation)`
|
|
86
|
+
3. Calls `recordMutation(mutation)` - the mutation is recorded in the
|
|
88
87
|
trace log AND tagged in the transaction.
|
|
89
88
|
|
|
90
89
|
## Consequences
|
|
91
90
|
|
|
92
91
|
- **Positive:** Mutations are grouped and attributable to a logical
|
|
93
|
-
operation
|
|
94
|
-
- **Positive:** `abortTransaction` provides atomic rollback
|
|
92
|
+
operation - essential for explain() and impact() in Phase 4.
|
|
93
|
+
- **Positive:** `abortTransaction` provides atomic rollback - all
|
|
95
94
|
mutations are undone.
|
|
96
95
|
- **Positive:** Registry on `globalThis` survives module duplication.
|
|
97
|
-
- **Negative:** Nested transactions are flat (not hierarchical)
|
|
96
|
+
- **Negative:** Nested transactions are flat (not hierarchical) -
|
|
98
97
|
the outer transaction is not aborted if the inner is aborted.
|
|
99
98
|
- **Negative:** Rollback via inverse application requires all
|
|
100
|
-
`before` values to be present in the MutationRecord
|
|
99
|
+
`before` values to be present in the MutationRecord - for
|
|
101
100
|
very large objects this is memory-intensive.
|
|
102
101
|
|
|
103
102
|
## Compliance tests
|
package/adr/009-history-model.md
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
> **Status:** Proposed
|
|
4
4
|
> **Date:** 2026-09-12
|
|
5
|
-
> **Deciders:** Memorio 5.x Core Team
|
|
6
5
|
|
|
7
6
|
## Context
|
|
8
7
|
|
|
@@ -31,7 +30,7 @@ the full Commit → Snapshot → Delta model.
|
|
|
31
30
|
- `redo()` pops from `redoStack`, pushes to `undoStack`, re-applies.
|
|
32
31
|
- `trace()` returns the full `mutations` log (trimmed to
|
|
33
32
|
`maxHistory`).
|
|
34
|
-
- No commit concept exists
|
|
33
|
+
- No commit concept exists - every mutation is an individual entry.
|
|
35
34
|
|
|
36
35
|
### Target state (Memorio 5.0)
|
|
37
36
|
|
|
@@ -48,7 +47,7 @@ Commit (immutable, append-only)
|
|
|
48
47
|
- **Snapshots** are deep clones of state, materialized every
|
|
49
48
|
`snapshotInterval` commits (default: 100) to bound replay cost.
|
|
50
49
|
- **Deltas** are the `Patch[]` that transform a snapshot to the next
|
|
51
|
-
state. Only patches are stored between snapshots
|
|
50
|
+
state. Only patches are stored between snapshots - never full
|
|
52
51
|
state copies.
|
|
53
52
|
- **Undo/Redo** operate at the commit level, not the individual
|
|
54
53
|
mutation level. Undoing a commit applies the inverse of every patch
|
|
@@ -88,16 +87,16 @@ Commit (immutable, append-only)
|
|
|
88
87
|
|
|
89
88
|
## Consequences
|
|
90
89
|
|
|
91
|
-
- **Positive:** Commits group mutations logically
|
|
90
|
+
- **Positive:** Commits group mutations logically - essential for
|
|
92
91
|
explain(), business history, and audit trails.
|
|
93
92
|
- **Positive:** Snapshot/delta model bounds memory and replay cost.
|
|
94
|
-
- **Positive:** Undo and Revert are distinct operations
|
|
93
|
+
- **Positive:** Undo and Revert are distinct operations - no
|
|
95
94
|
conflation.
|
|
96
95
|
- **Negative:** The current flat stack must be replaced in Phase 3,
|
|
97
96
|
which is a breaking change to `undo()`/`redo()` semantics
|
|
98
97
|
(per-mutation → per-commit).
|
|
99
98
|
- **Negative:** Snapshot materialization at intervals is a trade-off
|
|
100
|
-
between memory and CPU
|
|
99
|
+
between memory and CPU - defaults must be benchmark-driven.
|
|
101
100
|
|
|
102
101
|
## Compliance tests
|
|
103
102
|
|
|
@@ -106,5 +105,5 @@ Commit (immutable, append-only)
|
|
|
106
105
|
|
|
107
106
|
## Benchmarks
|
|
108
107
|
|
|
109
|
-
- `experimental/benchmarks/replay.bench.ts`
|
|
108
|
+
- `experimental/benchmarks/replay.bench.ts` - measures replay cost
|
|
110
109
|
with and without interval snapshots.
|
package/adr/README.md
CHANGED
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
# Architecture Decision Records (ADRs)
|
|
2
|
-
|
|
3
|
-
This directory contains Architecture Decision Records (ADRs) for the
|
|
4
|
-
**Memorio 5.x** "Application State Intelligence Runtime" initiative.
|
|
5
|
-
|
|
6
|
-
## Format
|
|
7
|
-
|
|
8
|
-
ADRs follow the [MADR](https://adr.github.io/) (Markdown Architectural
|
|
9
|
-
Decision Records) format. Each decision record answers four questions:
|
|
10
|
-
|
|
11
|
-
1. **Context**
|
|
12
|
-
started thinking about it?
|
|
13
|
-
2. **Decision**
|
|
14
|
-
the issue)?
|
|
15
|
-
3. **Consequences**
|
|
16
|
-
because of this change?
|
|
17
|
-
|
|
18
|
-
## Numbering
|
|
19
|
-
|
|
20
|
-
| ADR | Title | Status |
|
|
21
|
-
|-----|-------|--------|
|
|
22
|
-
| [001](001-state-proxy-model.md) | State Proxy Model | Accepted |
|
|
23
|
-
| [002](002-observer-semantics.md) | Observer Semantics | Proposed |
|
|
24
|
-
| [003](003-deep-mutation-semantics.md) | Deep Mutation Semantics | Proposed |
|
|
25
|
-
| [004](004-array-mutation-semantics.md) | Array Mutation Semantics | Proposed |
|
|
26
|
-
| [005](005-scheduler-contract.md) | Scheduler Contract | Proposed |
|
|
27
|
-
| [006](006-context-isolation.md) | Context Isolation Model | Accepted |
|
|
28
|
-
| [007](007-mutation-records.md) | Mutation Records | Accepted |
|
|
29
|
-
| [008](008-transactions.md) | Transactions | Accepted |
|
|
30
|
-
| [009](009-history-model.md) | History Model (Snapshot/Delta) | Proposed |
|
|
31
|
-
|
|
32
|
-
## Lifecycle
|
|
33
|
-
|
|
34
|
-
New ADRs start as **Proposed**, move to **Accepted** when the decision
|
|
35
|
-
is implemented and tests pass, and become **Superseded** when a later
|
|
36
|
-
ADR supersedes them. A **Deprecated** status marks decisions that are no
|
|
37
|
-
longer relevant but kept for historical context.
|
|
38
|
-
|
|
39
|
-
## Compliance
|
|
40
|
-
|
|
41
|
-
Every ADR that defines a behavioral contract must have a corresponding
|
|
42
|
-
compliance test suite under `tests/vitest/tests/contracts/`. The test
|
|
43
|
-
file name mirrors the ADR number (e.g. `adr-004-arrays.test.ts`).
|
|
44
|
-
|
|
45
|
-
A release must not be published if any **Accepted** ADR has failing
|
|
46
|
-
compliance tests.
|
|
1
|
+
# Architecture Decision Records (ADRs)
|
|
2
|
+
|
|
3
|
+
This directory contains Architecture Decision Records (ADRs) for the
|
|
4
|
+
**Memorio 5.x** "Application State Intelligence Runtime" initiative.
|
|
5
|
+
|
|
6
|
+
## Format
|
|
7
|
+
|
|
8
|
+
ADRs follow the [MADR](https://adr.github.io/) (Markdown Architectural
|
|
9
|
+
Decision Records) format. Each decision record answers four questions:
|
|
10
|
+
|
|
11
|
+
1. **Context** - What is the issue that we were dealing with when we
|
|
12
|
+
started thinking about it?
|
|
13
|
+
2. **Decision** - What is the change that we will make (that resolves
|
|
14
|
+
the issue)?
|
|
15
|
+
3. **Consequences** - What becomes easier or more difficult to do
|
|
16
|
+
because of this change?
|
|
17
|
+
|
|
18
|
+
## Numbering
|
|
19
|
+
|
|
20
|
+
| ADR | Title | Status |
|
|
21
|
+
|-----|-------|--------|
|
|
22
|
+
| [001](001-state-proxy-model.md) | State Proxy Model | Accepted |
|
|
23
|
+
| [002](002-observer-semantics.md) | Observer Semantics | Proposed |
|
|
24
|
+
| [003](003-deep-mutation-semantics.md) | Deep Mutation Semantics | Proposed |
|
|
25
|
+
| [004](004-array-mutation-semantics.md) | Array Mutation Semantics | Proposed |
|
|
26
|
+
| [005](005-scheduler-contract.md) | Scheduler Contract | Proposed |
|
|
27
|
+
| [006](006-context-isolation.md) | Context Isolation Model | Accepted |
|
|
28
|
+
| [007](007-mutation-records.md) | Mutation Records | Accepted |
|
|
29
|
+
| [008](008-transactions.md) | Transactions | Accepted |
|
|
30
|
+
| [009](009-history-model.md) | History Model (Snapshot/Delta) | Proposed |
|
|
31
|
+
|
|
32
|
+
## Lifecycle
|
|
33
|
+
|
|
34
|
+
New ADRs start as **Proposed**, move to **Accepted** when the decision
|
|
35
|
+
is implemented and tests pass, and become **Superseded** when a later
|
|
36
|
+
ADR supersedes them. A **Deprecated** status marks decisions that are no
|
|
37
|
+
longer relevant but kept for historical context.
|
|
38
|
+
|
|
39
|
+
## Compliance
|
|
40
|
+
|
|
41
|
+
Every ADR that defines a behavioral contract must have a corresponding
|
|
42
|
+
compliance test suite under `tests/vitest/tests/contracts/`. The test
|
|
43
|
+
file name mirrors the ADR number (e.g. `adr-004-arrays.test.ts`).
|
|
44
|
+
|
|
45
|
+
A release must not be published if any **Accepted** ADR has failing
|
|
46
|
+
compliance tests.
|
package/adr/template.md
CHANGED
|
@@ -1,49 +1,48 @@
|
|
|
1
|
-
# ADR Template
|
|
2
|
-
|
|
3
|
-
> **Status:** `{Proposed | Accepted | Superseded by [ADR-XXX](adr-XXX.md) | Deprecated}`
|
|
4
|
-
> **Date:** YYYY-MM-DD
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
> What
|
|
10
|
-
>
|
|
11
|
-
>
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
>
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
>
|
|
22
|
-
>
|
|
23
|
-
>
|
|
24
|
-
>
|
|
25
|
-
> -
|
|
26
|
-
> -
|
|
27
|
-
> -
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
>
|
|
33
|
-
>
|
|
34
|
-
>
|
|
35
|
-
>
|
|
36
|
-
>
|
|
37
|
-
>
|
|
38
|
-
>
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
>
|
|
44
|
-
>
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
File: _ADR_TITLE_PLACEHOLDER.md
|
|
1
|
+
# ADR Template - MADR format
|
|
2
|
+
|
|
3
|
+
> **Status:** `{Proposed | Accepted | Superseded by [ADR-XXX](adr-XXX.md) | Deprecated}`
|
|
4
|
+
> **Date:** YYYY-MM-DD
|
|
5
|
+
|
|
6
|
+
## Context
|
|
7
|
+
|
|
8
|
+
> What is the issue that we were dealing with when we started thinking
|
|
9
|
+
> about it? What are the forces at play? Consider the unique constraints
|
|
10
|
+
> of this project - the need for deterministic, explainable state that
|
|
11
|
+
> remembers, understands, replays, and simulates application state.
|
|
12
|
+
|
|
13
|
+
## Assumptions
|
|
14
|
+
|
|
15
|
+
> List any assumptions the decision relies on (e.g. "state mutations are
|
|
16
|
+
> synchronous," "the Proxy target is always a plain object or array").
|
|
17
|
+
|
|
18
|
+
## Decision
|
|
19
|
+
|
|
20
|
+
> What is the change that we will make? Describe the chosen approach in
|
|
21
|
+
> detail. This section must be precise enough to serve as an implementation
|
|
22
|
+
> contract. Include:
|
|
23
|
+
>
|
|
24
|
+
> - The precise semantics (what happens, what does not happen)
|
|
25
|
+
> - Edge cases and error behavior
|
|
26
|
+
> - Performance characteristics
|
|
27
|
+
> - Backward-compatibility implications
|
|
28
|
+
|
|
29
|
+
## Consequences
|
|
30
|
+
|
|
31
|
+
> What becomes easier or more difficult to do because of this change?
|
|
32
|
+
> Consider:
|
|
33
|
+
>
|
|
34
|
+
> - **Positive** - benefits gained (e.g. improved developer experience,
|
|
35
|
+
> better performance, deterministic behavior)
|
|
36
|
+
> - **Negative** - trade-offs and drawbacks (e.g. loss of flexibility,
|
|
37
|
+
> migration complexity, runtime overhead)
|
|
38
|
+
> - **Testability** - how this decision is covered by compliance tests
|
|
39
|
+
|
|
40
|
+
## Compliance tests
|
|
41
|
+
|
|
42
|
+
> Reference the test file(s) that verify this contract. Every Accepted
|
|
43
|
+
> ADR must list at least one compliance test file path relative to the
|
|
44
|
+
> repository root.
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
File: _ADR_TITLE_PLACEHOLDER.md
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawnSync } from 'node:child_process';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import os from 'node:os';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
|
|
8
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
|
|
10
|
+
const args = process.argv.slice(2);
|
|
11
|
+
const command = args[0];
|
|
12
|
+
|
|
13
|
+
if (command === 'install-extension') {
|
|
14
|
+
installExtension();
|
|
15
|
+
} else {
|
|
16
|
+
console.log('Usage: npx memorio install-extension');
|
|
17
|
+
process.exit(command ? 1 : 0);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function installExtension() {
|
|
21
|
+
const vsixPath = path.join(__dirname, '..', 'vsix', 'memorio.vsix');
|
|
22
|
+
|
|
23
|
+
if (!fs.existsSync(vsixPath)) {
|
|
24
|
+
console.error(`VSIX file not found at ${vsixPath}.`);
|
|
25
|
+
console.error('The npm package may be corrupted, or the build did not copy the .vsix into vsix/.');
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const candidates = candidateBinaries();
|
|
30
|
+
const found = candidates.find((bin) => isAvailable(bin));
|
|
31
|
+
|
|
32
|
+
if (!found) {
|
|
33
|
+
console.error('No compatible editor found in PATH (tried: ' + candidates.join(', ') + ').');
|
|
34
|
+
console.error('Manual installation:');
|
|
35
|
+
console.error(' 1. Open your editor (VSCodium/VSCode)');
|
|
36
|
+
console.error(' 2. Command Palette -> "Extensions: Install from VSIX..."');
|
|
37
|
+
console.error(` 3. Select: ${vsixPath}`);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
console.log(`Editor detected: ${found}. Installing memorio extension...`);
|
|
42
|
+
const result = spawnSync(found, ['--install-extension', vsixPath], {
|
|
43
|
+
stdio: 'inherit',
|
|
44
|
+
shell: os.platform() === 'win32',
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
if (result.status !== 0) {
|
|
48
|
+
console.error('Installation failed. Try manually:');
|
|
49
|
+
console.error(` ${found} --install-extension "${vsixPath}"`);
|
|
50
|
+
process.exit(result.status || 1);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
console.log('Memorio extension installed successfully.');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function candidateBinaries() {
|
|
57
|
+
const names = ['codium', 'vscodium', 'code', 'code-insiders'];
|
|
58
|
+
if (os.platform() === 'win32') {
|
|
59
|
+
return names.map((n) => `${n}.cmd`);
|
|
60
|
+
}
|
|
61
|
+
return names;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function isAvailable(bin) {
|
|
65
|
+
const checkCmd = os.platform() === 'win32' ? 'where' : 'which';
|
|
66
|
+
const result = spawnSync(checkCmd, [bin], { stdio: 'ignore', shell: true });
|
|
67
|
+
return result.status === 0;
|
|
68
|
+
}
|