enigma-memory 0.1.10 → 0.1.11
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 +30 -7
- package/apps/cli/bin/enigma.mjs +381 -48
- package/docs/developer-ecosystem.md +19 -11
- package/docs/sdk-api.md +1 -1
- package/package.json +1 -1
- package/packages/mcp-server/src/index.js +1 -1
- package/scripts/build-hosted-api-key-lifecycle.mjs +1 -1
- package/scripts/build-hosted-customer-lifecycle.mjs +1 -1
- package/scripts/build-installer-assets.mjs +1 -1
- package/scripts/run-standard-memory-benchmarks.mjs +1 -1
package/README.md
CHANGED
|
@@ -2,18 +2,41 @@
|
|
|
2
2
|
|
|
3
3
|
Enigma Memory is a local-first AI Memory Passport. It gives you one canonical local memory vault, receipt-backed proof for Enigma-controlled events, and MCP connections into assistants such as Claude Desktop, Cursor, Kimi Code, and generic MCP clients.
|
|
4
4
|
|
|
5
|
-
Start with the
|
|
5
|
+
Start with the public test drive below. You do not need to understand relay, gateway, mesh, browser, desktop, or hosted infrastructure before trying Enigma locally.
|
|
6
6
|
|
|
7
7
|
The package path needs no database, provider credential, cloud credential, npm publishing token, or external account. Hosted cloud and BYOC operation are separate advanced modes that require real deployment credentials, domains, TLS, durable storage, KMS/secrets, monitoring, backups, and operator acceptance.
|
|
8
8
|
|
|
9
9
|
Enigma does not claim that a closed provider deleted internal data, that model weights forgot, or that provider-native memory disappeared. It proves facts about Enigma-controlled vault state, receipts, checkpoints, and declared boundary operations.
|
|
10
10
|
|
|
11
|
+
## Public test drive: prove the local package path first
|
|
12
|
+
|
|
13
|
+
The fastest public test is the published npm package plus the local-only test drive:
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npm install -g enigma-memory
|
|
17
|
+
enigma test-drive --overwrite
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`enigma test-drive --overwrite` needs no database, provider API key, cloud credential, npm publishing token, package registry account, or hosted Enigma account. It runs entirely on the local filesystem, does not call OpenAI, Anthropic, Cloudflare, hosted Enigma, or other external providers, and does not write Claude, Cursor, Kimi, or other third-party client configs.
|
|
21
|
+
|
|
22
|
+
By default the command writes an isolated demo under `.enigma/test-drive`. Use `--dry-run` to print the plan without writing, or `--out-dir <path>` to choose another isolated demo directory. The default bundle and proof artifacts live inside that directory.
|
|
23
|
+
|
|
24
|
+
The test-drive output is a single public-safe JSON summary. It points to the local setup artifacts, search/status output, cross-model demo report, and benchmark pointers, and it prints exact next commands for testers without printing raw private memory plaintext. The proof is bounded to the local demo: Enigma-controlled vault state, receipts, checkpoints, committed roots, exported bundle shape, and declared boundary operations. It is not evidence that hosted SaaS is live, that a closed provider deleted internal data, that model weights forgot, or that provider-native memory disappeared.
|
|
25
|
+
|
|
26
|
+
When you are ready to connect real local clients that are already installed or already configured:
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
enigma setup --connect-installed --overwrite
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`--connect-installed` is the explicit client-config write path. It skips missing client configs instead of creating every default client config.
|
|
33
|
+
|
|
11
34
|
## Install once, use everywhere
|
|
12
35
|
|
|
13
36
|
Prerequisites:
|
|
14
37
|
|
|
15
38
|
- Node.js `>=24`
|
|
16
|
-
- No database, package registry account, provider credential, or cloud credential for the local setup
|
|
39
|
+
- No database, package registry account, provider credential, or cloud credential for the local test-drive or setup paths
|
|
17
40
|
- Git only when you choose the advanced source-checkout path
|
|
18
41
|
|
|
19
42
|
Use Enigma as a one-time AI Memory Passport setup: install the package, create the local Enigma workspace once, then use the same memory/search/context/verify/connect loop from any supported client.
|
|
@@ -23,7 +46,7 @@ npm install -g enigma-memory
|
|
|
23
46
|
enigma setup --overwrite
|
|
24
47
|
```
|
|
25
48
|
|
|
26
|
-
`enigma setup --overwrite` is the safe default. It writes local Enigma artifacts under the workspace `.enigma` path and emits deterministic, public-safe JSON without printing raw memory plaintext. It does not write Claude, Cursor, Kimi, or other third-party app configs.
|
|
49
|
+
`enigma setup --overwrite` is the safe default for creating a regular local workspace after the test drive. It writes local Enigma artifacts under the workspace `.enigma` path and emits deterministic, public-safe JSON without printing raw memory plaintext. It does not write Claude, Cursor, Kimi, or other third-party app configs.
|
|
27
50
|
|
|
28
51
|
To let setup detect installed or already-configured clients and show the connector plan without mutating client configs:
|
|
29
52
|
|
|
@@ -33,7 +56,7 @@ enigma setup --client auto --overwrite
|
|
|
33
56
|
|
|
34
57
|
`--client auto` selects clients found by connector detection and falls back to the default setup client list when none are present. The setup output lists which clients were selected, which were skipped, and why.
|
|
35
58
|
|
|
36
|
-
|
|
59
|
+
Only when you are ready to explicitly write connector entries for installed/config-present clients:
|
|
37
60
|
|
|
38
61
|
```sh
|
|
39
62
|
enigma setup --connect-installed --overwrite
|
|
@@ -53,10 +76,10 @@ enigma connect claude-desktop --dry-run
|
|
|
53
76
|
|
|
54
77
|
The local Enigma vault remains canonical. Provider-native memory is non-canonical and should be treated as a convenience cache only. Enigma receipts prove Enigma-controlled vault state, receipts, checkpoints, and declared boundary operations; they do not prove provider deletion, provider model forgetting, provider-native memory removal, hosted availability, ROI/savings, or compliance certification.
|
|
55
78
|
|
|
56
|
-
One-off
|
|
79
|
+
One-off public test drive without a global install:
|
|
57
80
|
|
|
58
81
|
```sh
|
|
59
|
-
npx --yes --package enigma-memory enigma
|
|
82
|
+
npx --yes --package enigma-memory enigma test-drive --overwrite
|
|
60
83
|
```
|
|
61
84
|
|
|
62
85
|
## Advanced/source-only path
|
|
@@ -164,7 +187,7 @@ Supported connector profiles are:
|
|
|
164
187
|
- `opencode`
|
|
165
188
|
- `generic-mcp`
|
|
166
189
|
|
|
167
|
-
After `enigma setup --overwrite
|
|
190
|
+
After `enigma test-drive --overwrite` proves the local package path and `enigma setup --overwrite` creates a regular local workspace, preview a client connection before writing anything:
|
|
168
191
|
|
|
169
192
|
```sh
|
|
170
193
|
enigma connect claude-desktop --dry-run
|
package/apps/cli/bin/enigma.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import { createHash } from 'node:crypto';
|
|
|
3
3
|
import { createServer as createHttpServer } from 'node:http';
|
|
4
4
|
import { realpathSync } from 'node:fs';
|
|
5
5
|
import { access, mkdir, readFile, readdir, writeFile } from 'node:fs/promises';
|
|
6
|
-
import { dirname, resolve } from 'node:path';
|
|
6
|
+
import { dirname, isAbsolute, join, resolve } from 'node:path';
|
|
7
7
|
import { pathToFileURL } from 'node:url';
|
|
8
8
|
import { createVault, remember, recall, updateMemory, deleteMemory, exportBundle } from '../../../packages/vault/src/index.js';
|
|
9
9
|
import { createPassport, compileContextPack } from '../../../packages/passport/src/index.js';
|
|
@@ -32,6 +32,9 @@ import {
|
|
|
32
32
|
} from '../../../packages/settlement/src/index.js';
|
|
33
33
|
|
|
34
34
|
const DEFAULT_BUNDLE = '.enigma/bundle.json';
|
|
35
|
+
const DEFAULT_TEST_DRIVE_DIR = '.enigma/test-drive';
|
|
36
|
+
const DEFAULT_TEST_DRIVE_BUNDLE_NAME = 'bundle.json';
|
|
37
|
+
const DEFAULT_TEST_DRIVE_CROSS_MODEL_REPORT_NAME = 'cross-model-report.json';
|
|
35
38
|
export const DEFAULT_RELAY_PORT = 8787;
|
|
36
39
|
export const DEFAULT_GATEWAY_PORT = 8797;
|
|
37
40
|
const DEFAULT_QUICKSTART_MEMORY = 'Enigma quickstart demo memory: local proof bundles can be created and verified without provider or cloud credentials.';
|
|
@@ -279,10 +282,10 @@ function quickstartOutputs(bundleInput, outDirInput) {
|
|
|
279
282
|
};
|
|
280
283
|
}
|
|
281
284
|
|
|
282
|
-
async function buildQuickstartArtifacts(flags, { bundleInput = DEFAULT_BUNDLE, outDirInput = dirname(bundleInput), overwrite = false, write = true } = {}) {
|
|
285
|
+
async function buildQuickstartArtifacts(flags, { bundleInput = DEFAULT_BUNDLE, outDirInput = dirname(bundleInput), overwrite = false, write = true, checkExisting = true } = {}) {
|
|
283
286
|
const paths = quickstartOutputs(bundleInput, outDirInput);
|
|
284
287
|
ensureDistinctOutputPaths(paths.outputs.map((output) => output.path));
|
|
285
|
-
await assertCanWriteQuickstartOutputs(paths.outputs, overwrite);
|
|
288
|
+
if (checkExisting) await assertCanWriteQuickstartOutputs(paths.outputs, overwrite);
|
|
286
289
|
|
|
287
290
|
const vault = createVault({
|
|
288
291
|
subjectId: String(getFlag(flags, ['subject', 'subject-id'], 'local-user')),
|
|
@@ -1133,6 +1136,39 @@ export async function quickstartCommand(flags, io) {
|
|
|
1133
1136
|
return artifacts.verifyReport.ok === true ? 0 : 1;
|
|
1134
1137
|
}
|
|
1135
1138
|
|
|
1139
|
+
function buildCrossModelProfileSummaries({ vault, passport, demoMemoryAddr, limit }) {
|
|
1140
|
+
const profiles = [];
|
|
1141
|
+
for (const profile of CROSS_MODEL_PROFILES) {
|
|
1142
|
+
const pack = compileContextPack({
|
|
1143
|
+
vault,
|
|
1144
|
+
passport,
|
|
1145
|
+
provider: profile.provider,
|
|
1146
|
+
model: profile.model,
|
|
1147
|
+
query: 'memory follows me across models',
|
|
1148
|
+
purpose: `cross_model_demo:${profile.id}`,
|
|
1149
|
+
memory_addresses: [demoMemoryAddr],
|
|
1150
|
+
limit,
|
|
1151
|
+
});
|
|
1152
|
+
const contextPack = publicContextPackSummary(pack);
|
|
1153
|
+
profiles.push({
|
|
1154
|
+
profile: profile.id,
|
|
1155
|
+
label: profile.label,
|
|
1156
|
+
provider: profile.provider,
|
|
1157
|
+
model: profile.model,
|
|
1158
|
+
context_pack_ref: contextPack.context_pack_ref,
|
|
1159
|
+
context_pack_id: contextPack.context_pack_id,
|
|
1160
|
+
context_pack_digest: contextPack.context_pack_digest,
|
|
1161
|
+
context_pack: contextPack,
|
|
1162
|
+
receipt_count: contextPack.receipt_count,
|
|
1163
|
+
memory_count: contextPack.memory_count,
|
|
1164
|
+
provider_native_memory_canonical: false,
|
|
1165
|
+
receipts: contextPack.receipts,
|
|
1166
|
+
claim_boundaries: { ...CROSS_MODEL_CLAIM_BOUNDARIES },
|
|
1167
|
+
});
|
|
1168
|
+
}
|
|
1169
|
+
return profiles;
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1136
1172
|
export async function crossModelDemoCommand(flags, io) {
|
|
1137
1173
|
const bundleFlag = getFlag(flags, ['bundle', 'file']);
|
|
1138
1174
|
if (bundleFlag === true || bundleFlag === '') throw new Error('Missing required --bundle.');
|
|
@@ -1189,35 +1225,7 @@ export async function crossModelDemoCommand(flags, io) {
|
|
|
1189
1225
|
const limit = integerFlag(flags, ['limit'], 'limit', 1);
|
|
1190
1226
|
if (limit < 1) throw new Error('--limit must be at least 1.');
|
|
1191
1227
|
const receiptCountBeforeProfiles = Array.isArray(vault.receipts) ? vault.receipts.length : 0;
|
|
1192
|
-
const profiles =
|
|
1193
|
-
for (const profile of CROSS_MODEL_PROFILES) {
|
|
1194
|
-
const pack = compileContextPack({
|
|
1195
|
-
vault,
|
|
1196
|
-
passport,
|
|
1197
|
-
provider: profile.provider,
|
|
1198
|
-
model: profile.model,
|
|
1199
|
-
query: 'memory follows me across models',
|
|
1200
|
-
purpose: `cross_model_demo:${profile.id}`,
|
|
1201
|
-
memory_addresses: [demoMemoryAddr],
|
|
1202
|
-
limit,
|
|
1203
|
-
});
|
|
1204
|
-
const contextPack = publicContextPackSummary(pack);
|
|
1205
|
-
profiles.push({
|
|
1206
|
-
profile: profile.id,
|
|
1207
|
-
label: profile.label,
|
|
1208
|
-
provider: profile.provider,
|
|
1209
|
-
model: profile.model,
|
|
1210
|
-
context_pack_ref: contextPack.context_pack_ref,
|
|
1211
|
-
context_pack_id: contextPack.context_pack_id,
|
|
1212
|
-
context_pack_digest: contextPack.context_pack_digest,
|
|
1213
|
-
context_pack: contextPack,
|
|
1214
|
-
receipt_count: contextPack.receipt_count,
|
|
1215
|
-
memory_count: contextPack.memory_count,
|
|
1216
|
-
provider_native_memory_canonical: false,
|
|
1217
|
-
receipts: contextPack.receipts,
|
|
1218
|
-
claim_boundaries: { ...CROSS_MODEL_CLAIM_BOUNDARIES },
|
|
1219
|
-
});
|
|
1220
|
-
}
|
|
1228
|
+
const profiles = buildCrossModelProfileSummaries({ vault, passport, demoMemoryAddr, limit });
|
|
1221
1229
|
|
|
1222
1230
|
const bundle = await persistState(bundlePath, vault);
|
|
1223
1231
|
const report = {
|
|
@@ -1327,20 +1335,14 @@ async function contextCommand(flags, io) {
|
|
|
1327
1335
|
}
|
|
1328
1336
|
|
|
1329
1337
|
|
|
1330
|
-
|
|
1331
|
-
const bundlePath = resolve(String(getFlag(flags, ['bundle', 'file'], DEFAULT_BUNDLE)));
|
|
1332
|
-
const query = String(requireFlag(flags, ['query', 'q'], 'query'));
|
|
1333
|
-
const limit = integerFlag(flags, ['limit'], 'limit', 8);
|
|
1334
|
-
if (limit < 0) throw new Error('--limit must be non-negative.');
|
|
1335
|
-
const includeContent = getFlag(flags, ['include-content', 'includeContent']) === true || getFlag(flags, ['include-content', 'includeContent']) === 'true';
|
|
1336
|
-
const { vault } = await loadState(bundlePath);
|
|
1338
|
+
function memorySearchReport({ bundlePath, vault, query, limit, includeContent = false, now = '2026-01-01T00:00:00.000Z' }) {
|
|
1337
1339
|
const roots = vault.__computeRoots();
|
|
1338
1340
|
const queryTokens = searchTokensFrom(query);
|
|
1339
1341
|
const { candidates, byAddress } = searchCandidates(vault, queryTokens);
|
|
1340
1342
|
const plan = createMemoryOptimizationPlan({
|
|
1341
1343
|
candidates,
|
|
1342
1344
|
prompt: query,
|
|
1343
|
-
now
|
|
1345
|
+
now,
|
|
1344
1346
|
});
|
|
1345
1347
|
const planIndex = new Map(plan.items.map((item, index) => [item.address, index]));
|
|
1346
1348
|
const selectedItems = plan.items
|
|
@@ -1381,7 +1383,7 @@ async function searchCommand(flags, io) {
|
|
|
1381
1383
|
...(includeContent ? { content: hit.content } : {}),
|
|
1382
1384
|
};
|
|
1383
1385
|
});
|
|
1384
|
-
|
|
1386
|
+
return {
|
|
1385
1387
|
ok: true,
|
|
1386
1388
|
schema: 'enigma.memory_search.v1',
|
|
1387
1389
|
bundle: bundlePath,
|
|
@@ -1395,18 +1397,33 @@ async function searchCommand(flags, io) {
|
|
|
1395
1397
|
claim_boundary: includeContent
|
|
1396
1398
|
? 'Search ran against the selected local bundle and includes plaintext only because --include-content was explicit; this does not prove provider deletion, provider-native memory state, or model forgetting.'
|
|
1397
1399
|
: 'Search ran against the selected local bundle and redacts plaintext by default; refs, scores, tags, roots, and receipt refs are not provider deletion proof or model forgetting proof.',
|
|
1398
|
-
}
|
|
1399
|
-
return 0;
|
|
1400
|
+
};
|
|
1400
1401
|
}
|
|
1401
1402
|
|
|
1402
|
-
async function
|
|
1403
|
+
async function searchCommand(flags, io) {
|
|
1403
1404
|
const bundlePath = resolve(String(getFlag(flags, ['bundle', 'file'], DEFAULT_BUNDLE)));
|
|
1404
|
-
const
|
|
1405
|
+
const query = String(requireFlag(flags, ['query', 'q'], 'query'));
|
|
1406
|
+
const limit = integerFlag(flags, ['limit'], 'limit', 8);
|
|
1407
|
+
if (limit < 0) throw new Error('--limit must be non-negative.');
|
|
1408
|
+
const includeContent = getFlag(flags, ['include-content', 'includeContent']) === true || getFlag(flags, ['include-content', 'includeContent']) === 'true';
|
|
1409
|
+
const { vault } = await loadState(bundlePath);
|
|
1410
|
+
print(memorySearchReport({
|
|
1411
|
+
bundlePath,
|
|
1412
|
+
vault,
|
|
1413
|
+
query,
|
|
1414
|
+
limit,
|
|
1415
|
+
includeContent,
|
|
1416
|
+
now: getFlag(flags, ['now'], '2026-01-01T00:00:00.000Z'),
|
|
1417
|
+
}), io);
|
|
1418
|
+
return 0;
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1421
|
+
function passportStatusReport({ bundlePath, stored = {}, vault, passport }) {
|
|
1405
1422
|
const roots = vault.__computeRoots();
|
|
1406
1423
|
const activeCount = activeMemoryCount(vault);
|
|
1407
1424
|
const tombstoneCount = vault.tombstones instanceof Map ? vault.tombstones.size : 0;
|
|
1408
1425
|
const receiptCount = Array.isArray(vault.receipts) ? vault.receipts.length : 0;
|
|
1409
|
-
|
|
1426
|
+
return {
|
|
1410
1427
|
ok: true,
|
|
1411
1428
|
schema: 'enigma.passport_status.v1',
|
|
1412
1429
|
bundle: bundlePath,
|
|
@@ -1434,10 +1451,317 @@ async function statusCommand(flags, io) {
|
|
|
1434
1451
|
`enigma connect <client> --bundle "${bundlePath}"`,
|
|
1435
1452
|
],
|
|
1436
1453
|
claim_boundary: 'Status reports local bundle counters, owner display fields, connector readiness hints, and commitment roots only; it does not expose raw memory, certify compliance, prove provider deletion, or prove model forgetting.',
|
|
1437
|
-
}
|
|
1454
|
+
};
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
async function statusCommand(flags, io) {
|
|
1458
|
+
const bundlePath = resolve(String(getFlag(flags, ['bundle', 'file'], DEFAULT_BUNDLE)));
|
|
1459
|
+
const { stored, vault, passport } = await loadState(bundlePath);
|
|
1460
|
+
print(passportStatusReport({ bundlePath, stored, vault, passport }), io);
|
|
1438
1461
|
return 0;
|
|
1439
1462
|
}
|
|
1440
1463
|
|
|
1464
|
+
function testDrivePathDisplay(outDirInput, name) {
|
|
1465
|
+
return isAbsolute(outDirInput) ? join(outDirInput, name) : quickstartPathDisplay(outDirInput, name);
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
function testDriveBundleDisplay(outDirInput) {
|
|
1469
|
+
return testDrivePathDisplay(outDirInput, DEFAULT_TEST_DRIVE_BUNDLE_NAME);
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
function testDriveOutputs(outDirInput, bundleInput = testDriveBundleDisplay(outDirInput)) {
|
|
1473
|
+
const quickstart = quickstartOutputs(bundleInput, outDirInput);
|
|
1474
|
+
const contextPackDisplay = testDrivePathDisplay(outDirInput, QUICKSTART_ARTIFACT_NAMES.contextPack);
|
|
1475
|
+
const exportDisplay = testDrivePathDisplay(outDirInput, QUICKSTART_ARTIFACT_NAMES.export);
|
|
1476
|
+
const verifyReportDisplay = testDrivePathDisplay(outDirInput, QUICKSTART_ARTIFACT_NAMES.verifyReport);
|
|
1477
|
+
const crossModelReportDisplay = testDrivePathDisplay(outDirInput, DEFAULT_TEST_DRIVE_CROSS_MODEL_REPORT_NAME);
|
|
1478
|
+
const crossModelReportPath = resolve(quickstart.outDirPath, DEFAULT_TEST_DRIVE_CROSS_MODEL_REPORT_NAME);
|
|
1479
|
+
const artifacts = [
|
|
1480
|
+
{ role: 'bundle', path: quickstart.bundlePath, display: bundleInput, schema: 'enigma.bundle.v1' },
|
|
1481
|
+
{ role: 'context_pack', path: quickstart.contextPackPath, display: contextPackDisplay, schema: 'enigma.context_pack.v1' },
|
|
1482
|
+
{ role: 'export', path: quickstart.exportPath, display: exportDisplay, schema: 'enigma.bundle.v1' },
|
|
1483
|
+
{ role: 'verify_report', path: quickstart.verifyReportPath, display: verifyReportDisplay, schema: 'enigma.verify_report.v1' },
|
|
1484
|
+
{ role: 'cross_model_report', path: crossModelReportPath, display: crossModelReportDisplay, schema: 'enigma.cross_model_demo.v1' },
|
|
1485
|
+
];
|
|
1486
|
+
return {
|
|
1487
|
+
...quickstart,
|
|
1488
|
+
contextPackDisplay,
|
|
1489
|
+
exportDisplay,
|
|
1490
|
+
verifyReportDisplay,
|
|
1491
|
+
crossModelReportPath,
|
|
1492
|
+
crossModelReportDisplay,
|
|
1493
|
+
artifacts,
|
|
1494
|
+
outputs: artifacts.map((artifact) => ({ path: artifact.path, display: artifact.display })),
|
|
1495
|
+
};
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
function testDriveFileSummaries(artifacts, written) {
|
|
1499
|
+
return artifacts.map((artifact) => ({
|
|
1500
|
+
role: artifact.role,
|
|
1501
|
+
path: artifact.display,
|
|
1502
|
+
schema: artifact.schema,
|
|
1503
|
+
written: Boolean(written),
|
|
1504
|
+
}));
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
function firstActiveMemoryAddress(vault) {
|
|
1508
|
+
if (!(vault.activeAddresses instanceof Set)) throw new Error('Test drive vault did not expose an active memory set.');
|
|
1509
|
+
const first = vault.activeAddresses.values().next();
|
|
1510
|
+
if (first.done) throw new Error('Test drive vault did not create a demo memory.');
|
|
1511
|
+
return first.value;
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1514
|
+
function testDriveNextCommands(bundleDisplay, crossModelReportDisplay) {
|
|
1515
|
+
const quotedBundle = commandPath(bundleDisplay);
|
|
1516
|
+
const quotedReport = commandPath(crossModelReportDisplay);
|
|
1517
|
+
return [
|
|
1518
|
+
`enigma status --bundle ${quotedBundle}`,
|
|
1519
|
+
`enigma search --bundle ${quotedBundle} --query "local proof bundle"`,
|
|
1520
|
+
`enigma demo cross-model --bundle ${quotedBundle} --out ${quotedReport}`,
|
|
1521
|
+
'node scripts/run-memory-benchmarks.mjs',
|
|
1522
|
+
];
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
function testDriveFlowCommands({ bundleDisplay, outDirInput, crossModelReportDisplay, overwrite }) {
|
|
1526
|
+
const overwriteSuffix = overwrite ? ' --overwrite' : '';
|
|
1527
|
+
const quotedBundle = commandPath(bundleDisplay);
|
|
1528
|
+
const quotedOutDir = commandPath(outDirInput);
|
|
1529
|
+
const quotedReport = commandPath(crossModelReportDisplay);
|
|
1530
|
+
return [
|
|
1531
|
+
`enigma quickstart --bundle ${quotedBundle} --out-dir ${quotedOutDir}${overwriteSuffix}`,
|
|
1532
|
+
`enigma status --bundle ${quotedBundle}`,
|
|
1533
|
+
`enigma search --bundle ${quotedBundle} --query "local proof bundle"`,
|
|
1534
|
+
`enigma demo cross-model --bundle ${quotedBundle} --out ${quotedReport}`,
|
|
1535
|
+
];
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
function testDriveBenchmarkPointers() {
|
|
1539
|
+
return [
|
|
1540
|
+
{
|
|
1541
|
+
command: 'node scripts/run-memory-benchmarks.mjs',
|
|
1542
|
+
public_safe: true,
|
|
1543
|
+
planned_only: true,
|
|
1544
|
+
requires_repo_checkout: true,
|
|
1545
|
+
external_provider_calls: false,
|
|
1546
|
+
raw_memory_included: false,
|
|
1547
|
+
claim_boundary: 'Runs deterministic local fixture operations only; it is not a provider comparison, hosted service proof, benchmark leadership claim, ROI claim, provider deletion proof, or model forgetting proof.',
|
|
1548
|
+
},
|
|
1549
|
+
{
|
|
1550
|
+
command: 'node scripts/download-standard-benchmarks.mjs --dry-run',
|
|
1551
|
+
public_safe: true,
|
|
1552
|
+
planned_only: true,
|
|
1553
|
+
requires_repo_checkout: true,
|
|
1554
|
+
external_provider_calls: false,
|
|
1555
|
+
raw_memory_included: false,
|
|
1556
|
+
claim_boundary: 'Plans official dataset downloads without fetching by default; raw benchmark records are not included in the public plan.',
|
|
1557
|
+
},
|
|
1558
|
+
{
|
|
1559
|
+
command: 'node scripts/run-standard-memory-benchmarks.mjs --locomo <path> --longmemeval <path>',
|
|
1560
|
+
public_safe: true,
|
|
1561
|
+
planned_only: true,
|
|
1562
|
+
requires_repo_checkout: true,
|
|
1563
|
+
external_provider_calls: false,
|
|
1564
|
+
raw_memory_included: false,
|
|
1565
|
+
claim_boundary: 'Runs local deterministic retrieval proxies against operator-supplied dataset files; it emits no provider API calls, competitor scores, benchmark leadership claim, or model-forgetting claim.',
|
|
1566
|
+
},
|
|
1567
|
+
];
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1570
|
+
function testDriveClaimBoundaries() {
|
|
1571
|
+
return {
|
|
1572
|
+
local_only: true,
|
|
1573
|
+
credentials_required: false,
|
|
1574
|
+
external_provider_calls: false,
|
|
1575
|
+
client_config_writes_performed: false,
|
|
1576
|
+
plaintext_memory_echoed: false,
|
|
1577
|
+
hosted_saas_live_claim: false,
|
|
1578
|
+
provider_native_memory_canonical: false,
|
|
1579
|
+
provider_deletion_proof: false,
|
|
1580
|
+
model_forgetting_proof: false,
|
|
1581
|
+
benchmark_leadership_claim: false,
|
|
1582
|
+
compliance_certification: false,
|
|
1583
|
+
};
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
function publicTestDriveStatusSummary(summary, bundleDisplay) {
|
|
1587
|
+
return {
|
|
1588
|
+
...summary,
|
|
1589
|
+
bundle: bundleDisplay,
|
|
1590
|
+
connector_readiness: {
|
|
1591
|
+
...summary.connector_readiness,
|
|
1592
|
+
bundle: bundleDisplay,
|
|
1593
|
+
},
|
|
1594
|
+
next_recommended_commands: [
|
|
1595
|
+
`enigma remember --bundle ${commandPath(bundleDisplay)} --text-file <path>`,
|
|
1596
|
+
`enigma search --bundle ${commandPath(bundleDisplay)} --query <text>`,
|
|
1597
|
+
`enigma context --bundle ${commandPath(bundleDisplay)} --query <text>`,
|
|
1598
|
+
`enigma verify --bundle ${commandPath(bundleDisplay)}`,
|
|
1599
|
+
`enigma connect <client> --bundle ${commandPath(bundleDisplay)}`,
|
|
1600
|
+
],
|
|
1601
|
+
};
|
|
1602
|
+
}
|
|
1603
|
+
|
|
1604
|
+
function publicTestDriveSearchSummary(summary, bundleDisplay) {
|
|
1605
|
+
return {
|
|
1606
|
+
...summary,
|
|
1607
|
+
bundle: bundleDisplay,
|
|
1608
|
+
};
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1611
|
+
function staticSetupSelection(requestedSelection) {
|
|
1612
|
+
return {
|
|
1613
|
+
...requestedSelection,
|
|
1614
|
+
fallback_used: false,
|
|
1615
|
+
selected: requestedSelection.clients.map((clientId) => {
|
|
1616
|
+
const profile = getClientProfile(clientId);
|
|
1617
|
+
return publicSetupClientSelectionEntry({ client_id: clientId, display_name: profile.display_name }, requestedSelection.mode === 'default' ? 'default_setup_client' : 'explicit_client');
|
|
1618
|
+
}),
|
|
1619
|
+
skipped: [],
|
|
1620
|
+
connectable_client_ids: null,
|
|
1621
|
+
};
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1624
|
+
export async function testDriveCommand(flags, io) {
|
|
1625
|
+
const outDirInput = pathFlag(flags, ['out-dir', 'outDir'], DEFAULT_TEST_DRIVE_DIR);
|
|
1626
|
+
const bundleInput = pathFlag(flags, ['bundle', 'file'], testDriveBundleDisplay(outDirInput));
|
|
1627
|
+
const overwrite = booleanFlag(flags, ['overwrite'], false);
|
|
1628
|
+
const dryRun = booleanFlag(flags, ['dry-run', 'dryRun'], false);
|
|
1629
|
+
const outputs = testDriveOutputs(outDirInput, bundleInput);
|
|
1630
|
+
ensureDistinctOutputPaths(outputs.outputs.map((output) => output.path));
|
|
1631
|
+
if (!dryRun) await assertCanWriteQuickstartOutputs(outputs.outputs, overwrite);
|
|
1632
|
+
|
|
1633
|
+
const artifacts = await buildQuickstartArtifacts(flags, {
|
|
1634
|
+
bundleInput,
|
|
1635
|
+
outDirInput,
|
|
1636
|
+
overwrite,
|
|
1637
|
+
write: false,
|
|
1638
|
+
checkExisting: false,
|
|
1639
|
+
});
|
|
1640
|
+
const requestedSelection = setupClientIds(flags);
|
|
1641
|
+
const selection = requestedSelection.auto
|
|
1642
|
+
? await setupAutoClientSelection(flags, artifacts, DEFAULT_SETUP_CLIENTS, 'auto')
|
|
1643
|
+
: staticSetupSelection(requestedSelection);
|
|
1644
|
+
const demoMemoryAddr = firstActiveMemoryAddress(artifacts.vault);
|
|
1645
|
+
const crossModelLimit = integerFlag(flags, ['limit'], 'limit', 1);
|
|
1646
|
+
if (crossModelLimit < 1) throw new Error('--limit must be at least 1.');
|
|
1647
|
+
const receiptCountBeforeProfiles = Array.isArray(artifacts.vault.receipts) ? artifacts.vault.receipts.length : 0;
|
|
1648
|
+
const profiles = buildCrossModelProfileSummaries({
|
|
1649
|
+
vault: artifacts.vault,
|
|
1650
|
+
passport: artifacts.passport,
|
|
1651
|
+
demoMemoryAddr,
|
|
1652
|
+
limit: crossModelLimit,
|
|
1653
|
+
});
|
|
1654
|
+
const finalExport = exportBundle({ vault: artifacts.vault, includePlaintext: false });
|
|
1655
|
+
const finalBundle = finalExport.bundle ?? finalExport;
|
|
1656
|
+
const finalVerifyReport = verifyBundle(finalBundle);
|
|
1657
|
+
const crossModelReport = {
|
|
1658
|
+
ok: true,
|
|
1659
|
+
schema: 'enigma.cross_model_demo.v1',
|
|
1660
|
+
command: 'enigma demo cross-model',
|
|
1661
|
+
story: 'One local Enigma memory is packaged as public-safe context pack references and receipts for ChatGPT, Claude, Kimi, Cursor, and a local LLM. No provider is called.',
|
|
1662
|
+
bundle_ref: bundleInput,
|
|
1663
|
+
bundle_supplied: true,
|
|
1664
|
+
bundle_created: true,
|
|
1665
|
+
demo_only_vault: true,
|
|
1666
|
+
memory_source: 'test_drive_demo',
|
|
1667
|
+
demo_memory_addr: demoMemoryAddr,
|
|
1668
|
+
profile_count: profiles.length,
|
|
1669
|
+
profiles,
|
|
1670
|
+
memory_count: activeMemoryCount(artifacts.vault),
|
|
1671
|
+
receipt_count: Array.isArray(finalBundle.receipts) ? finalBundle.receipts.length : 0,
|
|
1672
|
+
generated_receipt_count: (Array.isArray(finalBundle.receipts) ? finalBundle.receipts.length : 0) - receiptCountBeforeProfiles,
|
|
1673
|
+
provider_credentials_required: false,
|
|
1674
|
+
provider_native_memory_canonical: false,
|
|
1675
|
+
out_written: !dryRun,
|
|
1676
|
+
claim_boundaries: { ...CROSS_MODEL_CLAIM_BOUNDARIES },
|
|
1677
|
+
};
|
|
1678
|
+
const rawStatusSummary = passportStatusReport({
|
|
1679
|
+
bundlePath: outputs.bundlePath,
|
|
1680
|
+
vault: artifacts.vault,
|
|
1681
|
+
passport: artifacts.passport,
|
|
1682
|
+
stored: {
|
|
1683
|
+
owner: {
|
|
1684
|
+
subject_id: artifacts.vault.subject_id,
|
|
1685
|
+
display_name: artifacts.vault.display_name,
|
|
1686
|
+
},
|
|
1687
|
+
},
|
|
1688
|
+
});
|
|
1689
|
+
const statusSummary = publicTestDriveStatusSummary(rawStatusSummary, bundleInput);
|
|
1690
|
+
const rawSearchSummary = memorySearchReport({
|
|
1691
|
+
bundlePath: outputs.bundlePath,
|
|
1692
|
+
vault: artifacts.vault,
|
|
1693
|
+
query: 'local proof bundle',
|
|
1694
|
+
limit: 3,
|
|
1695
|
+
includeContent: false,
|
|
1696
|
+
now: getFlag(flags, ['now'], '2026-01-01T00:00:00.000Z'),
|
|
1697
|
+
});
|
|
1698
|
+
const searchSummary = publicTestDriveSearchSummary(rawSearchSummary, bundleInput);
|
|
1699
|
+
|
|
1700
|
+
if (!dryRun) {
|
|
1701
|
+
await writeJson(outputs.bundlePath, finalBundle);
|
|
1702
|
+
await writeJson(outputs.contextPackPath, publicContextPackSummary(artifacts.contextPack));
|
|
1703
|
+
await writeJson(outputs.exportPath, finalBundle);
|
|
1704
|
+
await writeJson(outputs.verifyReportPath, finalVerifyReport);
|
|
1705
|
+
await writeJson(outputs.crossModelReportPath, crossModelReport);
|
|
1706
|
+
}
|
|
1707
|
+
|
|
1708
|
+
const flowCommands = testDriveFlowCommands({
|
|
1709
|
+
bundleDisplay: bundleInput,
|
|
1710
|
+
outDirInput,
|
|
1711
|
+
crossModelReportDisplay: outputs.crossModelReportDisplay,
|
|
1712
|
+
overwrite,
|
|
1713
|
+
});
|
|
1714
|
+
const nextCommands = testDriveNextCommands(bundleInput, outputs.crossModelReportDisplay);
|
|
1715
|
+
const files = testDriveFileSummaries(outputs.artifacts, !dryRun);
|
|
1716
|
+
const packageJson = await readPackageJson();
|
|
1717
|
+
const ok = finalVerifyReport.ok === true && crossModelReport.ok === true && statusSummary.ok === true && searchSummary.ok === true;
|
|
1718
|
+
print({
|
|
1719
|
+
ok,
|
|
1720
|
+
schema: 'enigma.test_drive.v1',
|
|
1721
|
+
command: 'enigma test-drive',
|
|
1722
|
+
dry_run: dryRun,
|
|
1723
|
+
out_dir: outDirInput,
|
|
1724
|
+
bundle: bundleInput,
|
|
1725
|
+
install_command: `npm install -g ${packageJson.name ?? 'enigma-memory'}`,
|
|
1726
|
+
release_target: '0.1.11',
|
|
1727
|
+
artifacts_written: !dryRun,
|
|
1728
|
+
client_configs_written: false,
|
|
1729
|
+
client_config_write_required: false,
|
|
1730
|
+
memory_plaintext_echoed: false,
|
|
1731
|
+
provider_credentials_required: false,
|
|
1732
|
+
hosted_saas_live: false,
|
|
1733
|
+
files,
|
|
1734
|
+
files_written: dryRun ? [] : files.map((file) => file.path),
|
|
1735
|
+
files_planned: files.map((file) => file.path),
|
|
1736
|
+
commands_run: dryRun ? [] : flowCommands,
|
|
1737
|
+
commands_planned: dryRun ? flowCommands : [],
|
|
1738
|
+
next_commands: nextCommands,
|
|
1739
|
+
benchmark_pointers: testDriveBenchmarkPointers(),
|
|
1740
|
+
setup_summary: {
|
|
1741
|
+
schema: 'enigma.setup.v1',
|
|
1742
|
+
artifacts_written: !dryRun,
|
|
1743
|
+
bundle: bundleInput,
|
|
1744
|
+
context_pack: outputs.contextPackDisplay,
|
|
1745
|
+
export: outputs.exportDisplay,
|
|
1746
|
+
verify_report: outputs.verifyReportDisplay,
|
|
1747
|
+
selected_clients: selection.clients,
|
|
1748
|
+
client_selection: publicSetupClientSelection(selection),
|
|
1749
|
+
client_configs_written: false,
|
|
1750
|
+
provider_credentials_required: false,
|
|
1751
|
+
memory_plaintext_echoed: false,
|
|
1752
|
+
memory_count: Array.isArray(finalBundle.memory_objects) ? finalBundle.memory_objects.length : 0,
|
|
1753
|
+
receipt_count: Array.isArray(finalBundle.receipts) ? finalBundle.receipts.length : 0,
|
|
1754
|
+
context_item_count: Array.isArray(artifacts.contextPack.memories) ? artifacts.contextPack.memories.length : 0,
|
|
1755
|
+
verify_ok: finalVerifyReport.ok === true,
|
|
1756
|
+
},
|
|
1757
|
+
status_summary: statusSummary,
|
|
1758
|
+
search_summary: searchSummary,
|
|
1759
|
+
cross_model_summary: crossModelReport,
|
|
1760
|
+
claim_boundaries: testDriveClaimBoundaries(),
|
|
1761
|
+
}, io);
|
|
1762
|
+
return ok ? 0 : 1;
|
|
1763
|
+
}
|
|
1764
|
+
|
|
1441
1765
|
async function exportCommand(flags, io) {
|
|
1442
1766
|
const bundlePath = resolve(String(getFlag(flags, ['bundle', 'file'], DEFAULT_BUNDLE)));
|
|
1443
1767
|
const { vault } = await loadState(bundlePath);
|
|
@@ -1945,6 +2269,7 @@ function usage() {
|
|
|
1945
2269
|
'init',
|
|
1946
2270
|
'setup',
|
|
1947
2271
|
'quickstart',
|
|
2272
|
+
'test-drive',
|
|
1948
2273
|
'demo cross-model',
|
|
1949
2274
|
'doctor',
|
|
1950
2275
|
'install',
|
|
@@ -2024,6 +2349,13 @@ function usage() {
|
|
|
2024
2349
|
'--memory-text <text>': 'Inline demo memory text for non-private demos only.',
|
|
2025
2350
|
'--overwrite': 'Replace existing quickstart output files.',
|
|
2026
2351
|
},
|
|
2352
|
+
test_drive_options: {
|
|
2353
|
+
'--out-dir <path>': `Isolated demo directory. Defaults to ${DEFAULT_TEST_DRIVE_DIR}.`,
|
|
2354
|
+
'--bundle <path>': `Bundle JSON to create. Defaults to ${DEFAULT_TEST_DRIVE_DIR}/${DEFAULT_TEST_DRIVE_BUNDLE_NAME}.`,
|
|
2355
|
+
'--client <id|auto>': 'Client setup planning passthrough. No client config files are written by test-drive.',
|
|
2356
|
+
'--overwrite': 'Replace existing test-drive artifact files.',
|
|
2357
|
+
'--dry-run': 'Plan the local test drive without writing artifacts.',
|
|
2358
|
+
},
|
|
2027
2359
|
cross_model_demo_options: {
|
|
2028
2360
|
'--bundle <path>': `Reuse a local Enigma bundle. If omitted, ${DEFAULT_CROSS_MODEL_DEMO_BUNDLE} is recreated as a demo-only local vault.`,
|
|
2029
2361
|
'--memory-file <path>': 'Seed the demo from a local file without echoing plaintext. Alias: --text-file.',
|
|
@@ -2098,7 +2430,7 @@ export async function main(argv = process.argv.slice(2), io = { stdout: process.
|
|
|
2098
2430
|
const twoPartCommands = ['boundary', 'mcp', 'mesh', 'enterprise', 'capsule', 'relay', 'gateway', 'connect', 'disconnect', 'import', 'native-host', 'meter', 'settlement', 'demo', 'passport'];
|
|
2099
2431
|
const flags = parseArgs(twoPartCommands.includes(command) ? argv.slice(2) : argv.slice(1));
|
|
2100
2432
|
const positionalFile = optionalPositional(argv[2]);
|
|
2101
|
-
if ((flags.has('help') || argv.includes('-h')) && (command === 'setup' || command === 'search' || command === 'status' || (command === 'passport' && subcommand === 'status') || ((command === 'relay' || command === 'gateway') && (subcommand === 'serve' || subcommand === 'demo')) || (command === 'native-host' && (subcommand === 'manifest' || subcommand === 'install-plan')) || (command === 'demo' && subcommand === 'cross-model'))) {
|
|
2433
|
+
if ((flags.has('help') || argv.includes('-h')) && (command === 'setup' || command === 'test-drive' || command === 'search' || command === 'status' || (command === 'passport' && subcommand === 'status') || ((command === 'relay' || command === 'gateway') && (subcommand === 'serve' || subcommand === 'demo')) || (command === 'native-host' && (subcommand === 'manifest' || subcommand === 'install-plan')) || (command === 'demo' && subcommand === 'cross-model'))) {
|
|
2102
2434
|
print(usage(), io);
|
|
2103
2435
|
return 0;
|
|
2104
2436
|
}
|
|
@@ -2106,6 +2438,7 @@ export async function main(argv = process.argv.slice(2), io = { stdout: process.
|
|
|
2106
2438
|
if (command === 'init') return await initCommand(flags, io);
|
|
2107
2439
|
if (command === 'setup') return await setupCommand(flags, io);
|
|
2108
2440
|
if (command === 'quickstart') return await quickstartCommand(flags, io);
|
|
2441
|
+
if (command === 'test-drive') return await testDriveCommand(flags, io);
|
|
2109
2442
|
if (command === 'demo' && subcommand === 'cross-model') return await crossModelDemoCommand(flags, io);
|
|
2110
2443
|
if (command === 'doctor') return await doctorCommand(flags, io);
|
|
2111
2444
|
if (command === 'install') return await installCommand(flags, io);
|
|
@@ -2,30 +2,37 @@
|
|
|
2
2
|
|
|
3
3
|
Enigma Memory is a local-first SDK, CLI, MCP server, and service-contract package. The developer surfaces are designed to be copied without secrets, cloud credentials, hidden local paths, or account identifiers.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Public test-drive loop
|
|
6
6
|
|
|
7
7
|
For most developers, start with the installed CLI before reading the SDK internals or service contracts:
|
|
8
8
|
|
|
9
9
|
```sh
|
|
10
10
|
npm install -g enigma-memory
|
|
11
|
-
enigma
|
|
11
|
+
enigma test-drive --overwrite
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
`enigma
|
|
14
|
+
`enigma test-drive --overwrite` is zero-credential, local-only, and public-safe by default. It writes an isolated demo under `.enigma/test-drive`, keeps the default bundle inside that directory, emits one JSON summary, and does not print raw private memory plaintext. Use `--dry-run` to preview without writing or `--out-dir <path>` to choose another isolated demo directory.
|
|
15
|
+
|
|
16
|
+
The test drive runs the local proof/demo path only: setup artifacts, search/status output, a cross-model demo report, and benchmark pointers. It does not call external providers, contact hosted Enigma SaaS, require OpenAI/Anthropic/Cloudflare credentials, create accounts, or write third-party client configs. Keep public claims bounded to local Enigma-controlled vault state, receipts, checkpoints, committed roots, exported bundle shape, and declared boundary operations.
|
|
15
17
|
|
|
16
|
-
To
|
|
18
|
+
To explicitly connect real local clients that are already installed or already configured:
|
|
17
19
|
|
|
18
20
|
```sh
|
|
19
|
-
enigma setup --
|
|
21
|
+
enigma setup --connect-installed --overwrite
|
|
20
22
|
```
|
|
21
23
|
|
|
22
|
-
|
|
24
|
+
`--connect-installed` implies auto selection, writes only for installed/config-present clients, and skips missing configs instead of creating every default client config. Only explicit write flags mutate client configs; `enigma connect <client>` without `--dry-run` remains the single-client write path, and existing `enigma setup --write-connectors` behavior for explicit/default clients is unchanged. Treat provider-native memory as non-canonical cache only; the local Enigma vault is canonical.
|
|
25
|
+
|
|
26
|
+
## CLI memory passport loop
|
|
27
|
+
|
|
28
|
+
After the public test drive, create a regular local workspace when you want day-to-day CLI usage:
|
|
23
29
|
|
|
24
30
|
```sh
|
|
25
|
-
|
|
31
|
+
npm install -g enigma-memory
|
|
32
|
+
enigma setup --overwrite
|
|
26
33
|
```
|
|
27
34
|
|
|
28
|
-
|
|
35
|
+
`enigma setup --overwrite` is the safe default for a regular local workspace. It writes local Enigma artifacts under the workspace `.enigma` path and emits deterministic, public-safe JSON without printing raw memory plaintext. It does not write third-party app configs.
|
|
29
36
|
|
|
30
37
|
After setup, use the same local vault from the CLI or connected clients:
|
|
31
38
|
|
|
@@ -60,15 +67,16 @@ The example app prints ids, counts, roots, and verification status only. It does
|
|
|
60
67
|
|
|
61
68
|
## CLI and CI loop
|
|
62
69
|
|
|
63
|
-
The CI example installs Node 24, installs the published `enigma-memory@0.1.
|
|
70
|
+
The CI example installs Node 24, installs the published `enigma-memory@0.1.11` package, runs:
|
|
64
71
|
|
|
65
72
|
```sh
|
|
73
|
+
npx --yes --package enigma-memory enigma test-drive --overwrite
|
|
66
74
|
npx --yes --package enigma-memory enigma setup --overwrite
|
|
67
75
|
npx --yes --package enigma-memory enigma doctor
|
|
68
76
|
npm run benchmark:memory-suite -- --out benchmark-report.json
|
|
69
77
|
```
|
|
70
78
|
|
|
71
|
-
and then runs a small ESM import smoke. It does not require GitHub secrets, cloud provider credentials, npm tokens, private bundles, local path assumptions, or official dataset network downloads in normal CI. The benchmark
|
|
79
|
+
and then runs a small ESM import smoke. It does not require GitHub secrets, cloud provider credentials, npm tokens, private bundles, local path assumptions, hosted Enigma SaaS, external memory-provider calls, or official dataset network downloads in normal CI. The test-drive and benchmark steps write public-safe local JSON reports; see the benchmark reproducibility guide for claim boundaries and the requirements for any future live third-party comparison.
|
|
72
80
|
|
|
73
81
|
The workflow also includes optional official-dataset benchmark preparation steps gated behind the manual `workflow_dispatch` input `run_standard_benchmark: true`. Normal `push` and `pull_request` runs skip them, so official dataset downloads are not required in normal CI. Enable the manual path only after the repository has reviewed network use and dataset-license handling:
|
|
74
82
|
|
|
@@ -84,7 +92,7 @@ Use the workflow as a template in a consumer repository. It is intentionally lim
|
|
|
84
92
|
|
|
85
93
|
## MCP client loop
|
|
86
94
|
|
|
87
|
-
The same installed package can be used by Claude Desktop, Cursor, Kimi Code, or any generic MCP client. The smooth setup path is `enigma setup --client auto --overwrite` to plan detected clients, then `enigma setup --connect-installed --overwrite` only when you explicitly want setup to write installed/config-present client configs. Manual snippets remain useful when a client needs a copied entry; replace the bundle path with the local path from your setup output, and restart the client.
|
|
95
|
+
The same installed package can be used by Claude Desktop, Cursor, Kimi Code, or any generic MCP client. Run `enigma test-drive --overwrite` first if you want a zero-credential local proof before touching real client configs. The smooth setup path is `enigma setup --client auto --overwrite` to plan detected clients, then `enigma setup --connect-installed --overwrite` only when you explicitly want setup to write installed/config-present client configs. Manual snippets remain useful when a client needs a copied entry; replace the bundle path with the local path from your setup output, and restart the client.
|
|
88
96
|
|
|
89
97
|
Claude Desktop:
|
|
90
98
|
|
package/docs/sdk-api.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# SDK and API guide
|
|
2
2
|
|
|
3
|
-
This guide covers the public package imports for `enigma-memory@0.1.
|
|
3
|
+
This guide covers the public package imports for `enigma-memory@0.1.11`. The SDK runs locally by default: vaults, passports, context packs, receipts, relay/gateway demo state, storage contracts, metering artifacts, settlement artifacts, and hosted-cloud contract packets are package-level developer surfaces. They are not evidence of hosted Enigma cloud, live customer API key issuance, provider-side deletion, provider model forgetting, token ROI, invoice savings, compliance certification, or benchmark leadership.
|
|
4
4
|
|
|
5
5
|
## Install and import style
|
|
6
6
|
|
package/package.json
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
const DEFAULT_BUNDLE = '.enigma/bundle.json';
|
|
18
18
|
const JSONRPC_VERSION = '2.0';
|
|
19
19
|
const MCP_PROTOCOL_VERSION = '2024-11-05';
|
|
20
|
-
const SERVER_INFO = Object.freeze({ name: 'enigma-mcp-server', version: '0.1.
|
|
20
|
+
const SERVER_INFO = Object.freeze({ name: 'enigma-mcp-server', version: '0.1.11' });
|
|
21
21
|
const JSON_RPC_ID_PATTERN = /^[A-Za-z0-9._:-]{1,128}$/;
|
|
22
22
|
const JSON_RPC_ERROR = Object.freeze({
|
|
23
23
|
INVALID_REQUEST: -32600,
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
} from '../packages/hosted-cloud/src/index.js';
|
|
14
14
|
|
|
15
15
|
export const HOSTED_API_KEY_LIFECYCLE_PACKET_SCHEMA = HOSTED_CLOUD_API_KEY_LIFECYCLE_PACKET_SCHEMA;
|
|
16
|
-
export const HOSTED_API_KEY_LIFECYCLE_RELEASE_TARGET = '0.1.
|
|
16
|
+
export const HOSTED_API_KEY_LIFECYCLE_RELEASE_TARGET = '0.1.11';
|
|
17
17
|
|
|
18
18
|
const PROVIDED = 'provided';
|
|
19
19
|
const BLOCKED = 'blocked_external_dependency';
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
} from 'enigma-memory/hosted-cloud';
|
|
29
29
|
|
|
30
30
|
export const HOSTED_CUSTOMER_LIFECYCLE_PACKET_SCHEMA = HOSTED_CLOUD_CUSTOMER_LIFECYCLE_PACKET_SCHEMA;
|
|
31
|
-
export const HOSTED_CUSTOMER_LIFECYCLE_RELEASE_TARGET = '0.1.
|
|
31
|
+
export const HOSTED_CUSTOMER_LIFECYCLE_RELEASE_TARGET = '0.1.11';
|
|
32
32
|
|
|
33
33
|
const PROVIDED = 'provided';
|
|
34
34
|
const BLOCKED_MISSING = 'blocked_missing_evidence';
|
|
@@ -6,7 +6,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
6
6
|
|
|
7
7
|
export const INSTALLER_ASSET_SCHEMA = 'enigma.installer_assets.v1';
|
|
8
8
|
export const INSTALLER_ASSET_PACKAGE = 'enigma-memory';
|
|
9
|
-
export const INSTALLER_ASSET_VERSION = '0.1.
|
|
9
|
+
export const INSTALLER_ASSET_VERSION = '0.1.11';
|
|
10
10
|
export const INSTALLER_ASSET_GENERATED_AT = '1970-01-01T00:00:00.000Z';
|
|
11
11
|
|
|
12
12
|
const SCRIPT_PATH = fileURLToPath(import.meta.url);
|
|
@@ -995,7 +995,7 @@ function buildSuiteReport(datasetRows, topK, options) {
|
|
|
995
995
|
generated_at: options.generated_at ?? new Date().toISOString(),
|
|
996
996
|
package: {
|
|
997
997
|
name: 'enigma-memory',
|
|
998
|
-
version: '0.1.
|
|
998
|
+
version: '0.1.11',
|
|
999
999
|
},
|
|
1000
1000
|
public_safe: true,
|
|
1001
1001
|
top_k: topK,
|