blob: 49e104d24857725da032d2bcb9bb14cd8c026f33 [file]
#!/usr/bin/env node
import { createHash } from 'node:crypto';
import { spawn } from 'node:child_process';
import { createReadStream, createWriteStream } from 'node:fs';
import {
mkdtemp,
mkdir,
open,
readdir,
readFile,
realpath,
rm,
stat,
writeFile,
} from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { performance } from 'node:perf_hooks';
import { dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
import { createInterface } from 'node:readline';
import { Writable } from 'node:stream';
import { pipeline } from 'node:stream/promises';
import { fileURLToPath, pathToFileURL } from 'node:url';
import {
SESSION_BUNDLE_PORTABLE_SESSION_DIRECTORIES,
SESSION_BUNDLE_PORTABLE_SESSION_FILES,
SESSION_BUNDLE_STATE_ENTRIES,
isArtifactPathForSession,
} from '@maka/storage';
import { STORAGE_ROOT_MARKER_FILE } from '@maka/storage/root-authority';
import {
constants as zlibConstants,
createBrotliCompress,
createGzip,
createZstdCompress,
createZstdDecompress,
} from 'node:zlib';
const SCRIPT_PATH = fileURLToPath(import.meta.url);
const SCRIPT_DIR = dirname(SCRIPT_PATH);
const REPO_ROOT = resolve(SCRIPT_DIR, '..');
const HARBOR_CELL_MODULE = resolve(REPO_ROOT, 'packages/headless/dist/harbor-cell.js');
const HEADLESS_STORAGE_MODULE = resolve(REPO_ROOT, 'packages/headless/dist/headless-storage.js');
const DEFAULT_BOOT_SAMPLES = 3;
const BUNDLE_SCHEMA_VERSION = 2;
export const DECISION_READY_MIN_SAMPLES = 100;
const SUPPORTED_OPTIONS = new Set([
'workspace',
'session-export',
'iterations',
'boot-samples',
'provider-ttfb-ms',
'runtime-build-id',
'help',
]);
// Storage-root authority markers bind a directory to its host device/inode and
// must be regenerated when a session export is materialized elsewhere.
const STORAGE_ROOT_AUTHORITY_MARKER = STORAGE_ROOT_MARKER_FILE;
const PORTABLE_STATE_TOP_LEVEL = new Set(SESSION_BUNDLE_STATE_ENTRIES);
const PORTABLE_SESSION_DIRECTORIES = new Set(SESSION_BUNDLE_PORTABLE_SESSION_DIRECTORIES);
const PORTABLE_SESSION_FILES = new Set(SESSION_BUNDLE_PORTABLE_SESSION_FILES);
const MAX_JSON_BYTES = 1_048_576;
const EXCLUDED_WORKSPACE_SEGMENTS = new Set(['.git', 'node_modules']);
const SENSITIVE_WORKSPACE_FILE_PATTERNS = [
/^\.env(?:\..*)?$/i,
/^\.(?:npmrc|netrc|pypirc|terraformrc)$/i,
/^\.git-credentials(?:\.lock)?$/i,
/^(?:credentials?|secrets?)(?:\..*)?$/i,
/(?:^|[-_.])(?:id_(?:rsa|dsa|ecdsa|ed25519)|private[-_.]?key)(?:$|[-_.])/i,
/\.(?:key|pem|p12|pfx|der|crt|cer|csr|log)$/i,
];
const SENSITIVE_KEY_PARTS = new Set([
'api_key',
'access_key',
'access_token',
'authorization',
'client_secret',
'cookie',
'credential',
'credentials',
'password',
'passwd',
'private_key',
'refresh_token',
'secret',
]);
const SENSITIVE_COMPACT_KEY_PARTS = new Set([
'apikey',
'accesskey',
'accesstoken',
'authtoken',
'clientsecret',
'idtoken',
'privatekey',
'refreshtoken',
'sessiontoken',
]);
const NON_SECRET_KEY_NAMES = new Set(['agentSwarmAuthorization', 'author']);
const SECRET_PATTERNS = [
/((?:authorization|x-api-key|api-key)\s*:\s*)(?:bearer\s+|basic\s+)?[^\s,;"']+/gi,
/([?&](?:api[-_]?key|access[-_]?token|auth[-_]?token|token|password|secret)=)[^&#\s]+/gi,
/((?:api[-_]?key|auth[-_]?token|access[-_]?token|password|secret|token|cookie|set-cookie)\s*[:=]\s*)["'][^"']*["']|((?:api[-_]?key|auth[-_]?token|access[-_]?token|password|secret|token|cookie|set-cookie)\s*[:=]\s*)[^\s,;]+/gi,
/\bbearer\s+[A-Za-z0-9._~+/=-]{8,}/gi,
/\b(?:sk|ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_-]{8,}/g,
];
if (process.argv[1] && resolve(process.argv[1]) === SCRIPT_PATH) {
if (process.argv[2] === '--child-bootstrap') {
await childBootstrap(process.argv[3]);
} else {
await main(parseArgs(process.argv.slice(2)));
}
}
async function main(options) {
const workspaceInputs = options.workspace?.length ? options.workspace : [process.cwd()];
const exportRoots = options['session-export'] ?? [];
const workspaceRoots = await Promise.all(workspaceInputs.map((path) => realpath(resolve(path))));
const iterations = positiveInteger(
options.iterations ?? (exportRoots.length > 0 ? exportRoots.length : 1),
'iterations',
);
const bootSamples = positiveInteger(
options['boot-samples'] ?? DEFAULT_BOOT_SAMPLES,
'boot-samples',
);
const providerTtfbMs =
options['provider-ttfb-ms'] === undefined
? undefined
: nonNegativeNumber(options['provider-ttfb-ms'], 'provider-ttfb-ms');
if (exportRoots.length > 0 && iterations > exportRoots.length) {
throw new Error(
`--iterations (${iterations}) cannot exceed the number of --session-export paths (${exportRoots.length}); do not duplicate real sessions in a percentile report`,
);
}
if (exportRoots.length === 0 && iterations !== 1) {
throw new Error(
'--iterations must be 1 unless --session-export is supplied; do not duplicate the smoke fixture',
);
}
if (exportRoots.length === 0 && workspaceRoots.length !== 1) {
throw new Error(
'repeat --workspace only when pairing one workspace with each --session-export',
);
}
if (
exportRoots.length > 0 &&
workspaceRoots.length !== 1 &&
workspaceRoots.length !== exportRoots.length
) {
throw new Error(
`--workspace count (${workspaceRoots.length}) must be 1 or match --session-export count (${exportRoots.length})`,
);
}
if (new Set(workspaceRoots).size !== workspaceRoots.length) {
throw new Error('each --workspace path must be unique when using one-to-one pairing');
}
const sourceRoots = await Promise.all(exportRoots.map((path) => realpath(resolve(path))));
if (new Set(sourceRoots).size !== sourceRoots.length) {
throw new Error('each --session-export path must be unique; do not duplicate real sessions');
}
for (const workspaceRoot of workspaceRoots) {
for (const sourceRoot of sourceRoots) {
if (pathsOverlap(workspaceRoot, sourceRoot)) {
throw new Error(
`workspace and session export roots must not overlap: ${workspaceRoot} and ${sourceRoot}`,
);
}
}
}
const sourceSessionIds = [];
for (const sourceRoot of sourceRoots) {
sourceSessionIds.push(await readSessionExportId(sourceRoot));
}
if (new Set(sourceSessionIds).size !== sourceSessionIds.length) {
throw new Error('each --session-export must contain a unique session id');
}
const temporaryRoot = await mkdtemp(join(tmpdir(), 'maka-session-bundle-measure-'));
try {
const workspaceMeasurements = await Promise.all(
workspaceRoots.map(async (root) => ({ root, stats: await measureWorkspace(root) })),
);
const workspaceByRoot = new Map(
workspaceMeasurements.map((measurement) => [measurement.root, measurement]),
);
const sharedWorkspaceEntries = workspaceRoots.length === 1 ? new Map() : undefined;
const measuredSourceRoots =
exportRoots.length > 0 ? sourceRoots : [await createBootstrapSmokeExport(temporaryRoot)];
const measuredWorkspaceRoots =
workspaceRoots.length === 1
? Array.from({ length: iterations }, () => workspaceRoots[0])
: workspaceRoots.slice(0, iterations);
const samples = [];
for (let index = 0; index < iterations; index += 1) {
const sampleRoot = join(temporaryRoot, `sample-${String(index + 1).padStart(3, '0')}`);
const stateRoot = join(sampleRoot, 'state');
const sourceRoot = measuredSourceRoots[index];
const workspaceMeasurement = workspaceByRoot.get(measuredWorkspaceRoots[index]);
if (!workspaceMeasurement) throw new Error('missing workspace measurement for sample');
let workspaceEntries = sharedWorkspaceEntries?.get(workspaceMeasurement.root);
if (!workspaceEntries) {
workspaceEntries = await readTreeEntries(workspaceMeasurement.root, {
excludeWorkspaceDirectories: true,
});
sharedWorkspaceEntries?.set(workspaceMeasurement.root, workspaceEntries);
}
await prepareStateExport(sourceRoot, stateRoot, sourceSessionIds[index]);
const archivePath = join(sampleRoot, 'session-bundle.tar.zst');
const archive = await createBundleArchive({
stateRoot,
workspaceEntries,
archivePath,
});
const hydrateSamples = [];
const bootSamplesForSample = [];
for (let repeat = 0; repeat < bootSamples; repeat += 1) {
hydrateSamples.push(await measureHydrate(archivePath));
bootSamplesForSample.push(await measureBoot(archivePath));
}
samples.push({
id: archive.sessionId,
source: exportRoots[index] ? 'sanitized-real-session-export' : 'fake-bootstrap-smoke',
rawStateBytes: archive.rawStateBytes,
rawTarBytes: archive.rawTarBytes,
compressedBytes: archive.compressedBytes,
hydrateMs: percentileStats(hydrateSamples),
freshProcessBootstrapMs: percentileStats(bootSamplesForSample),
hydrateSamples,
bootSamples: bootSamplesForSample,
workspace: workspaceReport(workspaceMeasurement),
});
}
const evidenceKind =
exportRoots.length > 0 ? 'sanitized-real-session-exports' : 'fake-bootstrap-smoke-only';
const report = {
schemaVersion: BUNDLE_SCHEMA_VERSION,
measuredAt: new Date().toISOString(),
node: process.version,
evidence: {
kind: evidenceKind,
sampleCount: samples.length,
bundleSizeDecisionReady: isDecisionReady(
evidenceKind,
samples.length,
workspaceRoots.length,
exportRoots.length,
),
bootstrapLatencyDecisionReady: isBootstrapDecisionReady(options['runtime-build-id']),
decisionReady:
isDecisionReady(
evidenceKind,
samples.length,
workspaceRoots.length,
exportRoots.length,
) && isBootstrapDecisionReady(options['runtime-build-id']),
runtime: {
node: process.version,
platform: process.platform,
arch: process.arch,
buildIdentity: options['runtime-build-id'] ?? null,
},
decisionReadyMinSamples: DECISION_READY_MIN_SAMPLES,
sourceCount: exportRoots.length,
workspaceCount: workspaceRoots.length,
workspacePairing:
exportRoots.length === 0
? 'smoke'
: workspaceRoots.length === 1 && exportRoots.length > 1
? 'shared'
: 'one-to-one',
note:
exportRoots.length > 0
? 'Session exports are expected to be sanitized before measurement; JSON text receives a defense-in-depth redaction pass.'
: 'This run exercises the archive and bootstrap smoke path only. It is not evidence from real coding sessions and must not be used to set a capacity or latency SLO.',
},
archive: {
format: 'tar.zst',
schemaVersion: BUNDLE_SCHEMA_VERSION,
layout: ['manifest.json', 'state/**', 'workspace/**'],
rawTarBytes: statsFor(samples.map((sample) => sample.rawTarBytes)),
zstdBytes: statsFor(samples.map((sample) => sample.compressedBytes.zstd)),
},
workspace: buildWorkspaceReport(workspaceMeasurements),
samples: samples.map((sample) => ({
id: sample.id,
source: sample.source,
rawStateBytes: sample.rawStateBytes,
rawTarBytes: sample.rawTarBytes,
compressedBytes: sample.compressedBytes,
hydrateMs: sample.hydrateMs,
freshProcessBootstrapMs: sample.freshProcessBootstrapMs,
workspace: sample.workspace,
})),
coldStart: {
providerTtfbMs: providerTtfbMs ?? null,
providerTtfbSource:
providerTtfbMs === undefined
? 'not supplied; planning estimate omitted'
: 'explicit CLI input; planning assumption, not a live provider measurement',
hydrateMs: statsFor(samples.flatMap((sample) => sample.hydrateSamples)),
freshProcessBootstrapMs: statsFor(samples.flatMap((sample) => sample.bootSamples)),
...(providerTtfbMs === undefined
? {}
: {
planningEstimateFirstTokenMs: statsFor(
samples.flatMap((sample) =>
sample.bootSamples.map((duration) => duration + providerTtfbMs),
),
),
}),
},
notes: [
'The archive is a real POSIX tar stream compressed with Node native Zstandard.',
'Fresh-process bootstrap extracts the archive, reads the materialized storage, rebases restored paths, constructs the Harbor cell runtime, and records local readiness before FakeBackend latency while still validating clean turn completion.',
'The provider TTFB input and any budget derived from it are assumptions; this command does not measure provider latency.',
],
};
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
} finally {
await rm(temporaryRoot, { recursive: true, force: true });
}
}
function pathsOverlap(left, right) {
return pathIsAtOrInside(left, right) || pathIsAtOrInside(right, left);
}
function pathIsAtOrInside(root, candidate) {
const path = relative(root, candidate);
return path === '' || (path !== '..' && !path.startsWith(`..${sep}`) && !isAbsolute(path));
}
async function createBootstrapSmokeExport(temporaryRoot) {
const rawStorageRoot = join(temporaryRoot, 'smoke-storage-raw');
const storageRoot = join(temporaryRoot, 'smoke-storage');
const outputDir = join(temporaryRoot, 'smoke-output');
const workspaceDir = join(temporaryRoot, 'smoke-workspace');
await mkdir(workspaceDir, { recursive: true });
let runHarborCell;
try {
({ runHarborCell } = await import(pathToFileURL(HARBOR_CELL_MODULE).href));
} catch (error) {
throw new Error(
`The real bootstrap smoke path requires built headless artifacts at ${HARBOR_CELL_MODULE}; run the workspace build first (${error instanceof Error ? error.message : String(error)})`,
);
}
const result = await runHarborCell({
config: {
id: 'session-bundle-measurement-smoke',
backend: 'fake',
llmConnectionSlug: 'fixture',
model: 'fixture-model',
},
instruction: 'Inspect the fixture workspace and report one safe improvement.',
cwd: workspaceDir,
outputDir,
storageRoot: rawStorageRoot,
});
if (result.invocation.status !== 'completed') {
throw new Error(`bootstrap smoke run did not complete: ${result.invocation.status}`);
}
const { exportSessionBundleState } = await import('@maka/storage');
await exportSessionBundleState({
stateRoot: rawStorageRoot,
configRoot: rawStorageRoot,
destinationRoot: storageRoot,
sessionId: result.invocation.sessionId,
allowShared: true,
});
return storageRoot;
}
async function prepareStateExport(sourceRoot, destinationRoot, expectedSessionId) {
const source = resolve(sourceRoot);
const sourceStats = await stat(source).catch(() => undefined);
if (!sourceStats?.isDirectory()) throw new Error(`session export is not a directory: ${source}`);
const entries = await readTreeEntries(source);
const sessionId = findSessionId(entries);
if (expectedSessionId !== undefined && expectedSessionId !== sessionId) {
throw new Error(`session export identity changed while preparing: ${source}`);
}
await validateStateExportEntries(source, entries, sessionId);
if (!entries.some((entry) => entry.path.startsWith('sessions/'))) {
throw new Error(`session export has no sessions/** tree: ${source}`);
}
for (const entry of entries) {
if (entry.path === STORAGE_ROOT_AUTHORITY_MARKER) continue;
const destination = join(destinationRoot, entry.path);
await mkdir(dirname(destination), { recursive: true });
if (isJsonTextPath(entry.path)) {
await sanitizeJsonFile(entry.sourcePath, destination);
} else {
await pipeline(createReadStream(entry.sourcePath), createWriteStream(destination));
}
}
}
async function validateStateExportEntries(sourceRoot, entries, sessionId) {
for (const entry of entries) {
if (entry.path === STORAGE_ROOT_AUTHORITY_MARKER) continue;
const [topLevel, child] = entry.path.split('/');
if (!PORTABLE_STATE_TOP_LEVEL.has(topLevel)) {
throw new Error(
`session export contains protected or unclassified state entry: ${entry.path}`,
);
}
if (topLevel === 'sessions') {
const sessionPrefix = `sessions/${sessionId}/`;
if (entry.path === `sessions/${sessionId}/session.jsonl`) continue;
if (!entry.path.startsWith(sessionPrefix)) {
throw new Error(`session export contains unfiltered session entry: ${entry.path}`);
}
const relativePath = entry.path.slice(sessionPrefix.length);
const firstSegment = relativePath.split('/')[0];
if (
(relativePath.includes('/') && PORTABLE_SESSION_DIRECTORIES.has(firstSegment)) ||
PORTABLE_SESSION_FILES.has(relativePath)
) {
continue;
}
throw new Error(
`session export contains protected or unclassified session entry: ${entry.path}`,
);
}
if (topLevel === 'runtime.sqlite') {
if (entry.path !== 'runtime.sqlite') {
throw new Error(
`session export contains protected or unclassified state entry: ${entry.path}`,
);
}
continue;
}
if (topLevel !== 'artifacts') continue;
if (entry.path === 'artifacts/metadata.jsonl') {
await validateArtifactMetadata(sourceRoot, entry, sessionId);
continue;
}
if (child !== sessionId || !entry.path.startsWith(`artifacts/${sessionId}/`)) {
throw new Error(`session export contains unfiltered artifact entry: ${entry.path}`);
}
}
}
async function validateArtifactMetadata(sourceRoot, entry, sessionId) {
const text = await readFile(join(sourceRoot, entry.path), 'utf8');
for (const [index, line] of text.split('\n').entries()) {
if (!line.trim()) continue;
let record;
try {
record = JSON.parse(line);
} catch (error) {
throw new Error(`artifact metadata is invalid JSON at line ${index + 1}`, { cause: error });
}
if (
!record ||
record.sessionId !== sessionId ||
typeof record.relativePath !== 'string' ||
!isArtifactPathForSession(record.relativePath, sessionId)
) {
throw new Error(`session export contains unfiltered artifact metadata at line ${index + 1}`);
}
}
}
async function createBundleArchive({ stateRoot, workspaceEntries, archivePath }) {
const stateEntries = await readTreeEntries(stateRoot);
const sessionId = findSessionId(stateEntries);
const files = [
...stateEntries.map((entry) => ({ ...entry, path: `state/${entry.path}` })),
...workspaceEntries.map((entry) => ({ ...entry, path: `workspace/${entry.path}` })),
].sort((a, b) => a.path.localeCompare(b.path));
const manifest = {
schemaVersion: BUNDLE_SCHEMA_VERSION,
format: 'maka-session-bundle',
sessionId,
stateRoot: 'state',
workspaceRoot: 'workspace',
files: await hashManifestFiles(files),
};
await mkdir(dirname(archivePath), { recursive: true });
const tarPath = `${archivePath}.raw-tar`;
try {
await writeTarFile(tarPath, [
{ path: 'manifest.json', bytes: Buffer.from(`${JSON.stringify(manifest)}\n`) },
...files,
]);
const rawTarBytes = (await stat(tarPath)).size;
const [gzip, brotli] = await Promise.all([
compressedStreamSize(tarPath, createGzip({ level: 6 })),
compressedStreamSize(
tarPath,
createBrotliCompress({
params: { [zlibConstants.BROTLI_PARAM_QUALITY]: 4 },
}),
),
]);
await pipeline(
createReadStream(tarPath),
createZstdCompress({
params: { [zlibConstants.ZSTD_c_compressionLevel]: 3 },
}),
createWriteStream(archivePath, { flags: 'wx' }),
);
const zstd = (await stat(archivePath)).size;
const decompressedBytes = await compressedStreamSize(archivePath, createZstdDecompress());
if (decompressedBytes !== rawTarBytes) {
throw new Error('Zstandard round-trip changed the tar byte count');
}
return {
sessionId,
rawStateBytes: stateEntries.reduce((total, entry) => total + entry.bytes, 0),
rawTarBytes,
compressedBytes: { gzip, brotli, zstd },
};
} finally {
await rm(tarPath, { force: true });
}
}
export async function hashManifestFiles(files, hash = hashFile) {
const records = [];
for (const file of files) {
records.push({
path: file.path,
bytes: file.bytes,
sha256: await hash(file.sourcePath),
});
}
return records;
}
async function measureHydrate(archivePath) {
const destination = await mkdtemp(join(tmpdir(), 'maka-session-bundle-hydrate-'));
const start = performance.now();
try {
const manifest = await extractTarZst(archivePath, destination);
await validateMaterializedBundle(destination, manifest);
return performance.now() - start;
} finally {
await rm(destination, { recursive: true, force: true });
}
}
function measureBoot(archivePath) {
return measureChildReady(process.execPath, [SCRIPT_PATH, '--child-bootstrap', archivePath], {
cwd: REPO_ROOT,
});
}
export function measureChildReady(command, args, options = {}) {
return new Promise((resolvePromise, reject) => {
const start = performance.now();
const child = spawn(command, args, {
stdio: ['ignore', 'pipe', 'pipe'],
cwd: options.cwd,
env: options.env,
});
let stdout = '';
let stderr = '';
let readyMs;
child.stdout.on('data', (chunk) => {
stdout += chunk;
if (readyMs === undefined && stdout.startsWith('ready\n')) {
readyMs = performance.now() - start;
}
});
child.stderr.on('data', (chunk) => {
stderr += chunk;
});
child.once('error', reject);
child.once('exit', (code, signal) => {
if (code === 0 && stdout === 'ready\n' && readyMs !== undefined) {
resolvePromise(readyMs);
} else {
reject(
new Error(
`bootstrap child exited with ${code ?? signal} before a valid ready signal: ${stderr}`,
),
);
}
});
});
}
async function childBootstrap(archivePath) {
if (!archivePath) throw new Error('--child-bootstrap requires an archive path');
const destination = await mkdtemp(join(tmpdir(), 'maka-session-bundle-bootstrap-'));
try {
const manifest = await extractTarZst(archivePath, destination);
await validateMaterializedBundle(destination, manifest);
const [{ runHarborCellWithStorage }, { openHeadlessStorageForWrite }] = await Promise.all([
import(pathToFileURL(HARBOR_CELL_MODULE).href),
import(pathToFileURL(HEADLESS_STORAGE_MODULE).href),
]);
const storageRoot = join(destination, 'state');
const workspaceDir = join(destination, 'workspace');
const storage = await openHeadlessStorageForWrite(storageRoot);
try {
const sessions = await storage.executionStores.sessionStore.listForRecovery();
if (sessions.length !== 1 || sessions[0].id !== manifest.sessionId) {
throw new Error('materialized bundle must contain exactly the manifest session');
}
const session = sessions[0];
await storage.executionStores.sessionStore.updateHeader(session.id, {
workspaceRoot: storageRoot,
cwd: workspaceDir,
backend: 'fake',
llmConnectionSlug: 'fixture',
model: 'fixture-model',
permissionMode: 'execute',
});
const rebasedSession = await storage.executionStores.sessionStore.readHeaderSnapshot(
session.id,
);
if (rebasedSession.workspaceRoot !== storageRoot || rebasedSession.cwd !== workspaceDir) {
throw new Error('restored session paths were not rebased to the materialized bundle');
}
const result = await runHarborCellWithStorage(
{
config: {
id: 'session-bundle-bootstrap-probe',
backend: 'fake',
llmConnectionSlug: 'fixture',
model: 'fixture-model',
...(rebasedSession.thinkingLevel
? { thinkingLevel: rebasedSession.thinkingLevel }
: {}),
},
instruction: 'bootstrap probe',
cwd: workspaceDir,
outputDir: join(destination, 'bootstrap-output'),
storageRoot,
resumeSessionId: session.id,
onRunStarted: () => {
process.stdout.write('ready\n');
},
},
storage,
);
if (result.invocation.status !== 'completed') {
throw new Error(`bootstrap probe did not complete: ${result.invocation.status}`);
}
const after = await storage.executionStores.sessionStore.listForRecovery();
if (after.length !== 1 || after[0].id !== session.id) {
throw new Error('bootstrap created an unrelated session instead of restoring the export');
}
} finally {
await storage.executionStores.sessionStore.close();
}
} finally {
await rm(destination, { recursive: true, force: true });
}
}
async function extractTarZst(archivePath, destination) {
const tarPath = join(destination, '.session-bundle.raw-tar');
const files = [];
try {
await pipeline(
createReadStream(archivePath),
createZstdDecompress(),
createWriteStream(tarPath, { flags: 'wx' }),
);
const tarStats = await stat(tarPath);
if (tarStats.size < 1024) throw new Error('archive is not a POSIX ustar tar.zst');
const handle = await open(tarPath, 'r');
try {
let offset = 0;
while (offset + 512 <= tarStats.size) {
const header = Buffer.alloc(512);
const { bytesRead } = await handle.read(header, 0, header.length, offset);
if (bytesRead !== header.length) throw new Error('truncated tar header');
if (header.every((byte) => byte === 0)) break;
if (header.subarray(257, 262).toString('ascii') !== 'ustar') {
throw new Error('archive is not a POSIX ustar tar.zst');
}
const name = readTarString(header, 0, 100);
const prefix = readTarString(header, 345, 155);
const path = prefix ? `${prefix}/${name}` : name;
const size = parseTarOctal(header.subarray(124, 136));
const type = header[156];
if (!path || type !== 0) throw new Error(`unsupported tar entry: ${path}`);
assertSafeArchivePath(path);
const bodyStart = offset + 512;
const bodyEnd = bodyStart + size;
if (bodyEnd > tarStats.size) throw new Error(`truncated tar entry: ${path}`);
const destinationPath = join(destination, path);
await mkdir(dirname(destinationPath), { recursive: true });
if (size === 0) await writeFile(destinationPath, Buffer.alloc(0), { flag: 'wx' });
else {
await pipeline(
createReadStream(tarPath, { start: bodyStart, end: bodyEnd - 1 }),
createWriteStream(destinationPath, { flags: 'wx' }),
);
}
files.push({ path, bytes: size });
offset = bodyStart + Math.ceil(size / 512) * 512;
}
} finally {
await handle.close();
}
} finally {
await rm(tarPath, { force: true });
}
const manifest = JSON.parse(await readFile(join(destination, 'manifest.json'), 'utf8'));
if (
manifest.schemaVersion !== BUNDLE_SCHEMA_VERSION ||
manifest.format !== 'maka-session-bundle'
) {
throw new Error('unsupported session bundle manifest');
}
validateManifest(manifest);
await mkdir(join(destination, manifest.stateRoot), { recursive: true });
await mkdir(join(destination, manifest.workspaceRoot), { recursive: true });
const archivePathSet = new Set();
for (const file of files) {
if (archivePathSet.has(file.path)) throw new Error(`duplicate archive entry: ${file.path}`);
archivePathSet.add(file.path);
}
const manifestPaths = new Set(manifest.files.map((file) => file.path));
const archivePaths = files
.filter((file) => file.path !== 'manifest.json')
.map((file) => file.path);
if (
archivePaths.length !== manifestPaths.size ||
archivePaths.some((path) => !manifestPaths.has(path))
) {
throw new Error('manifest does not exactly match archive entries');
}
return manifest;
}
async function validateMaterializedBundle(destination, manifest) {
validateManifest(manifest);
const stateRoot = join(destination, manifest.stateRoot);
const workspaceRoot = join(destination, manifest.workspaceRoot);
const sessionPath = join(stateRoot, 'sessions', manifest.sessionId, 'session.jsonl');
await stat(sessionPath);
await stat(workspaceRoot);
for (const file of manifest.files) {
const path = join(destination, file.path);
const bytes = (await stat(path)).size;
if (bytes !== file.bytes) throw new Error(`bundle byte count mismatch: ${file.path}`);
const digest = await hashFile(path);
if (digest !== file.sha256) throw new Error(`bundle digest mismatch: ${file.path}`);
}
}
async function measureWorkspace(root) {
const categories = { git: 0, nodeModules: 0, sensitive: 0, portableWorkspace: 0 };
let archivedPortableRawBytes = 0;
await walkFiles(root, async (path, relativePath) => {
const bytes = (await stat(path)).size;
const category = excludedWorkspaceCategory(relativePath);
if (category === 'git') categories.git += bytes;
else if (category === 'nodeModules') categories.nodeModules += bytes;
else if (category === 'sensitive') categories.sensitive += bytes;
else {
categories.portableWorkspace += bytes;
archivedPortableRawBytes += bytes;
}
});
return {
rawBytes:
categories.git + categories.nodeModules + categories.sensitive + categories.portableWorkspace,
categories,
archivedPortableRawBytes,
};
}
function workspaceReport(measurement) {
return {
root: measurement.root,
...measurement.stats,
archivedPortableRawBytes: measurement.stats.archivedPortableRawBytes,
};
}
function buildWorkspaceReport(measurements) {
const reports = measurements.map(workspaceReport);
if (reports.length === 1) return reports[0];
return {
mode: 'paired',
samples: reports,
aggregate: {
rawBytes: reports.reduce((total, report) => total + report.rawBytes, 0),
categories: Object.fromEntries(
Object.keys(reports[0].categories).map((category) => [
category,
reports.reduce((total, report) => total + report.categories[category], 0),
]),
),
archivedPortableRawBytes: reports.reduce(
(total, report) => total + report.archivedPortableRawBytes,
0,
),
},
};
}
async function readTreeEntries(root, options = {}) {
const files = [];
await walkFiles(root, async (path, relativePath) => {
if (options.excludeWorkspaceDirectories && excludedWorkspaceCategory(relativePath)) return;
files.push({ path: relativePath, sourcePath: path, bytes: (await stat(path)).size });
});
files.sort((a, b) => a.path.localeCompare(b.path));
return files;
}
async function readSessionExportId(root) {
const sessionsRoot = join(root, 'sessions');
const entries = await readdir(sessionsRoot, { withFileTypes: true }).catch(() => []);
const sessionIds = [];
for (const entry of entries) {
if (!entry.isDirectory()) continue;
const sessionPath = join(sessionsRoot, entry.name, 'session.jsonl');
const sessionStats = await stat(sessionPath).catch(() => undefined);
if (sessionStats?.isFile()) sessionIds.push(entry.name);
}
if (sessionIds.length === 0)
throw new Error('state export must contain sessions/<id>/session.jsonl');
if (sessionIds.length !== 1)
throw new Error('each session export must contain exactly one sessions/<id>/session.jsonl');
return sessionIds[0];
}
async function walkFiles(root, onFile, current = root) {
const entries = await readdir(current, { withFileTypes: true });
for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
const path = join(current, entry.name);
const platformRelativePath = relative(root, path);
if (sep !== '\\' && platformRelativePath.includes('\\')) {
throw new Error('workspace/session export contains unsupported backslash path');
}
const relativePath =
sep === '\\' ? platformRelativePath.split(sep).join('/') : platformRelativePath;
if (entry.isSymbolicLink()) continue;
if (entry.isDirectory()) await walkFiles(root, onFile, path);
else if (entry.isFile()) await onFile(path, relativePath);
}
}
function excludedWorkspaceCategory(relativePath) {
const segments = relativePath.split('/');
if (segments.some((segment) => segment === '.git')) return 'git';
if (
segments.some(
(segment) => EXCLUDED_WORKSPACE_SEGMENTS.has(segment) && segment === 'node_modules',
)
) {
return 'nodeModules';
}
const basename = segments.at(-1) ?? '';
if (
(segments.at(-2) === '.docker' && basename === 'config.json') ||
(segments.at(-2) === '.aws' && basename === 'credentials') ||
(segments.at(-2) === '.cargo' && basename === 'credentials') ||
(segments.at(-2) === '.kube' && basename === 'config') ||
(segments.at(-2) === 'gcloud' &&
segments.at(-3) === '.config' &&
basename === 'application_default_credentials.json')
) {
return 'sensitive';
}
if (SENSITIVE_WORKSPACE_FILE_PATTERNS.some((pattern) => pattern.test(basename))) {
return 'sensitive';
}
return undefined;
}
function findSessionId(entries) {
const sessionIds = [
...new Set(
entries.flatMap((entry) => {
const match = /^sessions\/([^/]+)\/session\.jsonl$/.exec(entry.path);
return match ? [match[1]] : [];
}),
),
];
if (sessionIds.length === 0)
throw new Error('state export must contain sessions/<id>/session.jsonl');
if (sessionIds.length !== 1)
throw new Error('each session export must contain exactly one sessions/<id>/session.jsonl');
return sessionIds[0];
}
export function isDecisionReady(
evidenceKind,
sampleCount,
workspaceCount = sampleCount,
sourceCount = sampleCount,
) {
return (
evidenceKind === 'sanitized-real-session-exports' &&
sampleCount >= DECISION_READY_MIN_SAMPLES &&
workspaceCount === sourceCount &&
sourceCount === sampleCount
);
}
export function isBootstrapDecisionReady(
runtimeBuildId,
runtime = { node: process.version, platform: process.platform, arch: process.arch },
) {
return (
runtime.node.startsWith('v24.') &&
runtime.platform === 'linux' &&
(runtime.arch === 'x64' || runtime.arch === 'arm64') &&
typeof runtimeBuildId === 'string' &&
runtimeBuildId.trim().length > 0
);
}
function isJsonTextPath(path) {
return path.endsWith('.json') || path.endsWith('.jsonl');
}
export async function sanitizeJsonFile(path, destination) {
const sourceStats = await stat(path);
if (path.endsWith('.json') && sourceStats.size > MAX_JSON_BYTES) {
throw new Error(`JSON file exceeds maximum size of ${MAX_JSON_BYTES} bytes: ${path}`);
}
if (path.endsWith('.jsonl')) {
const input = createReadStream(path, { encoding: 'utf8' });
const output = createWriteStream(destination, { flags: 'w' });
const closed = new Promise((resolvePromise, reject) => {
output.once('close', resolvePromise);
output.once('error', reject);
});
try {
const lines = createInterface({ input, crlfDelay: Infinity });
for await (const line of lines) {
if (!line.trim()) {
await writeStreamChunk(output, `${line}\n`);
continue;
}
try {
const parsed = JSON.parse(line);
const redacted = redactJson(parsed);
const sanitized = JSON.stringify(redacted);
await writeStreamChunk(
output,
`${!hasDuplicateJsonObjectKeys(line) && sanitized === JSON.stringify(parsed) ? line : sanitized}\n`,
);
} catch {
await writeStreamChunk(output, `${redactText(line)}\n`);
}
}
} finally {
output.end();
await closed;
}
return;
}
const bytes = await readFile(path);
const text = bytes.toString('utf8');
let output = text;
try {
const parsed = JSON.parse(text);
const redacted = redactJson(parsed);
output =
!hasDuplicateJsonObjectKeys(text) && JSON.stringify(redacted) === JSON.stringify(parsed)
? text
: `${JSON.stringify(redacted)}\n`;
} catch {
output = redactText(text);
}
await writeFile(destination, output);
}
function hasDuplicateJsonObjectKeys(text) {
const objectKeys = [];
for (let index = 0; index < text.length; index += 1) {
const character = text[index];
if (character === '"') {
const start = index;
index += 1;
let escaped = false;
for (; index < text.length; index += 1) {
const current = text[index];
if (escaped) escaped = false;
else if (current === '\\') escaped = true;
else if (current === '"') break;
}
const next = text.slice(index + 1).match(/^\s*([:])/u)?.[1];
if (next === ':' && objectKeys.length > 0) {
const key = JSON.parse(text.slice(start, index + 1));
const keys = objectKeys[objectKeys.length - 1];
if (keys.has(key)) return true;
keys.add(key);
}
continue;
}
if (/\s/u.test(character) || character === ':' || character === ',') continue;
if (character === '{') objectKeys.push(new Set());
else if (character === '}' && objectKeys.length > 0) objectKeys.pop();
}
return false;
}
function writeStreamChunk(stream, chunk) {
return new Promise((resolvePromise, reject) => {
if (stream.write(chunk, 'utf8')) resolvePromise();
else {
stream.once('drain', resolvePromise);
stream.once('error', reject);
}
});
}
function redactJson(value) {
if (Array.isArray(value)) return value.map(redactJson);
if (value && typeof value === 'object') {
return Object.fromEntries(
Object.entries(value).map(([key, nested]) => [
key,
isSensitiveKey(key) && !NON_SECRET_KEY_NAMES.has(key) ? '[REDACTED]' : redactJson(nested),
]),
);
}
return typeof value === 'string' ? redactText(value) : value;
}
function isSensitiveKey(key) {
const normalized = key
.replace(/([a-z0-9])([A-Z])/g, '$1_$2')
.replaceAll('-', '_')
.toLowerCase();
const compact = normalized.replaceAll('_', '');
return (
normalized === 'token' ||
normalized.endsWith('_token') ||
SENSITIVE_KEY_PARTS.has(normalized) ||
[...SENSITIVE_KEY_PARTS].some((part) => normalized.endsWith(`_${part}`)) ||
[...SENSITIVE_COMPACT_KEY_PARTS].some((part) => compact.endsWith(part))
);
}
export function redactText(value) {
return SECRET_PATTERNS.reduce(
(current, pattern) =>
current.replace(pattern, (...args) => {
const groups = args.slice(1, -2);
const prefix = groups.find((group) => typeof group === 'string' && /[:=?&\s]$/.test(group));
return `${prefix ?? ''}[REDACTED]`;
}),
value,
);
}
export async function writeTarFile(path, entries, options = {}) {
const { openFile = open, readFileChunks = (sourcePath) => createReadStream(sourcePath) } =
options;
const handle = await openFile(path, 'wx');
let offset = 0;
const write = async (bytes) => {
let written = 0;
while (written < bytes.byteLength) {
const result = await handle.write(
bytes,
written,
bytes.byteLength - written,
offset + written,
);
const bytesWritten = typeof result === 'number' ? result : result?.bytesWritten;
if (
!Number.isInteger(bytesWritten) ||
bytesWritten <= 0 ||
bytesWritten > bytes.byteLength - written
) {
throw new Error(`invalid file write count: ${String(bytesWritten)}`);
}
written += bytesWritten;
}
offset += written;
};
try {
for (const entry of entries) {
assertSafeArchivePath(entry.path);
const size = Buffer.isBuffer(entry.bytes) ? entry.bytes.byteLength : entry.bytes;
const { name, prefix } = splitTarPath(entry.path);
const header = Buffer.alloc(512, 0);
writeTarString(header, 0, 100, name);
writeTarOctal(header, 100, 8, 0o644);
writeTarOctal(header, 108, 8, 0);
writeTarOctal(header, 116, 8, 0);
writeTarOctal(header, 124, 12, size);
writeTarOctal(header, 136, 12, 0);
header.fill(0x20, 148, 156);
header[156] = 0;
writeTarString(header, 257, 6, 'ustar');
writeTarString(header, 263, 2, '00');
writeTarString(header, 345, 155, prefix);
const checksum = header.reduce((total, byte) => total + byte, 0);
writeTarChecksum(header, checksum);
await write(header);
let streamed = 0;
if (Buffer.isBuffer(entry.bytes)) {
await write(entry.bytes);
streamed = entry.bytes.byteLength;
} else {
for await (const chunk of readFileChunks(entry.sourcePath)) {
await write(chunk);
streamed += chunk.byteLength;
}
}
if (streamed !== size) {
throw new Error(
`tar source size changed during streaming for ${entry.path}: expected ${size}, observed ${streamed}`,
);
}
const padding = (512 - (size % 512)) % 512;
if (padding > 0) await write(Buffer.alloc(padding));
}
await write(Buffer.alloc(1024));
} finally {
await handle.close();
}
}
async function hashFile(path) {
const hash = createHash('sha256');
for await (const chunk of createReadStream(path)) hash.update(chunk);
return hash.digest('hex');
}
async function compressedStreamSize(path, transform) {
let bytes = 0;
await pipeline(
createReadStream(path),
transform,
new Writable({
write(chunk, _encoding, callback) {
bytes += chunk.byteLength;
callback();
},
}),
);
return bytes;
}
function splitTarPath(path) {
if (Buffer.byteLength(path) <= 100) return { name: path, prefix: '' };
const slashPositions = [];
for (let index = 0; index < path.length; index += 1) {
if (path[index] === '/') slashPositions.push(index);
}
for (const slash of slashPositions.reverse()) {
const prefix = path.slice(0, slash);
const name = path.slice(slash + 1);
if (Buffer.byteLength(prefix) <= 155 && Buffer.byteLength(name) <= 100) {
return { name, prefix };
}
}
throw new Error(`tar path is too long for ustar prefix/name fields: ${path}`);
}
function writeTarString(buffer, offset, length, value) {
buffer.write(value, offset, length, 'utf8');
}
function writeTarOctal(buffer, offset, length, value) {
const text = Math.floor(value)
.toString(8)
.padStart(length - 1, '0');
buffer.write(`${text}\0`, offset, length, 'ascii');
}
function writeTarChecksum(buffer, value) {
buffer.write(`${value.toString(8).padStart(6, '0')}\0 `, 148, 8, 'ascii');
}
function readTarString(buffer, offset, length) {
return buffer
.subarray(offset, offset + length)
.toString('utf8')
.replace(/\0.*$/, '');
}
function parseTarOctal(buffer) {
const value = buffer.toString('ascii').replace(/\0.*$/, '').trim();
const parsed = value ? Number.parseInt(value, 8) : 0;
if (!Number.isSafeInteger(parsed) || parsed < 0) throw new Error('invalid tar size');
return parsed;
}
function validateManifest(manifest) {
if (!manifest || typeof manifest !== 'object' || Array.isArray(manifest)) {
throw new Error('invalid session bundle manifest');
}
if (
typeof manifest.sessionId !== 'string' ||
!manifest.sessionId ||
manifest.sessionId.includes('/') ||
typeof manifest.stateRoot !== 'string' ||
typeof manifest.workspaceRoot !== 'string' ||
!Array.isArray(manifest.files)
) {
throw new Error('invalid session bundle manifest');
}
assertSafeArchivePath(manifest.stateRoot);
assertSafeArchivePath(manifest.workspaceRoot);
const seen = new Set();
for (const file of manifest.files) {
if (
!file ||
typeof file !== 'object' ||
typeof file.path !== 'string' ||
!Number.isSafeInteger(file.bytes) ||
file.bytes < 0 ||
!/^[0-9a-f]{64}$/.test(file.sha256) ||
file.path === 'manifest.json' ||
seen.has(file.path)
) {
throw new Error('invalid session bundle manifest file');
}
assertSafeArchivePath(file.path);
if (
!file.path.startsWith(`${manifest.stateRoot}/`) &&
!file.path.startsWith(`${manifest.workspaceRoot}/`)
) {
throw new Error(`manifest file outside bundle roots: ${file.path}`);
}
seen.add(file.path);
}
}
function assertSafeArchivePath(path) {
if (
!path ||
path.startsWith('/') ||
path.includes('\\') ||
path.split('/').some((part) => !part || part === '.' || part === '..')
) {
throw new Error(`unsafe archive path: ${path}`);
}
}
function statsFor(values) {
return {
min: round(percentile(values, 0)),
p50: round(percentile(values, 0.5)),
p99: round(percentile(values, 0.99)),
max: round(percentile(values, 1)),
};
}
function percentileStats(values) {
return {
p50: round(percentile(values, 0.5)),
p99: round(percentile(values, 0.99)),
};
}
function percentile(values, probability) {
const sorted = [...values].sort((a, b) => a - b);
if (sorted.length === 0) return 0;
if (probability <= 0) return sorted[0];
if (probability >= 1) return sorted[sorted.length - 1];
return sorted[Math.min(sorted.length - 1, Math.ceil(probability * sorted.length) - 1)];
}
function parseArgs(argv) {
const options = { workspace: [], 'session-export': [] };
for (let index = 0; index < argv.length; index += 1) {
const argument = argv[index];
if (!argument.startsWith('--')) throw new Error(`Unknown argument: ${argument}`);
const key = argument.slice(2);
if (!SUPPORTED_OPTIONS.has(key)) throw new Error(`Unknown option: --${key}`);
if (key === 'help') {
process.stdout.write(
'Usage: node scripts/measure-session-bundle.mjs --workspace PATH [--workspace PATH ...] [--session-export PATH ...] [--iterations N] [--boot-samples N] [--provider-ttfb-ms N] [--runtime-build-id ID]\n',
);
process.exit(0);
}
const value = argv[index + 1];
if (value === undefined || value.startsWith('--'))
throw new Error(`Missing value for --${key}`);
if (key === 'workspace' || key === 'session-export') options[key].push(value);
else options[key] = value;
index += 1;
}
return options;
}
function positiveInteger(value, name) {
const parsed = Number(value);
if (!Number.isInteger(parsed) || parsed < 1)
throw new Error(`--${name} must be a positive integer`);
return parsed;
}
function nonNegativeNumber(value, name) {
const parsed = Number(value);
if (!Number.isFinite(parsed) || parsed < 0) throw new Error(`--${name} must be non-negative`);
return parsed;
}
function round(value) {
return Math.round(value * 100) / 100;
}