enigma-memory 0.1.12 → 0.1.14
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 +36 -17
- package/apps/cli/bin/enigma.mjs +425 -49
- package/deploy/docker-compose.local-production-simulation.yml +10 -11
- package/docs/benchmark-attestation-network.md +487 -487
- package/docs/benchmark-reproducibility.md +10 -9
- package/docs/client-connectors.md +512 -0
- package/docs/demo-proof-network.md +275 -275
- package/docs/developer-ecosystem.md +223 -223
- package/docs/developer-proof-quickstart.md +325 -325
- package/docs/enigma-memory-ready-conformance.md +376 -376
- package/docs/hosted-cloud-product.md +10 -0
- package/docs/install-anywhere.md +534 -0
- package/docs/installers-and-desktop.md +9 -7
- package/docs/proof-network-build-notes.md +240 -240
- package/docs/proof-network.md +257 -257
- package/docs/sdk-api.md +324 -322
- package/docs/solana-devnet-acceptance.md +48 -0
- package/docs/solana-proof-rail.md +453 -453
- package/examples/ci/github-actions.yml +7 -6
- package/package.json +11 -1
- package/packages/mcp-server/src/index.js +1 -1
- package/packages/passport/src/index.js +9 -5
- package/scripts/build-benchmark-proof-release.mjs +391 -0
- package/scripts/build-goal-completion-audit.mjs +11 -5
- 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 +126 -10
- package/scripts/build-production-handoff-packet.mjs +7 -6
- package/scripts/build-production-unblocker.mjs +409 -0
- package/scripts/build-proof-network-packet.mjs +1 -1
- package/scripts/install-enigma-local.mjs +270 -0
- package/scripts/release-audit.mjs +71 -2
- package/scripts/run-standard-memory-benchmarks.mjs +1 -1
- package/scripts/verify-registry-install.mjs +1 -0
- package/scripts/wait-for-backend-ready.mjs +4 -2
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
validateProofNetworkPacket,
|
|
16
16
|
} from '../packages/proof-network/src/index.js';
|
|
17
17
|
|
|
18
|
-
export const PROOF_NETWORK_PACKET_RELEASE_TARGET = '0.1.
|
|
18
|
+
export const PROOF_NETWORK_PACKET_RELEASE_TARGET = '0.1.14';
|
|
19
19
|
|
|
20
20
|
const HASH_RE = /^(?:sha256:)?[a-f0-9]{64}$/iu;
|
|
21
21
|
const SECRET_VALUE_RE = /(?:Bearer\s+[A-Za-z0-9._~+/=-]{12,}|Basic\s+[A-Za-z0-9+/=-]{12,}|-----BEGIN [A-Z ]*PRIVATE KEY-----|https?:\/\/[^\s/@]+:[^\s/@]+@|sk-[A-Za-z0-9_-]{16,}|AKIA[0-9A-Z]{16}|\b(?:raw[\s_-]*memory|plaintext[\s_-]*prompts?|plain[\s_-]*text[\s_-]*prompts?|private[\s_-]*prompts?|provider[\s_-]*responses?|full[\s_-]*transcript|decrypted[\s_-]*memory|credentials?|secrets?|passwords?|private[\s_-]*keys?|api[\s_-]*key[\s_-]*(?:secret|material|value)|api[\s_-]*secrets?|access[\s_-]*tokens?|refresh[\s_-]*tokens?|token[\s_-]*values?|credential[\s_-]*material|tenant[\s_-]*names?)\b)/iu;
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { execFile } from 'node:child_process';
|
|
3
|
+
import { mkdir } from 'node:fs/promises';
|
|
4
|
+
import { dirname, isAbsolute, resolve as resolvePath } from 'node:path';
|
|
5
|
+
import { promisify } from 'node:util';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
|
|
8
|
+
export const INSTALLER_SCHEMA = 'enigma.local_installer.v1';
|
|
9
|
+
export const REQUIRED_NODE_MAJOR = 24;
|
|
10
|
+
export const DEFAULT_BUNDLE_PATH = '.enigma/bundle.json';
|
|
11
|
+
|
|
12
|
+
const execFileAsync = promisify(execFile);
|
|
13
|
+
const SCRIPT_PATH = fileURLToPath(import.meta.url);
|
|
14
|
+
const DEFAULT_PACKAGE_DIR = resolvePath(dirname(SCRIPT_PATH), '..');
|
|
15
|
+
const SAFE_COMMAND_RE = /^[A-Za-z0-9._-]+$/u;
|
|
16
|
+
|
|
17
|
+
function readRequiredValue(argv, index, flag) {
|
|
18
|
+
const value = argv[index + 1];
|
|
19
|
+
if (value === undefined || value.startsWith('--')) throw new Error(`Missing value for ${flag}.`);
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function usage() {
|
|
24
|
+
return `Usage: node scripts/install-enigma-local.mjs [--dry-run|--execute] [--init-vault] [--bundle <path>]\n\nDry-run is the default. Execute mode runs npm install -g . from the local checkout.\nNo network download command is generated, and vault initialization runs only when --init-vault is present.\n`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function parseInstallerArgs(argv = process.argv.slice(2)) {
|
|
28
|
+
const options = {
|
|
29
|
+
dryRun: true,
|
|
30
|
+
execute: false,
|
|
31
|
+
initVault: false,
|
|
32
|
+
bundlePath: DEFAULT_BUNDLE_PATH,
|
|
33
|
+
packageDir: DEFAULT_PACKAGE_DIR,
|
|
34
|
+
subject: 'local-user',
|
|
35
|
+
displayName: 'Local user',
|
|
36
|
+
};
|
|
37
|
+
let sawDryRun = false;
|
|
38
|
+
let sawExecute = false;
|
|
39
|
+
|
|
40
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
41
|
+
const arg = argv[index];
|
|
42
|
+
if (arg === '--help' || arg === '-h') {
|
|
43
|
+
options.help = true;
|
|
44
|
+
} else if (arg === '--dry-run') {
|
|
45
|
+
sawDryRun = true;
|
|
46
|
+
options.dryRun = true;
|
|
47
|
+
options.execute = false;
|
|
48
|
+
} else if (arg === '--execute') {
|
|
49
|
+
sawExecute = true;
|
|
50
|
+
options.dryRun = false;
|
|
51
|
+
options.execute = true;
|
|
52
|
+
} else if (arg === '--init-vault') {
|
|
53
|
+
options.initVault = true;
|
|
54
|
+
} else if (arg === '--no-init-vault') {
|
|
55
|
+
options.initVault = false;
|
|
56
|
+
} else if (arg === '--bundle') {
|
|
57
|
+
options.bundlePath = readRequiredValue(argv, index, arg);
|
|
58
|
+
index += 1;
|
|
59
|
+
} else if (arg === '--package-dir') {
|
|
60
|
+
options.packageDir = readRequiredValue(argv, index, arg);
|
|
61
|
+
index += 1;
|
|
62
|
+
} else if (arg === '--subject') {
|
|
63
|
+
options.subject = readRequiredValue(argv, index, arg);
|
|
64
|
+
index += 1;
|
|
65
|
+
} else if (arg === '--display-name') {
|
|
66
|
+
options.displayName = readRequiredValue(argv, index, arg);
|
|
67
|
+
index += 1;
|
|
68
|
+
} else {
|
|
69
|
+
throw new Error('Unknown argument.');
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (sawDryRun && sawExecute) throw new Error('Use either --dry-run or --execute, not both.');
|
|
74
|
+
return options;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function nodeMajor(version) {
|
|
78
|
+
const match = String(version ?? '').trim().match(/^v?(\d+)(?:\.\d+){0,2}(?:[-+].*)?$/u);
|
|
79
|
+
if (!match) throw new Error('Invalid Node version override.');
|
|
80
|
+
return Number(match[1]);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function validateNodeVersion(version = process.versions.node, requiredMajor = REQUIRED_NODE_MAJOR) {
|
|
84
|
+
const major = nodeMajor(version);
|
|
85
|
+
if (!Number.isSafeInteger(major) || major < requiredMajor) {
|
|
86
|
+
throw new Error(`Node >=${requiredMajor} is required for the local Enigma installer.`);
|
|
87
|
+
}
|
|
88
|
+
return { ok: true, required: `>=${requiredMajor}`, current_major: major };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function commandForPlatform(base, platform) {
|
|
92
|
+
return platform === 'win32' ? `${base}.cmd` : base;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function rejectUnsafeArg(arg, label) {
|
|
96
|
+
const value = String(arg ?? '');
|
|
97
|
+
if (value.length === 0) throw new Error(`${label} must not be empty.`);
|
|
98
|
+
if (value.includes('\0') || value.includes('\n') || value.includes('\r')) throw new Error(`${label} contains an invalid control character.`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function validateCommandSpec(spec) {
|
|
102
|
+
if (!spec || typeof spec !== 'object' || Array.isArray(spec)) throw new Error('Installer command spec must be an object.');
|
|
103
|
+
const command = String(spec.command ?? '');
|
|
104
|
+
if (!SAFE_COMMAND_RE.test(command)) throw new Error('Installer command name is not safe.');
|
|
105
|
+
const args = Array.isArray(spec.args) ? spec.args.map(String) : [];
|
|
106
|
+
for (const [index, arg] of args.entries()) rejectUnsafeArg(arg, `Installer command argument ${index}`);
|
|
107
|
+
|
|
108
|
+
if (command === 'npm' || command === 'npm.cmd') {
|
|
109
|
+
if (args.length !== 3 || args[0] !== 'install' || args[1] !== '-g' || args[2] !== '.') {
|
|
110
|
+
throw new Error('Installer npm command must be exactly npm install -g .');
|
|
111
|
+
}
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (command === 'enigma' || command === 'enigma.cmd') {
|
|
116
|
+
const bundleIndex = args.indexOf('--bundle');
|
|
117
|
+
if (args[0] !== 'init' || bundleIndex === -1 || bundleIndex + 1 >= args.length) {
|
|
118
|
+
throw new Error('Installer Enigma command must initialize a bundle with --bundle.');
|
|
119
|
+
}
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
throw new Error('Installer command is not allowlisted.');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function publicCommand(command) {
|
|
127
|
+
if (command.step === 'install_package') return { command: 'npm', args: ['install', '-g', '.'] };
|
|
128
|
+
return { command: 'enigma', args: ['init', '--bundle', '<bundle-path>', '--subject', '<subject>', '--display-name', '<display-name>'] };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function buildInstallerPlan(options = {}, runtime = {}) {
|
|
132
|
+
const platform = runtime.platform ?? process.platform;
|
|
133
|
+
const cwd = runtime.cwd ?? process.cwd();
|
|
134
|
+
const requestedPackageDir = String(options.packageDir ?? DEFAULT_PACKAGE_DIR);
|
|
135
|
+
rejectUnsafeArg(requestedPackageDir, 'Package directory');
|
|
136
|
+
const packageDir = resolvePath(requestedPackageDir);
|
|
137
|
+
const requestedBundlePath = String(options.bundlePath ?? DEFAULT_BUNDLE_PATH);
|
|
138
|
+
rejectUnsafeArg(requestedBundlePath, 'Bundle path');
|
|
139
|
+
const bundlePath = isAbsolute(requestedBundlePath) ? resolvePath(requestedBundlePath) : resolvePath(cwd, requestedBundlePath);
|
|
140
|
+
|
|
141
|
+
const commands = [
|
|
142
|
+
{
|
|
143
|
+
step: 'install_package',
|
|
144
|
+
command: commandForPlatform('npm', platform),
|
|
145
|
+
args: ['install', '-g', '.'],
|
|
146
|
+
cwd: packageDir,
|
|
147
|
+
mutates_global_state: true,
|
|
148
|
+
},
|
|
149
|
+
];
|
|
150
|
+
|
|
151
|
+
if (options.initVault === true) {
|
|
152
|
+
commands.push({
|
|
153
|
+
step: 'initialize_vault',
|
|
154
|
+
command: commandForPlatform('enigma', platform),
|
|
155
|
+
args: ['init', '--bundle', bundlePath, '--subject', String(options.subject ?? 'local-user'), '--display-name', String(options.displayName ?? 'Local user')],
|
|
156
|
+
cwd: packageDir,
|
|
157
|
+
mutates_local_filesystem: true,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
for (const command of commands) validateCommandSpec(command);
|
|
162
|
+
|
|
163
|
+
return {
|
|
164
|
+
dryRun: options.execute === true ? false : true,
|
|
165
|
+
execute: options.execute === true,
|
|
166
|
+
packageDir,
|
|
167
|
+
bundlePath,
|
|
168
|
+
bundlePathKind: requestedBundlePath === DEFAULT_BUNDLE_PATH ? 'default' : (isAbsolute(requestedBundlePath) ? 'absolute' : 'relative'),
|
|
169
|
+
initVault: options.initVault === true,
|
|
170
|
+
commands,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function publicCommandRecords(plan, resultByStep = new Map()) {
|
|
175
|
+
return plan.commands.map((command) => {
|
|
176
|
+
const publicSpec = publicCommand(command);
|
|
177
|
+
const runResult = resultByStep.get(command.step);
|
|
178
|
+
return {
|
|
179
|
+
step: command.step,
|
|
180
|
+
command: publicSpec.command,
|
|
181
|
+
args: publicSpec.args,
|
|
182
|
+
status: plan.execute ? (runResult?.ok ? 'executed' : 'pending') : 'preview',
|
|
183
|
+
mutates: command.mutates_global_state === true ? 'global_npm_install' : 'local_bundle_file',
|
|
184
|
+
};
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function publicOutput(plan, node, commandResults = []) {
|
|
189
|
+
const resultByStep = new Map(commandResults.map((result) => [result.step, result]));
|
|
190
|
+
const commands = publicCommandRecords(plan, resultByStep);
|
|
191
|
+
return {
|
|
192
|
+
schema: INSTALLER_SCHEMA,
|
|
193
|
+
ok: commandResults.every((result) => result.ok !== false),
|
|
194
|
+
mode: plan.execute ? 'execute' : 'dry-run',
|
|
195
|
+
dry_run: plan.dryRun,
|
|
196
|
+
execute: plan.execute,
|
|
197
|
+
public_safe: true,
|
|
198
|
+
node,
|
|
199
|
+
package_source: {
|
|
200
|
+
kind: 'local_checkout',
|
|
201
|
+
install_boundary: 'Runs npm install -g . against the checked-out package only; it does not download Enigma from a registry.',
|
|
202
|
+
},
|
|
203
|
+
bundle: {
|
|
204
|
+
path: '<bundle-path>',
|
|
205
|
+
path_kind: plan.bundlePathKind,
|
|
206
|
+
initialize_requested: plan.initVault,
|
|
207
|
+
initialized: plan.execute && plan.initVault && resultByStep.get('initialize_vault')?.ok === true,
|
|
208
|
+
},
|
|
209
|
+
commands,
|
|
210
|
+
preview: {
|
|
211
|
+
commands,
|
|
212
|
+
},
|
|
213
|
+
safety: {
|
|
214
|
+
default_dry_run: true,
|
|
215
|
+
requires_execute_for_mutation: true,
|
|
216
|
+
shell: false,
|
|
217
|
+
network_download_command: false,
|
|
218
|
+
prints_local_absolute_paths: false,
|
|
219
|
+
prints_secrets: false,
|
|
220
|
+
},
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
async function runCommand(command, execFileImpl) {
|
|
225
|
+
try {
|
|
226
|
+
await execFileImpl(command.command, command.args, { cwd: command.cwd, windowsHide: true });
|
|
227
|
+
return { step: command.step, ok: true };
|
|
228
|
+
} catch {
|
|
229
|
+
throw new Error(`Installer command failed at ${command.step}.`);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export async function runInstallEnigmaLocal(argv = process.argv.slice(2), runtime = {}) {
|
|
234
|
+
const options = Array.isArray(argv) ? parseInstallerArgs(argv) : { ...argv };
|
|
235
|
+
const node = validateNodeVersion(options.nodeVersion ?? runtime.nodeVersion ?? process.versions.node);
|
|
236
|
+
const plan = buildInstallerPlan(options, runtime);
|
|
237
|
+
if (plan.dryRun) return publicOutput(plan, node);
|
|
238
|
+
|
|
239
|
+
const mkdirImpl = runtime.mkdirImpl ?? mkdir;
|
|
240
|
+
if (options.initVault === true) await mkdirImpl(dirname(plan.bundlePath), { recursive: true });
|
|
241
|
+
const execFileImpl = runtime.execFileImpl ?? execFileAsync;
|
|
242
|
+
const commandResults = [];
|
|
243
|
+
for (const command of plan.commands) {
|
|
244
|
+
commandResults.push(await runCommand(command, execFileImpl));
|
|
245
|
+
}
|
|
246
|
+
return publicOutput(plan, node, commandResults);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function safeErrorMessage(error) {
|
|
250
|
+
const message = String(error?.message ?? error);
|
|
251
|
+
if (/^(Missing value|Unknown argument|Use either|Invalid Node version|Node >=|Installer command)/u.test(message)) return message;
|
|
252
|
+
return 'Local Enigma installer failed.';
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
async function main() {
|
|
256
|
+
const args = parseInstallerArgs();
|
|
257
|
+
if (args.help) {
|
|
258
|
+
process.stdout.write(usage());
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
const output = await runInstallEnigmaLocal(args);
|
|
262
|
+
process.stdout.write(`${JSON.stringify(output, null, 2)}\n`);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (process.argv[1] && fileURLToPath(import.meta.url) === resolvePath(process.argv[1])) {
|
|
266
|
+
main().catch((error) => {
|
|
267
|
+
process.stdout.write(`${JSON.stringify({ schema: INSTALLER_SCHEMA, ok: false, public_safe: true, error: { code: 'LOCAL_INSTALLER_FAILED', message: safeErrorMessage(error) } }, null, 2)}\n`);
|
|
268
|
+
process.exitCode = 1;
|
|
269
|
+
});
|
|
270
|
+
}
|
|
@@ -136,6 +136,10 @@ const KUBERNETES_BACKEND_MANIFEST = resolve(PROJECT_ROOT, 'deploy', 'kubernetes'
|
|
|
136
136
|
const ENIGMA_INFRASTRUCTURE_READINESS_MANIFEST = 'ENIGMA_INFRASTRUCTURE_READINESS_MANIFEST';
|
|
137
137
|
const ENIGMA_INFRASTRUCTURE_READINESS_LIVE = 'ENIGMA_INFRASTRUCTURE_READINESS_LIVE';
|
|
138
138
|
const SECRET_LOOKING_OUTPUT = /(?:Authorization:\s*Bearer\s+[A-Za-z0-9._~+/=-]{8,}|-----BEGIN [A-Z ]*PRIVATE KEY-----|["']?(?:api[_-]?key|access[_-]?token|refresh[_-]?token|secret|password|private[_-]?key)["']?\s*[:=]\s*["']?[A-Za-z0-9._~+/=-]{16,})/i;
|
|
139
|
+
const TEST_FAILURE_SUMMARY_LIMIT = 8;
|
|
140
|
+
const TEST_OUTPUT_TAIL_LINE_LIMIT = 18;
|
|
141
|
+
const TEST_OUTPUT_TAIL_CHAR_LIMIT = 280;
|
|
142
|
+
const REDACTED_DIAGNOSTIC_LINE = '<redacted secret-looking output>';
|
|
139
143
|
|
|
140
144
|
function npmInvocation(args) {
|
|
141
145
|
const label = commandLabel('npm', args);
|
|
@@ -235,6 +239,68 @@ function tapCounts(output) {
|
|
|
235
239
|
return counts;
|
|
236
240
|
}
|
|
237
241
|
|
|
242
|
+
function sanitizeDiagnosticLine(value) {
|
|
243
|
+
const scrubbed = scrubLocalPathText(value)
|
|
244
|
+
.replace(/file:\/\/(?=<(?:project-root|public-site-package|temp|user-home|home)>)/g, '')
|
|
245
|
+
.replace(/[A-Za-z]:\/[^\s'"`),]+/g, '<path>')
|
|
246
|
+
.replace(/(?:file:\/\/)?\/(?:Users|home|tmp|private\/var|var\/folders)\/[^\s'"`),]+/g, '<path>')
|
|
247
|
+
.replace(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/gi, '<email>')
|
|
248
|
+
.replace(/\s+/g, ' ')
|
|
249
|
+
.trim();
|
|
250
|
+
if (!scrubbed) return '';
|
|
251
|
+
if (
|
|
252
|
+
SECRET_LOOKING_OUTPUT.test(scrubbed)
|
|
253
|
+
|| RAW_MEMORY_EXAMPLE_FIELD.test(scrubbed)
|
|
254
|
+
|| scrubbed.includes(RAW_MEMORY_SENTINEL)
|
|
255
|
+
) return REDACTED_DIAGNOSTIC_LINE;
|
|
256
|
+
return scrubbed.length > TEST_OUTPUT_TAIL_CHAR_LIMIT
|
|
257
|
+
? `${scrubbed.slice(0, TEST_OUTPUT_TAIL_CHAR_LIMIT - 1)}…`
|
|
258
|
+
: scrubbed;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function diagnosticLines(value) {
|
|
262
|
+
return String(value).split(/\r?\n/).map(sanitizeDiagnosticLine).filter(Boolean);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function diagnosticMessage(value) {
|
|
266
|
+
return diagnosticLines(value)[0] ?? 'Command failed.';
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function failingTestNames(output) {
|
|
270
|
+
const names = [];
|
|
271
|
+
for (const line of diagnosticLines(output)) {
|
|
272
|
+
const tapMatch = line.match(/^not ok \d+ - (.+)$/);
|
|
273
|
+
const prettyMatch = line.match(/^✖\s+(.+?)(?:\s+\(\d+(?:\.\d+)?ms\))?$/u);
|
|
274
|
+
const name = tapMatch?.[1] ?? prettyMatch?.[1] ?? null;
|
|
275
|
+
if (!name || names.includes(name)) continue;
|
|
276
|
+
names.push(name);
|
|
277
|
+
if (names.length >= TEST_FAILURE_SUMMARY_LIMIT) break;
|
|
278
|
+
}
|
|
279
|
+
return names;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function diagnosticTail(stdout, stderr) {
|
|
283
|
+
const stdoutLines = diagnosticLines(stdout);
|
|
284
|
+
if (stdoutLines.length > 0) {
|
|
285
|
+
return { key: 'stdout_tail', lines: stdoutLines.slice(-TEST_OUTPUT_TAIL_LINE_LIMIT) };
|
|
286
|
+
}
|
|
287
|
+
const stderrLines = diagnosticLines(stderr);
|
|
288
|
+
if (stderrLines.length > 0) {
|
|
289
|
+
return { key: 'stderr_tail', lines: stderrLines.slice(-TEST_OUTPUT_TAIL_LINE_LIMIT) };
|
|
290
|
+
}
|
|
291
|
+
return null;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export function summarizeNpmTestFailure(stdout, stderr) {
|
|
295
|
+
const combined = `${stdout}\n${stderr}`;
|
|
296
|
+
const summary = { tap: tapCounts(combined) };
|
|
297
|
+
const failed = failingTestNames(combined);
|
|
298
|
+
const tail = diagnosticTail(stdout, stderr);
|
|
299
|
+
if (failed.length > 0) summary.failing_tests = failed;
|
|
300
|
+
if (tail) summary[tail.key] = tail.lines;
|
|
301
|
+
return summary;
|
|
302
|
+
}
|
|
303
|
+
|
|
238
304
|
function summarizeCheck(stdout) {
|
|
239
305
|
const line = lines(stdout).find((item) => item.includes('enigma check ok')) ?? lines(stdout).at(-1) ?? '';
|
|
240
306
|
return { message: line };
|
|
@@ -490,9 +556,12 @@ async function runCommandGate(name, command, args, options = {}) {
|
|
|
490
556
|
gate.signal = error.signal ?? null;
|
|
491
557
|
gate.stderr_bytes = Buffer.byteLength(error.stderr ?? '');
|
|
492
558
|
gate.stdout_bytes = Buffer.byteLength(error.stdout ?? '');
|
|
559
|
+
if (options.summarizeFailure) {
|
|
560
|
+
gate.evidence = await options.summarizeFailure(error.stdout ?? '', error.stderr ?? '');
|
|
561
|
+
}
|
|
493
562
|
gate.error = {
|
|
494
563
|
code: error.killed ? 'COMMAND_TIMEOUT' : (error.code ?? 'COMMAND_FAILED'),
|
|
495
|
-
message: error.message,
|
|
564
|
+
message: options.summarizeFailure ? diagnosticMessage(error.message) : error.message,
|
|
496
565
|
};
|
|
497
566
|
if (gate.status === 0) {
|
|
498
567
|
gate.error.code = 'OUTPUT_VALIDATION_FAILED';
|
|
@@ -5484,7 +5553,7 @@ export async function runReleaseAudit() {
|
|
|
5484
5553
|
const test = await nodeTestInvocation();
|
|
5485
5554
|
const pack = npmInvocation(['pack', '--dry-run']);
|
|
5486
5555
|
gates.push(await runCommandGate('npm-check', check.command, check.args, { label: check.label, summarize: summarizeCheck }));
|
|
5487
|
-
gates.push(await runCommandGate('npm-test', test.command, test.args, { label: test.label, timeoutMs: TEST_TIMEOUT_MS, summarize: summarizeTests }));
|
|
5556
|
+
gates.push(await runCommandGate('npm-test', test.command, test.args, { label: test.label, timeoutMs: TEST_TIMEOUT_MS, summarize: summarizeTests, summarizeFailure: summarizeNpmTestFailure }));
|
|
5488
5557
|
gates.push(await runCommandGate('npm-pack-dry-run', pack.command, pack.args, { label: pack.label, summarize: summarizePack }));
|
|
5489
5558
|
gates.push(await runDirectBinSmokes());
|
|
5490
5559
|
gates.push(await runNativeHostInstallPlanGate());
|
|
@@ -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.14',
|
|
999
999
|
},
|
|
1000
1000
|
public_safe: true,
|
|
1001
1001
|
top_k: topK,
|
|
@@ -24,6 +24,7 @@ export const DEFAULT_REGISTRY_VERSION = PACKAGE_JSON.version;
|
|
|
24
24
|
export const REGISTRY_INSTALL_CHECKS = Object.freeze([
|
|
25
25
|
Object.freeze({ step: 'check_enigma_help', bin: 'enigma', args: Object.freeze(['--help']) }),
|
|
26
26
|
Object.freeze({ step: 'check_enigma_doctor', bin: 'enigma', args: Object.freeze(['doctor']) }),
|
|
27
|
+
Object.freeze({ step: 'check_enigma_test_drive_dry_run', bin: 'enigma', args: Object.freeze(['test-drive', '--dry-run']) }),
|
|
27
28
|
Object.freeze({ step: 'check_enigma_relay_demo', bin: 'enigma-relay', args: Object.freeze(['demo']) }),
|
|
28
29
|
Object.freeze({ step: 'check_enigma_gateway_demo', bin: 'enigma-gateway', args: Object.freeze(['demo']) }),
|
|
29
30
|
]);
|
|
@@ -5,9 +5,11 @@
|
|
|
5
5
|
import https from 'node:https'
|
|
6
6
|
import { parseArgs } from 'node:util'
|
|
7
7
|
|
|
8
|
+
const RELAY_PORT = process.env.ENIGMA_SIM_RELAY_PORT || '8443'
|
|
9
|
+
const GATEWAY_PORT = process.env.ENIGMA_SIM_GATEWAY_PORT || '9443'
|
|
8
10
|
const ENDPOINTS = [
|
|
9
|
-
{ name: 'relay', url:
|
|
10
|
-
{ name: 'gateway', url:
|
|
11
|
+
{ name: 'relay', url: `https://localhost:${RELAY_PORT}/readyz` },
|
|
12
|
+
{ name: 'gateway', url: `https://localhost:${GATEWAY_PORT}/readyz` },
|
|
11
13
|
]
|
|
12
14
|
|
|
13
15
|
function parseCliArgs(argv) {
|