@orkestrel/process 0.0.15 → 0.0.16
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/dist/src/core/index.cjs +46 -21
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +14 -14
- package/dist/src/core/index.d.ts +14 -14
- package/dist/src/core/index.js +47 -22
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +345 -314
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +23 -9
- package/dist/src/server/index.d.ts +23 -9
- package/dist/src/server/index.js +345 -315
- package/dist/src/server/index.js.map +1 -1
- package/package.json +16 -16
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["hostPlatform"],"sources":["../../../src/server/cloners.ts","../../../src/server/helpers.ts","../../../src/server/processes/Supervisor.ts","../../../src/server/processes/Process.ts","../../../src/server/processes/ProcessManager.ts","../../../src/server/processes/Session.ts","../../../src/server/factories.ts"],"sourcesContent":["import type { ProcessCommand } from '@src/core'\n\n/**\n * Takes one owned frozen snapshot of a caller's command.\n *\n * @remarks\n * Every public entry point snapshots before it validates, so the object validated is the object\n * spawned. Each property is read exactly once, because reading one runs the caller's own getter: a\n * command whose `file` changes between reads would otherwise validate one executable and spawn\n * another. The argument vector and the environment record are copied and frozen, so a caller\n * mutating either after the call cannot reach the spawn. An absent optional stays absent rather than\n * becoming an explicit `undefined`.\n *\n * @param command - The caller's command, whose properties may be getters\n * @returns A frozen command carrying the values read at this instant\n *\n * @example\n * ```ts\n * snapshotCommand({ file: 'git', arguments: ['status'] }) // { file: 'git', arguments: ['status'] }\n * ```\n */\nexport function snapshotCommand(command: ProcessCommand): ProcessCommand {\n\tconst file = command.file\n\tconst argumentsList = Object.freeze([...command.arguments])\n\tconst sourceEnvironment = command.environment\n\tconst environment =\n\t\tsourceEnvironment === undefined ? undefined : Object.freeze({ ...sourceEnvironment })\n\tconst input = command.input\n\tconst isolated = command.isolated\n\treturn Object.freeze({\n\t\tfile,\n\t\targuments: argumentsList,\n\t\t...(environment === undefined ? {} : { environment }),\n\t\t...(input === undefined ? {} : { input }),\n\t\t...(isolated === undefined ? {} : { isolated }),\n\t})\n}\n","import type { ChildProcessWithoutNullStreams } from 'node:child_process'\nimport type {\n\tDetachOptions,\n\tExecutableOptions,\n\tExecuteInput,\n\tExecuteOptions,\n\tExecuteResult,\n\tExecuteSyncOptions,\n\tProcessCommand,\n\tSpawnInput,\n} from '@src/core'\nimport type { ProcessChildInterface } from './types.js'\nimport { Buffer } from 'node:buffer'\nimport { spawn, spawnSync } from 'node:child_process'\nimport { statSync } from 'node:fs'\nimport { join, posix, win32 } from 'node:path'\nimport { platform as hostPlatform } from 'node:process'\nimport {\n\tboundsOf,\n\tholds,\n\tisError,\n\tisNonEmptyString,\n\tisNonNegativeInteger,\n\tisString,\n} from '@orkestrel/contract'\nimport {\n\tcreateExecuteError,\n\tcreateInvalidError,\n\tPROCESS_CONFIRMATION,\n\tPROCESS_GRACE,\n\tPROCESS_OUTPUT,\n\tPROCESS_PATHEXT,\n\tPROCESS_TIMER,\n\tProcessError,\n} from '@src/core'\nimport { snapshotCommand } from './cloners.js'\n\n/**\n * Trims a buffer to at most `limit` trailing bytes without splitting a UTF-8 sequence.\n *\n * @remarks\n * Keeps the tail — the diagnostic end of a stderr stream. When the cut point lands inside a\n * multibyte sequence, the start advances past the leading continuation bytes so the retained\n * bytes always begin on a code-point boundary.\n *\n * @param bytes - The accumulated bytes\n * @param limit - The maximum retained byte count\n * @returns The trailing bytes, at most `limit` and never starting mid-sequence\n *\n * @example\n * ```ts\n * trimTail(Buffer.from('hello'), 3) // <Buffer 6c 6c 6f>\n * ```\n */\nexport function trimTail(bytes: Uint8Array, limit: number): Buffer {\n\tconst buffer = Buffer.isBuffer(bytes) ? bytes : Buffer.from(bytes)\n\tif (buffer.byteLength <= limit) return buffer\n\tlet start = buffer.byteLength - limit\n\twhile (start < buffer.byteLength) {\n\t\tconst byte = buffer[start]\n\t\tif (byte === undefined || (byte & 0xc0) !== 0x80) break\n\t\tstart += 1\n\t}\n\treturn Buffer.from(buffer.subarray(start))\n}\n\n/**\n * Trims a buffer to at most `limit` leading bytes without splitting a UTF-8 sequence.\n *\n * @remarks\n * Keeps the head — the captured start of a one-shot run's output. The end retreats only when a\n * sequence genuinely spans the cut: the byte at `limit` carries the continuation bit pattern, and a\n * lead byte within the preceding three bytes declares a length that reaches it. The retained bytes\n * then end on a code-point boundary and decode without a replacement character. A byte at `limit`\n * that carries the continuation pattern without such a lead byte is invalid UTF-8 rather than a\n * split sequence, so the full `limit` survives instead of a valid byte being dropped for it.\n *\n * @param bytes - The accumulated bytes\n * @param limit - The maximum retained byte count\n * @returns The leading bytes, at most `limit` and never ending mid-sequence\n *\n * @example\n * ```ts\n * trimHead(Buffer.from('hello'), 3) // <Buffer 68 65 6c>\n * ```\n */\nexport function trimHead(bytes: Uint8Array, limit: number): Buffer {\n\tconst buffer = Buffer.isBuffer(bytes) ? bytes : Buffer.from(bytes)\n\tif (buffer.byteLength <= limit) return buffer\n\tconst excluded = buffer[limit]\n\tif (excluded === undefined || (excluded & 0xc0) !== 0x80)\n\t\treturn Buffer.from(buffer.subarray(0, limit))\n\t// A lead byte opens at most a four-byte sequence, so only the three bytes before the cut can hold\n\t// the lead of a sequence that reaches it.\n\tconst floor = Math.max(0, limit - 3)\n\tlet start = limit - 1\n\twhile (start >= floor) {\n\t\tconst lead = buffer[start]\n\t\tif (lead !== undefined && (lead & 0xc0) !== 0x80) {\n\t\t\tlet span = 1\n\t\t\tif ((lead & 0xe0) === 0xc0) span = 2\n\t\t\telse if ((lead & 0xf0) === 0xe0) span = 3\n\t\t\telse if ((lead & 0xf8) === 0xf0) span = 4\n\t\t\tif (start + span > limit) return Buffer.from(buffer.subarray(0, start))\n\t\t\tbreak\n\t\t}\n\t\tstart -= 1\n\t}\n\treturn Buffer.from(buffer.subarray(0, limit))\n}\n\n/**\n * Bounds one delivered stream chunk to the bytes a capture still has room for.\n *\n * @remarks\n * A chunk that is not a buffer contributes nothing and reports `undefined` rather than throwing,\n * because a stream `data` listener receives an `unknown` payload. The cut is byte-exact and might\n * land inside a multibyte sequence, because {@link buildExecuteResult} performs the single\n * code-point-boundary trim over the whole capture rather than over each chunk. Give the capture one\n * byte more room than its limit, so that final trim can read the first excluded byte and retreat off\n * a split sequence. A chunk that fits its room is returned as the delivered buffer itself rather\n * than a copy, because a capture appending it copies again and never writes through it; a chunk that\n * overruns its room returns a copy of the bytes that fit. Treat the return as read-only either way.\n *\n * @param chunk - The delivered chunk, ignored when it is not a buffer\n * @param room - The bytes the capture still accepts\n * @returns The bytes to retain, or `undefined` when the chunk contributes none\n *\n * @example\n * ```ts\n * captureChunk(Buffer.from('hello'), 3) // <Buffer 68 65 6c>\n * ```\n */\nexport function captureChunk(chunk: unknown, room: number): Buffer | undefined {\n\tif (!Buffer.isBuffer(chunk) || room <= 0) return undefined\n\tif (chunk.byteLength <= room) return chunk\n\treturn Buffer.from(chunk.subarray(0, room))\n}\n\n/**\n * Renders one command into its diagnostic command line.\n *\n * @param command - The executable and its argument vector\n * @returns The space-joined command line, for an {@link ExecuteResult} and error messages\n *\n * @example\n * ```ts\n * formatCommand({ file: 'git', arguments: ['status'] }) // 'git status'\n * ```\n */\nexport function formatCommand(command: ProcessCommand): string {\n\treturn [command.file, ...command.arguments].join(' ')\n}\n\n/**\n * Reads one environment variable under an explicit platform's key rules.\n *\n * @remarks\n * Windows environment keys are case-insensitive, so a merged record can hold `Path` where the\n * caller asks for `PATH`. The exact key is tried first and a folded scan runs only for `win32`.\n *\n * @param environment - The environment record to read\n * @param name - The variable name\n * @param platform - The platform whose key rules apply\n * @returns The value, or `undefined` when the environment declares no such variable\n *\n * @example\n * ```ts\n * readPlatformVariable({ Path: 'C:\\\\Windows' }, 'PATH', 'win32') // 'C:\\\\Windows'\n * ```\n */\nexport function readPlatformVariable(\n\tenvironment: Readonly<Record<string, string | undefined>>,\n\tname: string,\n\tplatform: NodeJS.Platform,\n): string | undefined {\n\tconst direct = environment[name]\n\tif (direct !== undefined) return direct\n\tif (platform !== 'win32') return undefined\n\tconst target = name.toUpperCase()\n\tfor (const [key, value] of Object.entries(environment)) {\n\t\tif (key.toUpperCase() === target) return value\n\t}\n\treturn undefined\n}\n\n/**\n * Reads one environment variable the way the current host resolves it.\n *\n * @param environment - The environment record to read\n * @param name - The variable name\n * @returns The value, or `undefined` when the environment declares no such variable\n *\n * @example\n * ```ts\n * readVariable({ PATH: '/usr/bin' }, 'PATH') // '/usr/bin'\n * ```\n */\nexport function readVariable(\n\tenvironment: Readonly<Record<string, string | undefined>>,\n\tname: string,\n): string | undefined {\n\treturn readPlatformVariable(environment, name, hostPlatform)\n}\n\n/**\n * Merges environment layers under an explicit platform's key rules.\n *\n * @remarks\n * Later maps override earlier ones and an `undefined` value unsets a key. For `win32` the keys fold\n * case-insensitively and the last writer wins, so `PATH` followed by `Path` yields one variable\n * rather than two the host would resolve unpredictably.\n *\n * @param platform - The platform whose key rules apply\n * @param parent - The parent environment layer\n * @param isolated - If `true`, the parent environment is excluded; if `false`, the overrides layer over it\n * @param base - The command's own environment overrides\n * @param override - Per-invocation overrides applied last\n * @returns The environment for a spawn, carrying no unset key\n *\n * @example\n * ```ts\n * mergePlatformEnvironment('linux', {}, false, { TOKEN: 'a' }, { TOKEN: undefined }) // TOKEN unset\n * ```\n */\nexport function mergePlatformEnvironment(\n\tplatform: NodeJS.Platform,\n\tparent: Readonly<Record<string, string | undefined>>,\n\tisolated: boolean,\n\tbase?: Readonly<Record<string, string | undefined>>,\n\toverride?: Readonly<Record<string, string | undefined>>,\n): NodeJS.ProcessEnv {\n\tconst folded = platform === 'win32'\n\tconst layers: ReadonlyArray<Readonly<Record<string, string | undefined>>> = [\n\t\tisolated ? {} : parent,\n\t\tbase ?? {},\n\t\toverride ?? {},\n\t]\n\tconst entries = new Map<string, readonly [key: string, value: string]>()\n\tfor (const layer of layers) {\n\t\tfor (const [key, value] of Object.entries(layer)) {\n\t\t\tconst token = folded ? key.toUpperCase() : key\n\t\t\tif (value === undefined) {\n\t\t\t\tentries.delete(token)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tentries.set(token, [key, value])\n\t\t}\n\t}\n\tconst merged: NodeJS.ProcessEnv = {}\n\tfor (const [key, value] of entries.values()) merged[key] = value\n\treturn merged\n}\n\n/**\n * Merges environment overrides into the environment one child receives on the current host.\n *\n * @param isolated - If `true`, the parent environment is excluded; if `false`, the overrides layer over it\n * @param base - The command's own environment overrides\n * @param override - Per-invocation overrides applied last\n * @returns The environment for a spawn, carrying no unset key\n *\n * @example\n * ```ts\n * mergeEnvironment(true, { TOKEN: 'a' }) // { TOKEN: 'a' }\n * ```\n */\nexport function mergeEnvironment(\n\tisolated: boolean,\n\tbase?: Readonly<Record<string, string | undefined>>,\n\toverride?: Readonly<Record<string, string | undefined>>,\n): NodeJS.ProcessEnv {\n\treturn mergePlatformEnvironment(hostPlatform, process.env, isolated, base, override)\n}\n\n/**\n * Checks whether a path names a regular file.\n *\n * @remarks\n * Existence alone does not make a lookup hit: a directory named `git` on `PATH` is not the `git`\n * command. An unreadable or malformed path reports `false` rather than throwing.\n *\n * @param target - The absolute or relative path to inspect\n * @returns True if the path resolves to a regular file; false otherwise\n *\n * @example\n * ```ts\n * isFile(process.execPath) // true\n * ```\n */\nexport function isFile(target: string): boolean {\n\treturn holds(() => statSync(target, { throwIfNoEntry: false })?.isFile() === true)\n}\n\n/**\n * Builds the executable candidates an explicit platform would search.\n *\n * @remarks\n * Windows alone needs this list: the host searches the working directory before `PATH` and applies\n * `PATHEXT`, and Node reproduces neither for a direct spawn. Within each searched directory,\n * {@link buildExecutableCandidates} enumerates `PATHEXT` candidates for an extensionless name. For\n * an extension-bearing name, it enumerates the literal path before `PATHEXT` candidates, so\n * `report.txt` resolves to a `report.txt` file where one exists and to `report.txt.cmd` where none\n * does. The lookup reads the child's effective environment, so an overridden `PATH` selects the\n * executable the child would have found. A POSIX host resolves the file itself, so the candidate\n * list there is empty. A `PATHEXT` candidate keeps the extension spelling from `PATHEXT`, which the\n * case-insensitive host treats as the same file. A non-Windows platform returns an empty list\n * because `execvp` performs its own lookup.\n *\n * @param file - The command executable name or path\n * @param workspace - The directory searched first\n * @param environment - The child's effective environment\n * @param platform - The platform whose lookup rules apply\n * @returns The ordered absolute candidate paths\n *\n * @example\n * ```ts\n * buildExecutableCandidates('git', 'C:\\\\work', { PATH: 'C:\\\\bin' }, 'win32')\n * ```\n */\nexport function buildExecutableCandidates(\n\tfile: string,\n\tworkspace: string,\n\tenvironment: Readonly<Record<string, string | undefined>>,\n\tplatform: NodeJS.Platform,\n): readonly string[] {\n\tif (platform !== 'win32') return Object.freeze([])\n\tconst extensions = (readPlatformVariable(environment, 'PATHEXT', platform) ?? PROCESS_PATHEXT)\n\t\t.split(';')\n\t\t.filter((extension) => extension.length > 0)\n\tconst candidates =\n\t\twin32.extname(file).length === 0\n\t\t\t? extensions.map((extension) => `${file}${extension}`)\n\t\t\t: [file, ...extensions.map((extension) => `${file}${extension}`)]\n\tconst rooted = file.includes('/') || file.includes('\\\\')\n\tconst directories = rooted\n\t\t? [workspace]\n\t\t: [workspace, ...(readPlatformVariable(environment, 'PATH', platform) ?? '').split(';')]\n\tconst targets: string[] = []\n\tfor (const directory of directories) {\n\t\tif (directory.length === 0) continue\n\t\tfor (const candidate of candidates) {\n\t\t\ttargets.push(win32.resolve(directory, candidate))\n\t\t}\n\t}\n\treturn Object.freeze(targets)\n}\n\n/**\n * Resolves a command file to the executable path the host would launch, or to `undefined` on a POSIX\n * host, which performs its own lookup.\n *\n * @remarks\n * A Windows lookup miss also returns `undefined`. {@link buildSpawn} preserves the command file as\n * written for native spawning.\n *\n * @param file - The command executable name or path\n * @param options - The directory searched first and the child's effective environment\n * @returns The resolved absolute path, or `undefined` when no candidate is a regular file\n *\n * @example\n * ```ts\n * resolveExecutable('git', {}) ?? 'git' // an absolute path on Windows, 'git' elsewhere\n * ```\n */\nexport function resolveExecutable(file: string, options?: ExecutableOptions): string | undefined {\n\tconst environment = options?.environment ?? process.env\n\tconst workspace = options?.workspace ?? process.cwd()\n\tconst candidates = buildExecutableCandidates(file, workspace, environment, hostPlatform)\n\tfor (const target of candidates) {\n\t\tif (isFile(target)) return target\n\t}\n\treturn undefined\n}\n\n/**\n * Quotes one command-line token for a `cmd.exe` command line.\n *\n * @remarks\n * A token carrying whitespace or a shell metacharacter is wrapped in double quotes so `cmd.exe`\n * passes it as one literal argument; an embedded double quote is doubled, which is how `cmd.exe`\n * reads a literal quote inside a quoted token. The quoted set includes `%`, although quoting cannot\n * stop `cmd.exe` expansion; {@link buildSpawn} therefore refuses `%` in an argument to a Windows\n * batch target.\n *\n * @param value - The token to quote\n * @returns The token, quoted only when `cmd.exe` would otherwise split or interpret it\n *\n * @example\n * ```ts\n * quoteArgument('a&b') // '\"a&b\"'\n * ```\n */\nexport function quoteArgument(value: string): string {\n\tif (value.length > 0 && !/[\\s\"&|<>^()%!]/.test(value)) return value\n\treturn `\"${value.replaceAll('\"', '\"\"')}\"`\n}\n\n/**\n * Builds a spawn form from a resolved file and an explicit platform.\n *\n * @remarks\n * A resolved `.cmd` or `.bat` script cannot be spawned directly **on Windows**, so it runs there\n * through an explicitly quoted `cmd.exe /d /s /c` command line with the argument vector passed\n * verbatim. No path uses a shell, so a metacharacter in an argument is never interpreted. `cmd.exe`\n * expands `%NAME%` before it parses quotes, so no quoting can carry a percent sign through to a\n * Windows batch target: an argument carrying one is refused there rather than silently rewritten.\n * The whole batch path is Windows-only. A POSIX host has no `cmd.exe` and no restriction on spawning\n * a file directly, so a target named `worker.cmd` spawns directly there and receives a percent sign\n * as literal text.\n *\n * @param command - The executable and its argument vector\n * @param file - The resolved executable file\n * @param environment - The child's effective environment\n * @param platform - The platform whose batch rules apply\n * @returns The file, argument vector, and verbatim flag to spawn with\n * @throws A {@link ProcessError} coded `invalid` when `platform` is `win32`, the resolved target is a batch script, and an argument carries a percent sign\n *\n * @example\n * ```ts\n * buildPlatformSpawn({ file: 'node', arguments: ['--version'] }, 'node', {}, 'linux').verbatim // false\n * ```\n */\nexport function buildPlatformSpawn(\n\tcommand: ProcessCommand,\n\tfile: string,\n\tenvironment: Readonly<Record<string, string | undefined>>,\n\tplatform: NodeJS.Platform,\n): SpawnInput {\n\tconst extension = (platform === 'win32' ? win32.extname(file) : posix.extname(file)).toLowerCase()\n\t// Windows alone cannot spawn a batch script directly, and `cmd.exe` is what expands `%NAME%`.\n\t// A POSIX host has neither restriction, so a file whose name ends in `.cmd` is an ordinary\n\t// executable there and its extension changes nothing about how it spawns.\n\tconst batch = platform === 'win32' && (extension === '.cmd' || extension === '.bat')\n\tif (!batch) {\n\t\treturn Object.freeze({\n\t\t\tfile,\n\t\t\targuments: Object.freeze([...command.arguments]),\n\t\t\tverbatim: false,\n\t\t})\n\t}\n\tfor (const argument of command.arguments) {\n\t\tif (argument.includes('%')) throw createInvalidError('command argument', argument)\n\t}\n\tconst line = [`\"${file}\"`, ...command.arguments.map(quoteArgument)].join(' ')\n\treturn Object.freeze({\n\t\tfile: readPlatformVariable(environment, 'ComSpec', platform) ?? 'cmd.exe',\n\t\targuments: Object.freeze(['/d', '/s', '/c', `\"${line}\"`]),\n\t\tverbatim: true,\n\t})\n}\n\n/**\n * Builds the resolved spawn form of one command for the current host.\n *\n * @remarks\n * When executable lookup returns no regular-file candidate, {@link buildSpawn} preserves the\n * command file as written for native spawning.\n *\n * @param command - The executable and its argument vector\n * @param options - The directory searched first and the child's effective environment\n * @returns The file, argument vector, and verbatim flag to spawn with\n * @throws A {@link ProcessError} coded `invalid` when the host is Windows, the resolved target is a batch script, and an argument carries a percent sign\n *\n * @example\n * ```ts\n * buildSpawn({ file: 'node', arguments: ['--version'] }).verbatim // false\n * ```\n */\nexport function buildSpawn(command: ProcessCommand, options?: ExecutableOptions): SpawnInput {\n\tconst file = resolveExecutable(command.file, options) ?? command.file\n\tconst environment = options?.environment ?? process.env\n\treturn buildPlatformSpawn(command, file, environment, hostPlatform)\n}\n\n/**\n * Validates one spawn-bound string.\n *\n * @remarks\n * A NUL character terminates a string for the host, so it is refused everywhere rather than\n * reaching the spawn as a raw `ERR_INVALID_ARG_VALUE`.\n *\n * @param value - The value to inspect\n * @param subject - The rejected input named as the caller wrote it, such as `command file`\n * @param required - If `true`, an empty string is refused; if `false`, it is accepted\n * @returns Nothing; a successful return means the string is spawn-safe\n * @throws A {@link ProcessError} coded `invalid` when the value is not a string, carries a NUL, or is required and empty\n *\n * @example\n * ```ts\n * validateText('status', 'command argument', false) // returns\n * ```\n */\nexport function validateText(value: unknown, subject: string, required: boolean): void {\n\tif (!isString(value) || value.includes('\\0')) throw createInvalidError(subject, value)\n\tif (required && !isNonEmptyString(value)) throw createInvalidError(subject, value)\n}\n\n/**\n * Validates one timer-valued option in milliseconds.\n *\n * @remarks\n * The host truncates a fractional delay and converts anything above {@link PROCESS_TIMER} to one\n * millisecond, so a requested 25-day timeout would otherwise fire immediately.\n *\n * @param value - The value to inspect, or `undefined` when the option was omitted\n * @param subject - The rejected input named as the caller wrote it, such as `option 'grace'`\n * @returns Nothing; a successful return means the value schedules as written\n * @throws A {@link ProcessError} coded `invalid` when the value is not a non-negative integer at or below `PROCESS_TIMER`\n *\n * @example\n * ```ts\n * validateTimer(5_000, \"option 'grace'\") // returns\n * ```\n */\nexport function validateTimer(value: number | undefined, subject: string): void {\n\tif (value === undefined) return\n\tif (!isNonNegativeInteger(value) || !boundsOf(0, PROCESS_TIMER)(value)) {\n\t\tthrow createInvalidError(subject, value)\n\t}\n}\n\n/**\n * Validates one byte-valued option.\n *\n * @param value - The value to inspect, or `undefined` when the option was omitted\n * @param subject - The rejected input named as the caller wrote it, such as `option 'limit'`\n * @param minimum - The smallest accepted value\n * @returns Nothing; a successful return means the value bounds a real byte count\n * @throws A {@link ProcessError} coded `invalid` when the value is not a safe integer at or above `minimum`\n *\n * @example\n * ```ts\n * validateBytes(1_024, \"option 'limit'\", 0) // returns\n * ```\n */\nexport function validateBytes(value: number | undefined, subject: string, minimum: number): void {\n\tif (value === undefined) return\n\tif (!isNonNegativeInteger(value) || !boundsOf(minimum, Number.MAX_SAFE_INTEGER)(value)) {\n\t\tthrow createInvalidError(subject, value)\n\t}\n}\n\n/**\n * Validates every spawn-bound string of one environment override map.\n *\n * @remarks\n * The host refuses a NUL in a variable name or value with a raw `ERR_INVALID_ARG_VALUE`, so the same\n * refusal runs here for a command's own overrides and for a per-invocation override map alike.\n *\n * @param environment - The override map, or `undefined` when none was supplied\n * @returns Nothing; a successful return means every name and value reaches the host intact\n * @throws A {@link ProcessError} coded `invalid` when a name is empty or a name or value carries a NUL\n *\n * @example\n * ```ts\n * validateEnvironment({ TOKEN: 'a' }) // returns\n * ```\n */\nexport function validateEnvironment(\n\tenvironment: Readonly<Record<string, string | undefined>> | undefined,\n): void {\n\tif (environment === undefined) return\n\tfor (const [key, value] of Object.entries(environment)) {\n\t\tvalidateText(key, 'environment key', true)\n\t\tif (value !== undefined) validateText(value, 'environment value', false)\n\t}\n}\n\n/**\n * Validates every spawn-bound string of one command.\n *\n * @param command - The executable, arguments, and optional environment overrides\n * @returns Nothing; a successful return means the command reaches the host intact\n * @throws A {@link ProcessError} coded `invalid` when the file is empty or any string carries a NUL\n *\n * @example\n * ```ts\n * validateCommand({ file: 'git', arguments: ['status'] }) // returns\n * ```\n */\nexport function validateCommand(command: ProcessCommand): void {\n\tvalidateText(command.file, 'command file', true)\n\tfor (const argument of command.arguments) validateText(argument, 'command argument', false)\n\tvalidateEnvironment(command.environment)\n}\n\n/**\n * Validates the working directory one child starts in.\n *\n * @param workspace - The directory, or `undefined` when the option was omitted\n * @returns Nothing; a successful return means the directory reaches the host intact\n * @throws A {@link ProcessError} coded `invalid` when the directory is empty or carries a NUL\n *\n * @example\n * ```ts\n * validateWorkspace(process.cwd()) // returns\n * ```\n */\nexport function validateWorkspace(workspace: string | undefined): void {\n\tif (workspace === undefined) return\n\tvalidateText(workspace, 'workspace', true)\n}\n\n/**\n * Checks whether a child process has reached its native exit.\n *\n * @remarks\n * The host sets exactly one of these fields when the process ends, so together they are the\n * authoritative liveness answer. Reading them before each signal is what keeps a signal from being\n * initiated against a pid the host may have reused.\n *\n * @param child - The child boundary\n * @returns True if the process has exited; false otherwise\n *\n * @example\n * ```ts\n * isExited({ exitCode: 0, signalCode: null }) // true\n * ```\n */\nexport function isExited(child: Pick<ProcessChildInterface, 'exitCode' | 'signalCode'>): boolean {\n\treturn child.exitCode !== null || child.signalCode !== null\n}\n\n/**\n * Signals one owned child process, or its detached process group on a POSIX host.\n *\n * @remarks\n * On a POSIX host a child spawned `detached` leads its own process group, so signalling the\n * negated pid reaches the whole tree. When no group owns the pid and the host reports `ESRCH`, the\n * signal falls back to the child directly. On Windows, or when no pid is available, the signal also\n * goes to the child directly. Every other throw during signalling is swallowed: the process can\n * exit between the caller's liveness check and this call, and the child's native exit remains the\n * authoritative terminal state.\n *\n * @param child - The child boundary\n * @param signal - The signal to deliver\n * @returns Nothing\n *\n * @example\n * ```ts\n * killProcess(child, 'SIGTERM')\n * ```\n */\nexport function killProcess(\n\tchild: Pick<ProcessChildInterface, 'pid' | 'kill'>,\n\tsignal: NodeJS.Signals,\n): void {\n\ttry {\n\t\tif (process.platform === 'win32' || child.pid === undefined) {\n\t\t\tchild.kill(signal)\n\t\t\treturn\n\t\t}\n\t\tprocess.kill(-child.pid, signal)\n\t} catch (error) {\n\t\tif (isError(error) && 'code' in error && error.code === 'ESRCH') {\n\t\t\tholds(() => child.kill(signal))\n\t\t\treturn\n\t\t}\n\t\t// Exit can win the signal race; the native exit remains authoritative.\n\t}\n}\n\n/**\n * Kills one Windows process tree through `taskkill`.\n *\n * @remarks\n * Windows has no process group a signal can reach, so the whole tree is ended by the host utility,\n * addressed by its absolute `System32` path so a `PATH` override cannot substitute another program.\n * The call is bounded: it is killed itself when `timeout` elapses, which is what keeps a termination\n * from waiting on the host indefinitely. A tree is discoverable only while its root lives, so a\n * descendant that outlives the root is beyond this mechanism.\n *\n * @param pid - The root process id of the tree to end\n * @param timeout - The milliseconds the utility is given before it is killed\n * @returns True if the utility reported success; false otherwise (it failed, was unavailable, or was cut off)\n *\n * @example\n * ```ts\n * await killTree(child.pid ?? 0, 5_000)\n * ```\n */\nexport function killTree(pid: number, timeout: number): Promise<boolean> {\n\tconst settled = Promise.withResolvers<boolean>()\n\tconst executable = join(process.env.SystemRoot ?? 'C:\\\\Windows', 'System32', 'taskkill.exe')\n\tconst killer = spawn(executable, ['/F', '/T', '/PID', String(pid)], {\n\t\tstdio: 'ignore',\n\t\twindowsHide: true,\n\t\ttimeout,\n\t})\n\tkiller.once('error', () => settled.resolve(false))\n\tkiller.once('close', (code: number | null) => settled.resolve(code === 0))\n\treturn settled.promise\n}\n\n/**\n * Waits for one child process's native exit, bounded by a deadline.\n *\n * @param child - The child boundary\n * @param timeout - The milliseconds to wait before giving up\n * @returns A promise that resolves on the native exit or when the deadline elapses, whichever comes first\n *\n * @example\n * ```ts\n * await waitForExit(child, 5_000)\n * ```\n */\nexport function waitForExit(\n\tchild: Pick<ProcessChildInterface, 'exitCode' | 'signalCode' | 'once' | 'off'>,\n\ttimeout: number,\n): Promise<void> {\n\tif (isExited(child)) return Promise.resolve()\n\tconst settled = Promise.withResolvers<void>()\n\tconst timer = setTimeout(() => {\n\t\tchild.off('exit', settled.resolve)\n\t\tsettled.resolve()\n\t}, timeout)\n\tchild.once('exit', settled.resolve)\n\treturn settled.promise.finally(() => clearTimeout(timer))\n}\n\n/**\n * Waits for one child process's streams to close, bounded by a deadline.\n *\n * @param child - The child boundary\n * @param timeout - The milliseconds to wait before giving up\n * @returns True if the host close arrived inside the deadline; false otherwise\n *\n * @example\n * ```ts\n * const closed = await waitForClose(child, 5_000)\n * ```\n */\nexport function waitForClose(\n\tchild: Pick<ProcessChildInterface, 'once' | 'off'>,\n\ttimeout: number,\n): Promise<boolean> {\n\tconst closed = Promise.withResolvers<void>()\n\tconst expired = Promise.withResolvers<boolean>()\n\tconst timer = setTimeout(() => expired.resolve(false), timeout)\n\tchild.once('close', closed.resolve)\n\treturn Promise.race([closed.promise.then(() => true), expired.promise]).finally(() => {\n\t\tclearTimeout(timer)\n\t\tchild.off('close', closed.resolve)\n\t})\n}\n\n/**\n * Terminates one child process tree and reports whether its native exit was observed.\n *\n * @remarks\n * An already-exited child is returned on before any route to its pid runs, because the host has\n * reaped that number and may have handed it to another process. Windows ends the whole tree at once\n * through {@link killTree}, falling back to a direct kill after the utility fails, because the host\n * has no cooperative termination to offer. A POSIX host signals the process group `SIGTERM`, falls\n * back to the direct child when no group owns its pid, waits `grace`, then sends `SIGKILL` through\n * the same route. No signal is initiated after the native exit is observed; the window between\n * initiating a signal and the host delivering it belongs to the operating system. `confirm` bounds\n * each awaited step rather than the call as a whole: on Windows it bounds the `taskkill` call and\n * then the final wait, and on a POSIX host `grace` bounds the cooperative wait and `confirm` the\n * final one. Never rejects.\n *\n * @param child - The child boundary\n * @param grace - The cooperative POSIX window in milliseconds between `SIGTERM` and `SIGKILL`\n * @param confirm - The milliseconds the native exit is awaited after the final kill\n * @returns True if the native exit was observed; false otherwise (`confirm` elapsed without it)\n *\n * @example\n * ```ts\n * const confirmed = await stopChild(child, 5_000, 5_000)\n * ```\n */\nexport async function stopChild(\n\tchild: ProcessChildInterface,\n\tgrace: number,\n\tconfirm: number,\n): Promise<boolean> {\n\tif (isExited(child)) return true\n\tif (process.platform === 'win32') {\n\t\tconst killed = child.pid === undefined ? false : await killTree(child.pid, confirm)\n\t\tif (!killed && !isExited(child)) killProcess(child, 'SIGKILL')\n\t} else {\n\t\tkillProcess(child, 'SIGTERM')\n\t\tawait waitForExit(child, grace)\n\t\tif (!isExited(child)) killProcess(child, 'SIGKILL')\n\t}\n\tif (isExited(child)) return true\n\tawait waitForExit(child, confirm)\n\treturn isExited(child)\n}\n\n/**\n * Builds one settled {@link ExecuteResult} from a completed run's captured bytes and terminal facts.\n *\n * @remarks\n * `failed` is derived: a run failed when it timed out, was aborted, ended on a host fault, was ended\n * by a signal, or exited with a code other than `0` — a `null` code from a spawn fault is therefore\n * a failure. Each byte field is bounded by `limit` on a code-point boundary here, which is the one\n * place the captured bytes are decoded.\n *\n * @param input - The captured bytes, terminal state, and capture limit\n * @returns The frozen run outcome\n *\n * @example\n * ```ts\n * buildExecuteResult({\n * \tcommand: 'git status',\n * \tstdout: Buffer.from('ok'),\n * \tstderr: Buffer.alloc(0),\n * \tcode: 0,\n * \tsignal: null,\n * \texpired: false,\n * \taborted: false,\n * \ttruncated: false,\n * \tlimit: 1_024,\n * }).failed // false\n * ```\n */\nexport function buildExecuteResult(input: ExecuteInput): ExecuteResult {\n\treturn Object.freeze({\n\t\tcommand: input.command,\n\t\tstdout: trimHead(input.stdout, input.limit).toString('utf8'),\n\t\tstderr: trimHead(input.stderr, input.limit).toString('utf8'),\n\t\tcode: input.code,\n\t\tsignal: input.signal,\n\t\tfailed:\n\t\t\tinput.expired ||\n\t\t\tinput.aborted ||\n\t\t\tinput.cause !== undefined ||\n\t\t\tinput.signal !== null ||\n\t\t\tinput.code !== 0,\n\t\texpired: input.expired,\n\t\taborted: input.aborted,\n\t\ttruncated: input.truncated,\n\t})\n}\n\n/**\n * Runs one command to completion, buffering its output, and settles with the outcome.\n *\n * @remarks\n * The executable is resolved through {@link buildSpawn}, so no run uses a shell. On a POSIX host the\n * child is detached, which is what lets its whole process group be terminated. Standard output and\n * error are each byte-bounded by `limit` (default {@link PROCESS_OUTPUT}) and `truncated` reports\n * whether either stream exceeded it. Each capture keeps one byte beyond `limit`, so the single\n * code-point-boundary trim in {@link buildExecuteResult} reads the first excluded byte and never\n * delivers a split multibyte sequence. A positive `timeout` and an aborting `signal` both terminate the\n * child through the same bounded stop, and only the earliest is recorded: a timeout reports\n * `expired` and an abort reports `aborted`, never both. After termination the outcome is awaited for\n * a bounded window, so a descendant holding the child's stdio cannot keep the run pending. That bound\n * covers a terminated run alone: a run with no `timeout` and no `signal` settles on stdio completion\n * rather than on process exit, so a descendant that inherited the child's stdio holds the run open\n * after the child itself has gone. Give such a run a `timeout`. The child's `environment` merges over\n * the parent unless the command is `isolated`, then `options.environment` on top, and `options.input`\n * overrides `command.input`. A host fault while writing that input terminates the run by design and\n * marks its result failed; a strict rejection carries the host fault as its cause. This differs\n * from `Process` constructor input, whose package-initiated input phase stays quiet. Unless `strict`\n * is `false`, a failed run rejects with a {@link ProcessError} carrying the {@link ExecuteResult};\n * {@link createExecuteError} constructs every rejection outside the input-fault door. An invalid\n * option or command string rejects before the child is spawned, because an async function cannot\n * throw synchronously.\n *\n * @param command - The executable, arguments, and optional environment and input\n * @param options - Working directory, timeout, grace, signal, capture limit, and failure delivery\n * @returns The settled run outcome\n * @throws A {@link ProcessError} coded `invalid` for a malformed option, command string, or batch-bound argument, or one carrying the {@link ExecuteResult} when the run failed and `strict` is not `false`\n *\n * @example\n * ```ts\n * const result = await execute({ file: 'git', arguments: ['status'] }, { workspace: process.cwd() })\n * ```\n */\nexport async function execute(\n\tcommand: ProcessCommand,\n\toptions?: ExecuteOptions,\n): Promise<ExecuteResult> {\n\tconst snapshot = snapshotCommand(command)\n\tconst optionEnvironment = options?.environment\n\tconst optionWorkspace = options?.workspace\n\tconst optionInput = options?.input\n\tconst optionTimeout = options?.timeout\n\tconst optionGrace = options?.grace\n\tconst optionSignal = options?.signal\n\tconst optionStrict = options?.strict\n\tconst optionLimit = options?.limit\n\tvalidateCommand(snapshot)\n\tvalidateEnvironment(optionEnvironment)\n\tvalidateWorkspace(optionWorkspace)\n\tvalidateTimer(optionTimeout, \"option 'timeout'\")\n\tvalidateTimer(optionGrace, \"option 'grace'\")\n\tvalidateBytes(optionLimit, \"option 'limit'\", 0)\n\tconst limit = optionLimit ?? PROCESS_OUTPUT\n\tconst grace = optionGrace ?? PROCESS_GRACE\n\tconst timeout = optionTimeout ?? 0\n\tconst strict = optionStrict ?? true\n\tconst text = optionInput ?? snapshot.input\n\tconst line = formatCommand(snapshot)\n\tconst workspace = optionWorkspace ?? process.cwd()\n\tconst environment = mergeEnvironment(\n\t\tsnapshot.isolated === true,\n\t\tsnapshot.environment,\n\t\toptionEnvironment,\n\t)\n\tconst plan = buildSpawn(snapshot, { workspace, environment })\n\tconst settled = Promise.withResolvers<ExecuteResult>()\n\tconst terminate = new AbortController()\n\tconst cleanup = new AbortController()\n\tconst finish = new AbortController()\n\tconst inputFailure = new AbortController()\n\tconst outChunks: Buffer[] = []\n\tconst errChunks: Buffer[] = []\n\tlet spawned = false\n\tlet expired = false\n\tlet aborted = false\n\tlet outRetained = 0\n\tlet errRetained = 0\n\tlet cause: unknown\n\tlet timeoutTimer: ReturnType<typeof setTimeout> | undefined\n\tlet confirmTimer: ReturnType<typeof setTimeout> | undefined\n\n\tconst child: ChildProcessWithoutNullStreams = spawn(plan.file, [...plan.arguments], {\n\t\tcwd: workspace,\n\t\tdetached: process.platform !== 'win32',\n\t\tenv: environment,\n\t\tstdio: ['pipe', 'pipe', 'pipe'],\n\t\twindowsHide: true,\n\t\twindowsVerbatimArguments: plan.verbatim,\n\t})\n\n\tfinish.signal.addEventListener(\n\t\t'abort',\n\t\t() => {\n\t\t\tclearTimeout(timeoutTimer)\n\t\t\tclearTimeout(confirmTimer)\n\t\t\tcleanup.abort()\n\t\t\tsettled.resolve(\n\t\t\t\tbuildExecuteResult({\n\t\t\t\t\tcommand: line,\n\t\t\t\t\tstdout: Buffer.concat(outChunks),\n\t\t\t\t\tstderr: Buffer.concat(errChunks),\n\t\t\t\t\tcode: child.exitCode,\n\t\t\t\t\tsignal: child.signalCode,\n\t\t\t\t\texpired,\n\t\t\t\t\taborted,\n\t\t\t\t\ttruncated: outRetained > limit || errRetained > limit,\n\t\t\t\t\tlimit,\n\t\t\t\t\t...(cause === undefined ? {} : { cause }),\n\t\t\t\t}),\n\t\t\t)\n\t\t},\n\t\t{ once: true },\n\t)\n\n\tterminate.signal.addEventListener(\n\t\t'abort',\n\t\t() => {\n\t\t\tif (finish.signal.aborted) return\n\t\t\tclearTimeout(timeoutTimer)\n\t\t\tcleanup.abort()\n\t\t\tvoid stopChild(child, grace, PROCESS_CONFIRMATION).then(() => {\n\t\t\t\tif (finish.signal.aborted) return\n\t\t\t\tconfirmTimer = setTimeout(() => finish.abort(), PROCESS_CONFIRMATION)\n\t\t\t})\n\t\t},\n\t\t{ once: true },\n\t)\n\n\tinputFailure.signal.addEventListener(\n\t\t'abort',\n\t\t() => {\n\t\t\tif (finish.signal.aborted) return\n\t\t\tcause = inputFailure.signal.reason\n\t\t\tterminate.abort()\n\t\t},\n\t\t{ once: true },\n\t)\n\n\tchild.stdin.on('error', (error: Error) => inputFailure.abort(error))\n\tchild.stdout.on('data', (chunk: unknown) => {\n\t\tconst captured = captureChunk(chunk, limit + 1 - outRetained)\n\t\tif (captured === undefined) return\n\t\toutRetained += captured.byteLength\n\t\toutChunks.push(captured)\n\t})\n\tchild.stderr.on('data', (chunk: unknown) => {\n\t\tconst captured = captureChunk(chunk, limit + 1 - errRetained)\n\t\tif (captured === undefined) return\n\t\terrRetained += captured.byteLength\n\t\terrChunks.push(captured)\n\t})\n\tchild.once('spawn', () => {\n\t\tspawned = true\n\t})\n\tchild.once('error', (error: unknown) => {\n\t\tif (spawned) return\n\t\tcause = error\n\t\tfinish.abort()\n\t})\n\tchild.once('close', () => finish.abort())\n\n\tif (text !== undefined) {\n\t\tchild.stdin.write(text, (error?: Error | null) => {\n\t\t\tif (error !== undefined && error !== null) inputFailure.abort(error)\n\t\t})\n\t}\n\tchild.stdin.end()\n\tif (timeout > 0) {\n\t\ttimeoutTimer = setTimeout(() => {\n\t\t\texpired = true\n\t\t\tterminate.abort()\n\t\t}, timeout)\n\t}\n\tif (optionSignal !== undefined) {\n\t\toptionSignal.addEventListener(\n\t\t\t'abort',\n\t\t\t() => {\n\t\t\t\taborted = true\n\t\t\t\tterminate.abort()\n\t\t\t},\n\t\t\t{ once: true, signal: cleanup.signal },\n\t\t)\n\t\tif (optionSignal.aborted) {\n\t\t\taborted = true\n\t\t\tterminate.abort()\n\t\t}\n\t}\n\n\tconst result = await settled.promise\n\tif (result.failed && strict) {\n\t\tif (cause !== undefined && cause === inputFailure.signal.reason) {\n\t\t\tthrow new ProcessError(`Command '${result.command}' failed while writing standard input`, {\n\t\t\t\tcode: 'input',\n\t\t\t\tcontext: { command: result.command, code: result.code, signal: result.signal },\n\t\t\t\tcause: inputFailure.signal.reason,\n\t\t\t\tresult,\n\t\t\t})\n\t\t}\n\t\tthrow createExecuteError(result, cause)\n\t}\n\treturn result\n}\n\n/**\n * Runs one command to completion synchronously, buffering its output, and returns the outcome.\n *\n * @remarks\n * The synchronous counterpart of {@link execute}, spawned through the same resolver and never through a\n * shell. The host offers no cooperative termination window and no in-flight cancellation, so this\n * contract carries neither. A positive `timeout` ends only the root process and can leave\n * descendants running; use {@link execute} or {@link Process} when timeout must terminate the tree. A\n * timeout and an output overflow both end the root with `SIGKILL`: an overflow reports `truncated`\n * and `failed` together and trims the partial output to `limit`, where {@link execute} keeps reading and\n * reports `truncated` without failing. The environment and input follow the same merge as\n * {@link execute}. Unless `strict` is `false`, a failed run throws a {@link createExecuteError}\n * carrying the {@link ExecuteResult}.\n *\n * @param command - The executable, arguments, and optional environment and input\n * @param options - Working directory, timeout, capture limit, and failure delivery\n * @returns The run outcome\n * @throws A {@link ProcessError} coded `invalid` for a malformed option, command string, or batch-bound argument, or one carrying the {@link ExecuteResult} when the run failed and `strict` is not `false`\n *\n * @example\n * ```ts\n * const result = executeSync({ file: 'git', arguments: ['--version'] }, { strict: false })\n * ```\n */\nexport function executeSync(command: ProcessCommand, options?: ExecuteSyncOptions): ExecuteResult {\n\tconst snapshot = snapshotCommand(command)\n\tconst optionEnvironment = options?.environment\n\tconst optionWorkspace = options?.workspace\n\tconst optionInput = options?.input\n\tconst optionTimeout = options?.timeout\n\tconst optionStrict = options?.strict\n\tconst optionLimit = options?.limit\n\tvalidateCommand(snapshot)\n\tvalidateEnvironment(optionEnvironment)\n\tvalidateWorkspace(optionWorkspace)\n\tvalidateTimer(optionTimeout, \"option 'timeout'\")\n\tvalidateBytes(optionLimit, \"option 'limit'\", 0)\n\tconst limit = optionLimit ?? PROCESS_OUTPUT\n\tconst timeout = optionTimeout ?? 0\n\tconst strict = optionStrict ?? true\n\tconst text = optionInput ?? snapshot.input\n\tconst line = formatCommand(snapshot)\n\tconst workspace = optionWorkspace ?? process.cwd()\n\tconst environment = mergeEnvironment(\n\t\tsnapshot.isolated === true,\n\t\tsnapshot.environment,\n\t\toptionEnvironment,\n\t)\n\tconst plan = buildSpawn(snapshot, { workspace, environment })\n\tconst outcome = spawnSync(plan.file, [...plan.arguments], {\n\t\tcwd: workspace,\n\t\tenv: environment,\n\t\tencoding: 'buffer',\n\t\tmaxBuffer: limit,\n\t\tkillSignal: 'SIGKILL',\n\t\twindowsHide: true,\n\t\twindowsVerbatimArguments: plan.verbatim,\n\t\t...(text !== undefined ? { input: Buffer.from(text) } : {}),\n\t\t...(timeout > 0 ? { timeout } : {}),\n\t})\n\tconst error = outcome.error\n\tconst fault = error !== undefined && 'code' in error && isString(error.code) ? error.code : ''\n\tconst result = buildExecuteResult({\n\t\tcommand: line,\n\t\tstdout: Buffer.isBuffer(outcome.stdout) ? outcome.stdout : Buffer.alloc(0),\n\t\tstderr: Buffer.isBuffer(outcome.stderr) ? outcome.stderr : Buffer.alloc(0),\n\t\tcode: outcome.status,\n\t\tsignal: outcome.signal,\n\t\texpired: fault === 'ETIMEDOUT',\n\t\taborted: false,\n\t\ttruncated: fault === 'ENOBUFS',\n\t\tlimit,\n\t\t...(error === undefined ? {} : { cause: error }),\n\t})\n\tif (result.failed && strict) throw createExecuteError(result, error)\n\treturn result\n}\n\n/**\n * Spawns one command as a detached process and returns without waiting for it.\n *\n * @remarks\n * The child owns no stdio and is unreferenced, so it outlives this process and nothing here observes\n * its outcome. The error listener is attached before the child is unreferenced, so a post-spawn host\n * fault is swallowed rather than crashing the caller; an invalid command is refused before anything\n * is spawned.\n *\n * @param command - The executable, arguments, and optional environment\n * @param options - The working directory the detached child starts in\n * @returns Nothing\n * @throws A {@link ProcessError} coded `invalid` when the working directory or a command string is malformed\n *\n * @example\n * ```ts\n * detach({ file: 'node', arguments: ['daemon.js'] }, { workspace: process.cwd() })\n * ```\n */\nexport function detach(command: ProcessCommand, options?: DetachOptions): void {\n\tconst snapshot = snapshotCommand(command)\n\tconst optionWorkspace = options?.workspace\n\tvalidateCommand(snapshot)\n\tvalidateWorkspace(optionWorkspace)\n\tconst workspace = optionWorkspace ?? process.cwd()\n\tconst environment = mergeEnvironment(snapshot.isolated === true, snapshot.environment)\n\tconst plan = buildSpawn(snapshot, { workspace, environment })\n\tconst child = spawn(plan.file, [...plan.arguments], {\n\t\tcwd: workspace,\n\t\tdetached: true,\n\t\tenv: environment,\n\t\tstdio: 'ignore',\n\t\twindowsHide: true,\n\t\twindowsVerbatimArguments: plan.verbatim,\n\t})\n\tchild.once('error', () => undefined)\n\tchild.unref()\n}\n","import type { ChildProcessWithoutNullStreams } from 'node:child_process'\nimport type { Readable } from 'node:stream'\nimport type { ProcessExit, ProcessOptions } from '@src/core'\nimport type { SupervisorFace } from '../types.js'\nimport { Buffer } from 'node:buffer'\nimport { spawn } from 'node:child_process'\nimport { StringDecoder } from 'node:string_decoder'\nimport {\n\tProcessError,\n\tPROCESS_CONFIRMATION,\n\tPROCESS_DRAIN,\n\tPROCESS_EVIDENCE,\n\tPROCESS_GRACE,\n} from '@src/core'\nimport { snapshotCommand } from '../cloners.js'\nimport {\n\tbuildSpawn,\n\tmergeEnvironment,\n\tstopChild,\n\ttrimTail,\n\tvalidateBytes,\n\tvalidateCommand,\n\tvalidateTimer,\n\tvalidateWorkspace,\n\twaitForClose,\n} from '../helpers.js'\n\n/**\n * Supervises one child process and reports each lifecycle moment to the face composing it.\n *\n * @remarks\n * This is the engine every supervised-child face shares. It owns the eager spawn, the byte-bounded\n * stderr tail and its decoded chunks, the standard-input channel and its bounded confirmation, the\n * termination sequence, and the progression from the child's native exit through the bounded `drain`\n * window to one terminal moment. It owns no output framing and no observation surface: a face\n * attaches its own consumer to `stdout`, frames bytes however its contract promises, and owns the\n * emitter and event map its consumers subscribe to.\n *\n * The child's ending and the supervision's ending are distinct. `pid`, `code`, and `signal` read the\n * host child directly, so they expose native exit as soon as the host records it, and `ending`\n * settles at that same moment. `settled`, `exit`, and `evidence` reach one terminal moment after the\n * read channels close or the bounded `drain` window cuts them off. That window is armed by the\n * child's native exit and by a termination this package initiated, so every way a child can end\n * reaches the moment. The terminal routine hands the face its `close` and `terminal` moments before\n * it destroys stdout and stderr, so a face's own pull surfaces are final while its read ends still\n * exist.\n *\n * The face is a set of callbacks rather than an emitter, because each face publishes a different\n * event map over the same moments. `chunk` and `fault` carry the live stderr text and the child or\n * channel faults, `relieve` reports that a termination began so the face can release whatever\n * backpressure it holds, `close` ends the face's read pipeline at the terminal moment, `terminal`\n * carries the frozen {@link ProcessExit}, and `teardown` releases the face's own surface after the\n * termination completes. `relieve` is optional because a face that never pauses the child's output\n * holds no backpressure to release, and a face with nothing to do there would otherwise declare an\n * empty method to say so.\n *\n * @example\n * ```ts\n * import { Supervisor } from '@orkestrel/process/server'\n *\n * const engine = new Supervisor(\n * \t{ command: { file: 'node', arguments: ['--version'] }, workspace: process.cwd() },\n * \t{\n * \t\tchunk: () => undefined,\n * \t\tfault: () => undefined,\n * \t\tclose: () => undefined,\n * \t\tterminal: () => undefined,\n * \t\tteardown: () => undefined,\n * \t},\n * )\n * const exit = await engine.exit\n * exit.code // 0\n * await engine.destroy()\n * ```\n */\nexport class Supervisor {\n\treadonly #chunk: (text: string) => void\n\treadonly #fault: (cause: unknown) => void\n\treadonly #relieve: (() => void) | undefined\n\treadonly #close: () => void\n\treadonly #terminal: (exit: ProcessExit) => void\n\treadonly #teardown: () => void\n\treadonly #child: ChildProcessWithoutNullStreams\n\treadonly #grace: number\n\treadonly #drain: number\n\treadonly #evidence: number\n\treadonly #delivery: number\n\treadonly #decoder = new StringDecoder('utf8')\n\treadonly #exit = Promise.withResolvers<ProcessExit>()\n\treadonly #ending = Promise.withResolvers<void>()\n\treadonly #signal: AbortSignal | undefined\n\treadonly #abort: EventListener | undefined\n\treadonly #writes = new Map<\n\t\tPromiseWithResolvers<boolean>,\n\t\tReturnType<typeof setTimeout> | undefined\n\t>()\n\t#tail: Buffer = Buffer.alloc(0)\n\t// A guard reads `#stopping`, never `#termination !== undefined`. `#kill` assigns the boolean in\n\t// its synchronous prefix, which runs while `stop` is still evaluating\n\t// `this.#termination = this.#kill()`, so the boolean also covers the retention and backpressure\n\t// decisions a face takes while `#termination` is still `undefined`.\n\t#stopping = false\n\t#settled = false\n\t#input = 0\n\t#failure: Error | undefined\n\t#waiting: Promise<void> | undefined\n\t#closure: Promise<void> | undefined\n\t#termination: Promise<boolean> | undefined\n\t#destruction: Promise<void> | undefined\n\n\t/**\n\t * Spawns one child process and begins standard-error capture.\n\t *\n\t * @remarks\n\t * The face's callbacks are captured before anything is read or spawned, so the first moment the\n\t * child can produce already has somewhere to go. `options` supplies the command, workspace,\n\t * termination, capture, and standard-input settings; a face's own settings, such as an output\n\t * retention bound, are read and validated by that face before it constructs this engine, so an\n\t * invalid one refuses construction while nothing has been spawned.\n\t *\n\t * @param options - Command, workspace, termination, capture, and stdin settings\n\t * @param face - The composing face's callbacks for each lifecycle moment\n\t * @throws A {@link ProcessError} coded `invalid` when an option or command string is malformed\n\t */\n\tconstructor(options: ProcessOptions, face: SupervisorFace) {\n\t\tthis.#chunk = face.chunk\n\t\tthis.#fault = face.fault\n\t\tthis.#relieve = face.relieve\n\t\tthis.#close = face.close\n\t\tthis.#terminal = face.terminal\n\t\tthis.#teardown = face.teardown\n\t\t// Every option and command property is read once, here, before anything is spawned. Reading a\n\t\t// property runs the caller's own getter, so a read after the spawn would let that getter throw\n\t\t// while a live child exists and no one holds a reference to it. Hoisting the reads is what\n\t\t// makes a construction failure unable to strand a process.\n\t\tconst source = options.command\n\t\tconst workspace = options.workspace\n\t\tconst grace = options.grace\n\t\tconst drain = options.drain\n\t\tconst evidence = options.evidence\n\t\tconst delivery = options.delivery\n\t\tconst writable = options.writable\n\t\tconst signal = options.signal\n\t\tconst command = snapshotCommand(source)\n\t\tconst input = command.input\n\t\tvalidateCommand(command)\n\t\tvalidateWorkspace(workspace)\n\t\tvalidateTimer(grace, \"option 'grace'\")\n\t\tvalidateTimer(drain, \"option 'drain'\")\n\t\tvalidateTimer(delivery, \"option 'delivery'\")\n\t\tvalidateBytes(evidence, \"option 'evidence'\", 0)\n\t\tthis.#grace = grace ?? PROCESS_GRACE\n\t\tthis.#drain = drain ?? PROCESS_DRAIN\n\t\tthis.#evidence = evidence ?? PROCESS_EVIDENCE\n\t\tthis.#delivery = delivery ?? 0\n\t\tthis.#signal = signal\n\t\tconst childEnvironment = mergeEnvironment(command.isolated === true, command.environment)\n\t\tconst plan = buildSpawn(command, { workspace, environment: childEnvironment })\n\t\tthis.#child = spawn(plan.file, [...plan.arguments], {\n\t\t\tcwd: workspace,\n\t\t\tdetached: process.platform !== 'win32',\n\t\t\tenv: childEnvironment,\n\t\t\tstdio: ['pipe', 'pipe', 'pipe'],\n\t\t\twindowsHide: true,\n\t\t\twindowsVerbatimArguments: plan.verbatim,\n\t\t})\n\t\tthis.#child.once('error', this.#fault)\n\t\tthis.#child.once('exit', this.#expire.bind(this))\n\t\tthis.#child.once('close', this.#complete.bind(this))\n\t\tthis.#child.stdin.on('error', this.#failInputStream.bind(this))\n\t\tthis.#child.stderr.on('data', this.#retain.bind(this))\n\t\tif (input !== undefined) {\n\t\t\tthis.#input += 1\n\t\t\tthis.#child.stdin.write(input, this.#completeInput.bind(this))\n\t\t}\n\t\tif (writable !== true) {\n\t\t\tthis.#input += 1\n\t\t\tthis.#child.stdin.end(this.#completeInput.bind(this))\n\t\t}\n\t\tif (signal !== undefined) {\n\t\t\tthis.#abort = this.#terminate.bind(this)\n\t\t\tsignal.addEventListener('abort', this.#abort, { once: true })\n\t\t\tif (signal.aborted) void this.stop()\n\t\t}\n\t}\n\n\t/** Holds the child's standard-output stream, for the composing face to attach its own consumer to. */\n\tget stdout(): Readable {\n\t\treturn this.#child.stdout\n\t}\n\n\t/** Holds the host process id, fixed when construction returns, or `undefined` when the spawn produced none. */\n\tget pid(): number | undefined {\n\t\treturn this.#child.pid\n\t}\n\n\t/** Holds the exit code the host recorded, or `null` while the child has not exited and when a signal ended it. */\n\tget code(): number | null {\n\t\treturn this.#child.exitCode\n\t}\n\n\t/** Holds the terminating signal name the host recorded, or `null` while the child has not exited and when it exited on its own. */\n\tget signal(): string | null {\n\t\treturn this.#child.signalCode\n\t}\n\n\t/** Holds the decoded byte-bounded stderr tail, frozen at the terminal moment. */\n\tget evidence(): string {\n\t\treturn this.#tail.toString('utf8')\n\t}\n\n\t/** Reports whether the terminal moment arrived and `exit` settled. */\n\tget settled(): boolean {\n\t\treturn this.#settled\n\t}\n\n\t/** Reports whether termination began, including after the terminal moment. */\n\tget stopping(): boolean {\n\t\treturn this.#stopping\n\t}\n\n\t/**\n\t * Settles at the child's own ending, awaited without the terminal moment's drain window.\n\t *\n\t * @remarks\n\t * Never rejects, and resolves no value: `code` and `signal` carry the terminal facts as soon as\n\t * the host records them. It settles at the native exit, and at the terminal moment for a child\n\t * whose spawn produced no native exit at all, so it can never outlive the supervision.\n\t */\n\tget ending(): Promise<void> {\n\t\treturn this.#ending.promise\n\t}\n\n\t/** Settles with the terminal child state, observed once after stream close or the drain cutoff. */\n\tget exit(): Promise<ProcessExit> {\n\t\treturn this.#exit.promise\n\t}\n\n\t/**\n\t * Writes raw bytes to the open standard-input channel.\n\t *\n\t * @remarks\n\t * Never rejects, and adds no framing: a face composes whatever terminator its contract promises\n\t * before it calls this. `true` means the host accepted the bytes without reporting a fault; it\n\t * does not prove that the child read them. An ordinary write settles when the kernel accepts it.\n\t * Only a full pipe can hold the write unconfirmed. The `delivery` option can bound that wait, and\n\t * every terminal teardown path settles pending writes. After `stop` or `destroy` begins, a later\n\t * call settles `false`, because teardown cannot confirm delivery for bytes it is about to\n\t * discard.\n\t *\n\t * @param bytes - The payload to write, already framed by the caller\n\t * @returns True if the host accepted the bytes without reporting a fault; false otherwise (the channel was closed, destroyed, ended, failed, or the write remained unconfirmed through `delivery`)\n\t *\n\t * @example\n\t * ```ts\n\t * import { Supervisor } from '@orkestrel/process/server'\n\t *\n\t * const engine = new Supervisor(\n\t * \t{\n\t * \t\tcommand: { file: 'node', arguments: ['-e', 'process.stdin.pipe(process.stdout)'] },\n\t * \t\tworkspace: process.cwd(),\n\t * \t\twritable: true,\n\t * \t},\n\t * \t{\n\t * \t\tchunk: () => undefined,\n\t * \t\tfault: () => undefined,\n\t * \t\tclose: () => undefined,\n\t * \t\tterminal: () => undefined,\n\t * \t\tteardown: () => undefined,\n\t * \t},\n\t * )\n\t * const accepted = await engine.deliver(new TextEncoder().encode('ping\\n'))\n\t * accepted // true\n\t * await engine.destroy()\n\t * ```\n\t */\n\tdeliver(bytes: Uint8Array): Promise<boolean> {\n\t\tconst stdin = this.#child.stdin\n\t\tif (this.#settled || this.#stopping || this.#failure !== undefined || !stdin.writable) {\n\t\t\treturn Promise.resolve(false)\n\t\t}\n\t\tconst settled = Promise.withResolvers<boolean>()\n\t\tthis.#writes.set(settled, undefined)\n\t\ttry {\n\t\t\tstdin.write(bytes, this.#confirmWrite.bind(this, settled))\n\t\t} catch {\n\t\t\tthis.#settleWrite(settled, false)\n\t\t\treturn settled.promise\n\t\t}\n\t\tif (this.#delivery > 0 && this.#writes.has(settled)) {\n\t\t\tconst timer = setTimeout(() => this.#settleWrite(settled, false), this.#delivery)\n\t\t\ttimer.unref()\n\t\t\tthis.#writes.set(settled, timer)\n\t\t}\n\t\treturn settled.promise\n\t}\n\n\t/**\n\t * Closes the standard-input channel while leaving the child running.\n\t *\n\t * @remarks\n\t * Never rejects, and terminates nothing: no signal is sent, `stopping` stays false, no drain\n\t * window is armed, and the terminal moment does not arrive. The child observes end of input and\n\t * decides for itself what to do about it, which is what separates this from `stop`.\n\t *\n\t * Every call shares one barrier, and it resolves after the host flushes the writes it had already\n\t * accepted, or reports that it cannot. A `deliver` after this call resolves `false`, because the\n\t * host stops reporting the channel writable the moment it is ended. That same flag keeps the\n\t * ended channel quiet for its remaining life, so a later host fault on it settles pending writes\n\t * and reaches no face. After `stop` or `destroy` has begun, or after the terminal moment, the\n\t * call resolves and changes nothing, because the channel is already being discarded.\n\t *\n\t * @returns The stable barrier shared by every call\n\t */\n\tend(): Promise<void> {\n\t\tif (this.#closure !== undefined) return this.#closure\n\t\tthis.#closure = this.#endInput()\n\t\treturn this.#closure\n\t}\n\n\t/**\n\t * Terminates the child process tree and reaches the terminal observation moment.\n\t *\n\t * @remarks\n\t * Never rejects, and every call shares one termination. After the termination sequence returns,\n\t * confirmed or not, it waits at most `drain` for the read channels to close, then cuts them off\n\t * and settles `exit` when they remain open. A cutoff reached before the native exit reports the\n\t * `code` and `signal` the host had recorded by then, which is `null` for a child still running.\n\t *\n\t * @returns True if the child's native exit was observed; false otherwise (the confirmation deadline elapsed without it)\n\t */\n\tstop(): Promise<boolean> {\n\t\tif (this.#termination !== undefined) return this.#termination\n\t\tthis.#termination = this.#kill()\n\t\treturn this.#termination\n\t}\n\n\t/**\n\t * Stops the child and releases the composing face after the terminal state freezes.\n\t *\n\t * @remarks\n\t * Always resolves, including when termination was never confirmed. Every call shares one barrier.\n\t *\n\t * @returns The stable barrier shared by every call\n\t */\n\tdestroy(): Promise<void> {\n\t\tif (this.#destruction !== undefined) return this.#destruction\n\t\tthis.#destruction = this.#conclude()\n\t\treturn this.#destruction\n\t}\n\n\t#retain(chunk: unknown): void {\n\t\tif (!Buffer.isBuffer(chunk) || this.#settled) return\n\t\tthis.#tail = trimTail(Buffer.concat([this.#tail, chunk]), this.#evidence)\n\t\tconst text = this.#decoder.write(chunk)\n\t\tif (text.length > 0) this.#chunk(text)\n\t}\n\n\t#complete(): void {\n\t\tif (this.#settled) return\n\t\tthis.#settle(true)\n\t}\n\n\t// A native exit does not close the read ends: a descendant that inherited them holds them open\n\t// for its own remaining life, and one that never ends never closes them at all. Arming the same\n\t// bounded wait a requested termination awaits is what makes every ending reach the terminal\n\t// moment. `ending` settles here rather than at that moment, because it reports the child's own\n\t// exit and not the release of the channels a descendant may still hold.\n\t#expire(): void {\n\t\tthis.#ending.resolve()\n\t\tif (this.#settled) return\n\t\tvoid this.#wait()\n\t}\n\n\t// One bounded wait per close, created once and shared: the native exit arms it and a termination\n\t// awaits the same one, so a close never carries two overlapping bounds. `waitForClose` clears its\n\t// own timer on either outcome. The constructor registers `#complete` before this listener exists,\n\t// so a natural close settles drained and the following continuation finds the latch already set.\n\t#wait(): Promise<void> {\n\t\tthis.#waiting ??= waitForClose(this.#child, this.#drain).then(() => {\n\t\t\tif (!this.#settled) this.#settle(false)\n\t\t})\n\t\treturn this.#waiting\n\t}\n\n\t#settle(drained: boolean): void {\n\t\t// Flush the decoder while the face's stderr channel is still live.\n\t\tconst suffix = this.#decoder.end()\n\t\tif (suffix.length > 0) this.#chunk(suffix)\n\t\t// Latch before the following lines resolve and deliver the terminal value, so a consumer\n\t\t// handed that value never reads a child still reporting itself unfinished.\n\t\tthis.#settled = true\n\t\tthis.#removeAbortListener()\n\t\t// Ending the face's read pipeline here preserves whatever it has already framed and queued.\n\t\tthis.#close()\n\t\tconst exit = Object.freeze({ code: this.code, signal: this.signal, drained })\n\t\tthis.#exit.resolve(exit)\n\t\t// A spawn that produced no child reports no native exit, so the terminal moment is the last\n\t\t// place `ending` can settle rather than wait forever.\n\t\tthis.#ending.resolve()\n\t\tthis.#terminal(exit)\n\t\t// Release read handles only after every pull surface is final.\n\t\tthis.#child.stdout.destroy()\n\t\tthis.#child.stderr.destroy()\n\t}\n\n\t#terminate(): void {\n\t\tvoid this.stop()\n\t}\n\n\t#removeAbortListener(): void {\n\t\tif (this.#signal === undefined || this.#abort === undefined) return\n\t\tthis.#signal.removeEventListener('abort', this.#abort)\n\t}\n\n\t#confirmWrite(settled: PromiseWithResolvers<boolean>, error?: Error | null): void {\n\t\tif (error === undefined || error === null) {\n\t\t\tthis.#settleWrite(settled, true)\n\t\t\treturn\n\t\t}\n\t\tthis.#failInputCallback(error)\n\t}\n\n\t#completeInput(): void {\n\t\tthis.#input -= 1\n\t}\n\n\t// A channel already ended, destroyed, or being discarded has nothing left to close, so the\n\t// barrier resolves without touching the stream: calling `end` on a destroyed stream raises a\n\t// host error that no consumer asked for. Otherwise Node's own `end` flushes whatever it already\n\t// accepted and reports through the callback either way, which is why this never rejects.\n\t#endInput(): Promise<void> {\n\t\tconst stdin = this.#child.stdin\n\t\tif (this.#stopping || this.#settled || stdin.writableEnded || stdin.destroyed) {\n\t\t\treturn Promise.resolve()\n\t\t}\n\t\tconst ended = Promise.withResolvers<void>()\n\t\tstdin.end(() => ended.resolve())\n\t\treturn ended.promise\n\t}\n\n\t#settleWrite(settled: PromiseWithResolvers<boolean>, accepted: boolean): void {\n\t\tif (!this.#writes.has(settled)) return\n\t\tconst timer = this.#writes.get(settled)\n\t\tthis.#writes.delete(settled)\n\t\tclearTimeout(timer)\n\t\tsettled.resolve(accepted)\n\t}\n\n\t#settleWrites(): void {\n\t\tfor (const settled of this.#writes.keys()) this.#settleWrite(settled, false)\n\t}\n\n\t#failInputStream(cause: Error): void {\n\t\t// The constructor's own input phase is quiet while it runs, because the package initiated that\n\t\t// write and its closing `end`. Every other quieting rule lives in the following classifier,\n\t\t// which both the stream's error event and a write callback reach.\n\t\tif (this.#input > 0) {\n\t\t\tthis.#settleWrites()\n\t\t\treturn\n\t\t}\n\t\tthis.#failInputCallback(cause)\n\t}\n\n\t#failInputCallback(cause: Error): void {\n\t\t// An ended channel stays quiet for its remaining life, whether the package ended it at\n\t\t// construction or a consumer ended it through `end`: the closure was asked for, so the fault it\n\t\t// produces is not news to report. Pending writes still settle, because nothing left is going to\n\t\t// confirm them. A `writable: true` channel never sets `writableEnded` until ended, so a later\n\t\t// host fault on an open channel stays classifiable.\n\t\tif (this.#child.stdin.writableEnded) {\n\t\t\tthis.#settleWrites()\n\t\t\treturn\n\t\t}\n\t\tif (this.#failure !== undefined || this.#stopping) return\n\t\tthis.#failure = cause\n\t\tthis.#settleWrites()\n\t\tthis.#fault(new ProcessError('The standard-input channel failed', { code: 'protocol', cause }))\n\t}\n\n\tasync #kill(): Promise<boolean> {\n\t\t// A paused stdout holds the child's own write, and therefore its exit. The face releases its\n\t\t// backpressure before anything is signalled; later output drops at the face's teardown bound\n\t\t// instead of pausing the stream again.\n\t\tthis.#stopping = true\n\t\tthis.#relieve?.()\n\t\tconst confirmed = await stopChild(this.#child, this.#grace, PROCESS_CONFIRMATION)\n\t\tthis.#settleWrites()\n\t\tthis.#child.stdin.destroy()\n\t\tif (!this.#settled) await this.#wait()\n\t\tif (!this.#settled) this.#settle(false)\n\t\treturn confirmed\n\t}\n\n\t// The composite `destroy` performs, named apart from the public `end` that closes standard input.\n\tasync #conclude(): Promise<void> {\n\t\tawait this.stop()\n\t\tthis.#teardown()\n\t}\n}\n","import type { Interface as ReadLineInterface } from 'node:readline'\nimport type { EmitterInterface } from '@orkestrel/emitter'\nimport type { ProcessEventMap, ProcessExit, ProcessInterface, ProcessOptions } from '@src/core'\nimport { Buffer } from 'node:buffer'\nimport { createInterface } from 'node:readline'\nimport { Emitter } from '@orkestrel/emitter'\nimport { PROCESS_BACKLOG } from '@src/core'\nimport { snapshotCommand } from '../cloners.js'\nimport { validateBytes, validateCommand, validateTimer, validateWorkspace } from '../helpers.js'\nimport { Supervisor } from './Supervisor.js'\n\n/**\n * Supervises one child, frames its standard output into lines under a bounded backlog, and keeps\n * every observation channel aligned at termination.\n *\n * @remarks\n * The child's ending and the supervision's ending are distinct. `pid`, `code`, and `signal` read\n * the host child directly, so they expose native exit as soon as the host records it. `settled`,\n * `exit`, `evidence`, and `lines` reach one terminal moment after the read channels close or the\n * bounded `drain` window cuts them off. That window is armed by the child's native exit and by a\n * termination this package initiated, so every way a child can end reaches the moment. The terminal\n * routine freezes `evidence` and ends `lines` before it destroys stdout, stderr, or the emitter, so\n * the push channel never disappears while a pull channel can still change or wait indefinitely.\n *\n * Standard output is framed through `readline` into a single-consumer stream. Lines already framed\n * and queued remain available through the terminal moment, while bytes arriving after a requested\n * termination may be cut off. Standard error is forwarded through the live `stderr` event and\n * retained as a byte-bounded raw tail until that same moment. `stop` ends the child tree and the\n * observation surfaces. `destroy` performs that stop and then destroys the emitter after the\n * frozen terminal state exists.\n *\n * @example\n * ```ts\n * import { Process } from '@orkestrel/process/server'\n *\n * const child = new Process({\n * \tcommand: { file: 'node', arguments: ['--version'] },\n * \tworkspace: process.cwd(),\n * })\n * const exit = await child.exit\n * await child.destroy()\n * ```\n */\nexport class Process implements ProcessInterface {\n\treadonly #emitter: Emitter<ProcessEventMap>\n\treadonly #engine: Supervisor\n\treadonly #reader: ReadLineInterface\n\treadonly #backlog: number\n\treadonly #lines: AsyncIterable<string>\n\treadonly #queue: string[] = []\n\treadonly #waiters: Array<PromiseWithResolvers<IteratorResult<string, void>>> = []\n\t#head = 0\n\t#pending = 0\n\t#requested = false\n\t#paused = false\n\t#truncated = false\n\t#ended = false\n\n\t/**\n\t * Spawns one child process and begins stream capture.\n\t *\n\t * @param options - Command, workspace, termination, capture, stdin, and observation settings\n\t * @throws A {@link ProcessError} coded `invalid` when an option or command string is malformed\n\t */\n\tconstructor(options: ProcessOptions) {\n\t\t// Every option and command property is read once, here, before the engine spawns. Reading a\n\t\t// property runs the caller's own getter, so the engine receives these plain values and re-reads\n\t\t// none of them: a getter runs once whether the construction succeeds or is refused.\n\t\t// The engine's own options are validated first, in the order the engine reads them, and the\n\t\t// line pipeline's `backlog` after them, so a construction carrying more than one invalid option\n\t\t// reports the same option a single supervised face has always reported, and a malformed\n\t\t// `backlog` still refuses while nothing has been spawned.\n\t\tconst source = options.command\n\t\tconst workspace = options.workspace\n\t\tconst grace = options.grace\n\t\tconst drain = options.drain\n\t\tconst evidence = options.evidence\n\t\tconst backlog = options.backlog\n\t\tconst delivery = options.delivery\n\t\tconst writable = options.writable\n\t\tconst signal = options.signal\n\t\tconst on = options.on\n\t\tconst error = options.error\n\t\tconst command = snapshotCommand(source)\n\t\tvalidateCommand(command)\n\t\tvalidateWorkspace(workspace)\n\t\tvalidateTimer(grace, \"option 'grace'\")\n\t\tvalidateTimer(drain, \"option 'drain'\")\n\t\tvalidateTimer(delivery, \"option 'delivery'\")\n\t\tvalidateBytes(evidence, \"option 'evidence'\", 0)\n\t\tvalidateBytes(backlog, \"option 'backlog'\", 1)\n\t\tthis.#emitter = new Emitter<ProcessEventMap>({\n\t\t\t...(on === undefined ? {} : { on }),\n\t\t\t...(error === undefined ? {} : { error }),\n\t\t})\n\t\tthis.#backlog = backlog ?? PROCESS_BACKLOG\n\t\tthis.#lines = Object.freeze({ [Symbol.asyncIterator]: this.#iterate.bind(this) })\n\t\tthis.#engine = new Supervisor(\n\t\t\t{\n\t\t\t\tcommand,\n\t\t\t\tworkspace,\n\t\t\t\t...(grace === undefined ? {} : { grace }),\n\t\t\t\t...(drain === undefined ? {} : { drain }),\n\t\t\t\t...(evidence === undefined ? {} : { evidence }),\n\t\t\t\t...(delivery === undefined ? {} : { delivery }),\n\t\t\t\t...(writable === undefined ? {} : { writable }),\n\t\t\t\t...(signal === undefined ? {} : { signal }),\n\t\t\t},\n\t\t\t{\n\t\t\t\tchunk: this.#reportStderr.bind(this),\n\t\t\t\tfault: this.#reportFault.bind(this),\n\t\t\t\trelieve: this.#releaseBackpressure.bind(this),\n\t\t\t\tclose: this.#closeReader.bind(this),\n\t\t\t\tterminal: this.#reportExit.bind(this),\n\t\t\t\tteardown: this.#emitter.destroy.bind(this.#emitter),\n\t\t\t},\n\t\t)\n\t\t// The host delivers no output before this synchronous constructor returns, so framing attaches\n\t\t// here without losing a byte the engine already spawned for.\n\t\tthis.#reader = createInterface({ input: this.#engine.stdout, crlfDelay: Infinity })\n\t\tthis.#reader.on('line', this.#push.bind(this))\n\t\tthis.#reader.once('close', this.#finish.bind(this))\n\t}\n\n\t/** Holds the host process id, fixed when construction returns, or `undefined` when the spawn produced none. */\n\tget pid(): number | undefined {\n\t\treturn this.#engine.pid\n\t}\n\n\t/** Holds the exit code the host recorded, or `null` while the child has not exited and when a signal ended it. */\n\tget code(): number | null {\n\t\treturn this.#engine.code\n\t}\n\n\t/** Holds the terminating signal name the host recorded, or `null` while the child has not exited and when it exited on its own. */\n\tget signal(): string | null {\n\t\treturn this.#engine.signal\n\t}\n\n\t/** Holds the typed lifecycle observation surface. */\n\tget emitter(): EmitterInterface<ProcessEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\t/** Yields the captured stdout lines, in arrival order, ending after queued lines at the terminal moment. */\n\tget lines(): AsyncIterable<string> {\n\t\treturn this.#lines\n\t}\n\n\t/** Holds the decoded byte-bounded stderr tail, frozen at the terminal moment. */\n\tget evidence(): string {\n\t\treturn this.#engine.evidence\n\t}\n\n\t/** Reports whether the `lines` stream omitted output after a retention bound was reached. */\n\tget truncated(): boolean {\n\t\treturn this.#truncated\n\t}\n\n\t/** Reports whether the terminal moment arrived and `exit` settled. */\n\tget settled(): boolean {\n\t\treturn this.#engine.settled\n\t}\n\n\t/** Reports whether termination began, including after the terminal moment. */\n\tget stopping(): boolean {\n\t\treturn this.#engine.stopping\n\t}\n\n\t/** Settles with the terminal child state, observed once after stream close or the drain cutoff. */\n\tget exit(): Promise<ProcessExit> {\n\t\treturn this.#engine.exit\n\t}\n\n\t/**\n\t * Writes one line to the open standard-input channel.\n\t *\n\t * @remarks\n\t * Never rejects. `true` means the host accepted the bytes without reporting a fault; it does not\n\t * prove that the child read them. An ordinary write settles when the kernel accepts it. Only a\n\t * full pipe can hold the write unconfirmed. The `delivery` option can bound that wait, and every\n\t * terminal teardown path settles pending writes. On Windows 11 with Node v24.18.1, measured on\n\t * 2026-08-21, a child that closes its own file descriptor 0 can leave the parent pipe writable:\n\t * the write can settle `true` without a callback error or a stream error while the child remains\n\t * alive. After `stop` or `destroy` begins, a later call settles `false`. Version 0.0.4 could settle\n\t * that call `true` before teardown destroyed the pipe; returning `false` avoids claiming delivery\n\t * for bytes the package is about to discard.\n\t *\n\t * @param text - The line text without its trailing newline\n\t * @returns True if the host accepted the bytes without reporting a fault; false otherwise (the channel was closed, destroyed, ended, failed, or the write remained unconfirmed through `delivery`)\n\t */\n\tsend(text: string): Promise<boolean> {\n\t\treturn this.#engine.deliver(Buffer.from(`${text}\\n`, 'utf8'))\n\t}\n\n\t/**\n\t * Terminates the child process tree and reaches the terminal observation moment.\n\t *\n\t * @remarks\n\t * Never rejects, and every call shares one termination. After the termination sequence returns,\n\t * confirmed or not, it waits at most `drain` for the read channels to close, then cuts them off\n\t * and settles `exit` when they remain open. A cutoff reached before the native exit reports the\n\t * `code` and `signal` the host had recorded by then, which is `null` for a child still running.\n\t *\n\t * @returns True if the child's native exit was observed; false otherwise (the confirmation deadline elapsed without it)\n\t */\n\tstop(): Promise<boolean> {\n\t\treturn this.#engine.stop()\n\t}\n\n\t/**\n\t * Stops the child and destroys the observation emitter after the terminal state freezes.\n\t *\n\t * @remarks\n\t * Always resolves, including when termination was never confirmed. Every call shares one barrier.\n\t *\n\t * @returns The stable barrier shared by every call\n\t */\n\tdestroy(): Promise<void> {\n\t\treturn this.#engine.destroy()\n\t}\n\n\t#iterate(): AsyncIterator<string, void, void> {\n\t\tthis.#requested = true\n\t\treturn Object.freeze({ next: this.#next.bind(this) })\n\t}\n\n\t#next(): Promise<IteratorResult<string, void>> {\n\t\tconst line = this.#take()\n\t\tif (line !== undefined) return Promise.resolve(Object.freeze({ done: false, value: line }))\n\t\tif (this.#ended) return Promise.resolve(Object.freeze({ done: true, value: undefined }))\n\t\tconst waiter = Promise.withResolvers<IteratorResult<string, void>>()\n\t\tthis.#waiters.push(waiter)\n\t\treturn waiter.promise\n\t}\n\n\t// Dequeues through a read index, so draining a long backlog stays linear.\n\t#take(): string | undefined {\n\t\tif (this.#head >= this.#queue.length) return undefined\n\t\tconst line = this.#queue[this.#head]\n\t\tthis.#queue[this.#head] = ''\n\t\tthis.#head += 1\n\t\tif (this.#head >= this.#queue.length) {\n\t\t\tthis.#queue.length = 0\n\t\t\tthis.#head = 0\n\t\t}\n\t\tif (line === undefined) return undefined\n\t\tthis.#pending -= Buffer.byteLength(line) + 1\n\t\tthis.#relieve()\n\t\treturn line\n\t}\n\n\t#push(line: string): void {\n\t\tif (this.#ended) return\n\t\tconst waiter = this.#waiters.shift()\n\t\tif (waiter !== undefined) {\n\t\t\twaiter.resolve(Object.freeze({ done: false, value: line }))\n\t\t\treturn\n\t\t}\n\t\t// A retained line costs its payload plus the newline that framed it, so an empty line still\n\t\t// costs a byte and a flood of them reaches the mark.\n\t\tconst bytes = Buffer.byteLength(line) + 1\n\t\t// With no consumer ever attached, retention stops at the mark and the stream keeps draining\n\t\t// so the child can exit; a consumer attaching later receives the head, a gap, then the live\n\t\t// stream.\n\t\tconst stopping = this.#engine.stopping\n\t\tconst limit = stopping ? this.#backlog * 2 : this.#backlog\n\t\tif ((!this.#requested || stopping) && this.#pending + bytes > limit) {\n\t\t\tthis.#truncated = true\n\t\t\treturn\n\t\t}\n\t\tthis.#queue.push(line)\n\t\tthis.#pending += bytes\n\t\tthis.#restrain()\n\t}\n\n\t#restrain(): void {\n\t\tif (this.#paused || this.#engine.stopping || !this.#requested) return\n\t\tif (this.#pending < this.#backlog) return\n\t\tthis.#paused = true\n\t\tthis.#reader.pause()\n\t}\n\n\t#relieve(): void {\n\t\tif (!this.#paused || this.#ended) return\n\t\tif (!this.#engine.stopping && this.#pending > this.#backlog / 2) return\n\t\tthis.#paused = false\n\t\tthis.#reader.resume()\n\t}\n\n\t#finish(): void {\n\t\tif (this.#ended) return\n\t\tthis.#ended = true\n\t\tthis.#paused = false\n\t\tfor (const waiter of this.#waiters) {\n\t\t\twaiter.resolve(Object.freeze({ done: true, value: undefined }))\n\t\t}\n\t\tthis.#waiters.length = 0\n\t}\n\n\t// The engine publishes nothing itself, so each moment it hands over is republished here on this\n\t// face's own typed event map. A generic `emit` cannot be bound to one event without collapsing\n\t// its payload to the first member of the map.\n\t#reportStderr(chunk: string): void {\n\t\tthis.#emitter.emit('stderr', chunk)\n\t}\n\n\t#reportFault(cause: unknown): void {\n\t\tthis.#emitter.emit('error', cause)\n\t}\n\n\t#reportExit(exit: ProcessExit): void {\n\t\tthis.#emitter.emit('exit', exit)\n\t}\n\n\t// Closing readline ends pending reads while preserving lines already framed and queued.\n\t#closeReader(): void {\n\t\tthis.#reader.close()\n\t}\n\n\t// A paused stdout holds the child's own write, and therefore its exit. Bound the retained head,\n\t// then release backpressure before the engine signals; later lines drop at the teardown cap\n\t// instead of pausing the reader again.\n\t#releaseBackpressure(): void {\n\t\tthis.#capBacklog()\n\t\tthis.#relieve()\n\t}\n\n\t#capBacklog(): void {\n\t\tconst limit = this.#backlog * 2\n\t\twhile (this.#pending > limit && this.#queue.length > this.#head) {\n\t\t\tconst line = this.#queue.pop()\n\t\t\tif (line === undefined) break\n\t\t\tthis.#pending -= Buffer.byteLength(line) + 1\n\t\t\tthis.#truncated = true\n\t\t}\n\t}\n}\n","import type { EmitterInterface } from '@orkestrel/emitter'\nimport type {\n\tProcessExit,\n\tProcessInterface,\n\tProcessManagerEventMap,\n\tProcessManagerInterface,\n\tProcessManagerOptions,\n\tProcessOptions,\n} from '@src/core'\nimport { isString } from '@orkestrel/contract'\nimport { Emitter } from '@orkestrel/emitter'\nimport { createDuplicateError, createProtocolError } from '@src/core'\nimport { Process } from './Process.js'\n\n/**\n * Launches supervised children under caller-chosen ids, evicts each one as it settles, and destroys\n * every live child on teardown.\n *\n * @remarks\n * A child launched under an id joins the registry and emits `launch`; when it settles it removes\n * itself and emits `exit`, so `count` and `processes` reflect only live children. The id is reserved\n * before the child is constructed and released when construction throws, so a refused launch never\n * strands its key. Eviction follows the child's own `exit` promise, which no listener can forge, so\n * it lands one microtask after the child's public `exit` event: a listener on that event still sees\n * the child registered. `launch` throws a {@link createDuplicateError} when the id is already live\n * and a {@link createProtocolError} after `destroy` has begun, including when the caller's own option\n * getter begins that teardown mid-construction — a spawn fault surfaces through the returned child's\n * `exit`, never from `launch`. `destroy` awaits every child's own teardown, including the teardown\n * of a child a lost race refused, which destroys each child's observation emitter and leaves every\n * subscription on it silently inert, then destroys the registry emitter last.\n *\n * @example\n * ```ts\n * import { ProcessManager } from '@orkestrel/process/server'\n *\n * const manager = new ProcessManager()\n * const child = manager.launch('build', {\n * \tcommand: { file: 'node', arguments: ['build.js'] },\n * \tworkspace: process.cwd(),\n * })\n * await child.exit\n * await manager.destroy()\n * ```\n */\nexport class ProcessManager implements ProcessManagerInterface {\n\treadonly #emitter: Emitter<ProcessManagerEventMap>\n\treadonly #children = new Map<string, ProcessInterface>()\n\treadonly #ids = new Set<string>()\n\t// The children a launch spawned into a registry that was already being destroyed. They are never\n\t// registered, so `#teardown` cannot reach them through `#children`, and it drains this set instead.\n\treadonly #orphans = new Set<ProcessInterface>()\n\t// A guard reads `#destroying`, never `#ending !== undefined`. `destroy` assigns the boolean before\n\t// it assigns the barrier, so the boolean also covers the synchronous prefix of the teardown, which\n\t// runs while `#ending` is still `undefined`.\n\t#destroying = false\n\t#ending: Promise<void> | undefined\n\n\t/**\n\t * Constructs a process registry.\n\t *\n\t * @param options - Initial fleet-level observation hooks and listener-error handling\n\t */\n\tconstructor(options?: ProcessManagerOptions) {\n\t\tconst on = options?.on\n\t\tconst error = options?.error\n\t\tthis.#emitter = new Emitter<ProcessManagerEventMap>({\n\t\t\t...(on === undefined ? {} : { on }),\n\t\t\t...(error === undefined ? {} : { error }),\n\t\t})\n\t}\n\n\t/** Holds the typed fleet-level observation surface. */\n\tget emitter(): EmitterInterface<ProcessManagerEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\t/** Counts the live children. */\n\tget count(): number {\n\t\treturn this.#children.size\n\t}\n\n\t/**\n\t * Returns the live child under `id`, or `undefined` when none is.\n\t *\n\t * @param id - The registry key\n\t * @returns The child, or `undefined`\n\t */\n\tprocess(id: string): ProcessInterface | undefined {\n\t\treturn this.#children.get(id)\n\t}\n\n\t/**\n\t * Returns a snapshot of every live child.\n\t *\n\t * @returns The live children in launch order\n\t */\n\tprocesses(): readonly ProcessInterface[] {\n\t\treturn [...this.#children.values()]\n\t}\n\n\t/**\n\t * Spawns and registers one child under `id`.\n\t *\n\t * @remarks\n\t * {@link Process} reads every option before it spawns, so a caller's own option getter runs while\n\t * nothing has started and a throw from one strands no process. A getter that begins `destroy`\n\t * without throwing is the one remaining race: the child is already spawned, so the launch is\n\t * refused with a {@link createProtocolError} and that child is destroyed rather than adopted, its\n\t * teardown bounded by `grace` plus the confirmation window. The `protocol` refusal throws\n\t * synchronously, and the `destroy` barrier covers that teardown, so the refused child reaches its\n\t * terminal moment before the barrier resolves.\n\t *\n\t * @param id - The registry key, unique among live children\n\t * @param options - The child construction options\n\t * @returns The launched child\n\t * @throws A {@link ProcessError} coded `duplicate` when `id` is already live, `protocol` when the registry is being destroyed, or `invalid` when an option or command string is malformed\n\t */\n\tlaunch(id: string, options: ProcessOptions): ProcessInterface {\n\t\tif (this.#destroying) throw createProtocolError(id)\n\t\tif (this.#ids.has(id)) throw createDuplicateError(id)\n\t\tthis.#ids.add(id)\n\t\tconst child = this.#construct(id, options)\n\t\t// Reading an option runs the caller's own code, so teardown can begin between the check above\n\t\t// and the child that is now spawned. A registry being destroyed adopts nothing: the child is\n\t\t// torn down here, the reservation goes back, and the launch is refused. The child joins\n\t\t// `#orphans` before its teardown starts, so `#teardown` covers it however far that teardown\n\t\t// has already progressed.\n\t\tif (this.#destroying) {\n\t\t\tthis.#ids.delete(id)\n\t\t\tthis.#orphans.add(child)\n\t\t\tvoid child.destroy()\n\t\t\tthrow createProtocolError(id)\n\t\t}\n\t\tthis.#children.set(id, child)\n\t\tvoid child.exit.then((exit) => this.#evict(id, child, exit))\n\t\tthis.#emitter.emit('launch', id)\n\t\treturn child\n\t}\n\n\t/**\n\t * Terminates the named children and awaits their exit.\n\t *\n\t * @param ids - The registry keys to stop\n\t * @returns True if every named child was live and its exit was confirmed; false otherwise\n\t */\n\tstop(ids: readonly string[]): Promise<boolean>\n\t/**\n\t * Terminates one child and awaits its exit.\n\t *\n\t * @param id - The registry key to stop\n\t * @returns True if the child was live and its exit was confirmed; false otherwise (the id was not live, or the confirmation deadline elapsed)\n\t */\n\tstop(id: string): Promise<boolean>\n\t/**\n\t * Terminates every live child and awaits their exit.\n\t *\n\t * @returns A promise that resolves after every child stops\n\t */\n\tstop(): Promise<void>\n\tstop(target?: string | readonly string[]): Promise<boolean | void> {\n\t\tif (target === undefined) return this.#stopAll()\n\t\tif (isString(target)) return this.#stopOne(target)\n\t\treturn this.#stopMany(target)\n\t}\n\n\t/**\n\t * Stops every child, then destroys the registry emitter last.\n\t *\n\t * @remarks\n\t * Always resolves, and refuses a later `launch` with a {@link createProtocolError}. Each child is\n\t * destroyed rather than merely stopped, so its own observation emitter is destroyed too and every\n\t * subscription on it goes silently inert.\n\t *\n\t * @returns The stable barrier shared by every call\n\t */\n\tdestroy(): Promise<void> {\n\t\tif (this.#ending !== undefined) return this.#ending\n\t\tthis.#destroying = true\n\t\tthis.#ending = this.#teardown()\n\t\treturn this.#ending\n\t}\n\n\t// Releases the reservation when construction throws, so a refused launch strands no id.\n\t#construct(id: string, options: ProcessOptions): ProcessInterface {\n\t\ttry {\n\t\t\treturn new Process(options)\n\t\t} catch (error) {\n\t\t\tthis.#ids.delete(id)\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t#evict(id: string, child: ProcessInterface, exit: ProcessExit): void {\n\t\tif (this.#children.get(id) !== child) return\n\t\tthis.#children.delete(id)\n\t\tthis.#ids.delete(id)\n\t\tthis.#emitter.emit('exit', id, exit)\n\t}\n\n\tasync #stopOne(id: string): Promise<boolean> {\n\t\tconst child = this.#children.get(id)\n\t\tif (child === undefined) return false\n\t\treturn child.stop()\n\t}\n\n\tasync #stopMany(ids: readonly string[]): Promise<boolean> {\n\t\tconst stopped = await Promise.all(ids.map((id) => this.#stopOne(id)))\n\t\treturn stopped.every((ok) => ok)\n\t}\n\n\tasync #stopAll(): Promise<void> {\n\t\tawait Promise.allSettled([...this.#children.values()].map((child) => child.stop()))\n\t}\n\n\tasync #teardown(): Promise<void> {\n\t\tawait Promise.allSettled([...this.#children.values()].map((child) => child.destroy()))\n\t\t// A launch that lost the race spawns its child after the line above read the registry, so the\n\t\t// barrier picks those children up here. Each pass takes the whole set and empties it, so a\n\t\t// child that arrives while an earlier pass is still awaiting is covered by the next one and no\n\t\t// child is awaited twice; the loop ends only on a pass that found the set empty. `destroy` on\n\t\t// a child is idempotent, so awaiting it here joins the teardown `launch` already began rather\n\t\t// than starting a second one. Every loser of the race is therefore covered, however many of\n\t\t// them one turn produces: a loser can only be a `launch` that passed the guard before\n\t\t// `#destroying` was set, and every such call is already on the stack when this runs.\n\t\twhile (this.#orphans.size > 0) {\n\t\t\tconst orphans = [...this.#orphans]\n\t\t\tthis.#orphans.clear()\n\t\t\tawait Promise.allSettled(orphans.map((child) => child.destroy()))\n\t\t}\n\t\t// A destroyed registry holds nothing: a child whose stdio a descendant still holds would\n\t\t// otherwise linger here until a close event that may never arrive.\n\t\tthis.#children.clear()\n\t\tthis.#ids.clear()\n\t\tthis.#emitter.destroy()\n\t}\n}\n","import type { EmitterInterface } from '@orkestrel/emitter'\nimport type { ProcessExit, SessionEventMap, SessionInterface, SessionOptions } from '@src/core'\nimport { Buffer } from 'node:buffer'\nimport { Emitter } from '@orkestrel/emitter'\nimport { Supervisor } from './Supervisor.js'\n\n/**\n * Supervises one child and publishes its standard output as raw bytes.\n *\n * @remarks\n * This is the transport face of the supervision engine `Process` also composes. It frames nothing,\n * retains nothing, and decodes nothing on the output side: every chunk the host delivers becomes one\n * `stdout` event carrying that chunk's bytes, in arrival order, so a consumer speaking a\n * length-prefixed or delimiter-framed protocol reads exactly what the child wrote and frames it\n * itself. Standard error is decoded and forwarded as `stderr`, with the same byte-bounded `evidence`\n * tail a `Process` retains, because a diagnostic stream is read rather than parsed.\n *\n * Each emitted chunk is this session's own copy, and a plain `Uint8Array` rather than the host buffer\n * the read produced, so a consumer keeps it, mutates it, concatenates it, and reads its whole backing\n * buffer without reaching memory the host still manages and without depending on a host type.\n *\n * The standard-input channel is open from the spawn, and `end` closes it without terminating\n * anything. That is the member a cooperative protocol reaches for: the child observes end of input\n * and exits on its own, which `ending` reports. `stop` and `destroy` remain the terminations, and\n * `exit` remains the terminal moment — the native exit plus at most `drain` while a descendant holds\n * the inherited read ends.\n *\n * @example\n * ```ts\n * import { Session } from '@orkestrel/process/server'\n *\n * const session = new Session({\n * \tcommand: { file: 'node', arguments: ['-e', 'process.stdin.pipe(process.stdout)'] },\n * \tworkspace: process.cwd(),\n * })\n * ```\n */\nexport class Session implements SessionInterface {\n\treadonly #emitter: Emitter<SessionEventMap>\n\treadonly #engine: Supervisor\n\treadonly #output: (chunk: unknown) => void\n\n\t/**\n\t * Spawns one child process and begins byte capture.\n\t *\n\t * @param options - Command, workspace, termination, evidence, stdin, and observation settings\n\t * @throws A {@link ProcessError} coded `invalid` when an option or command string is malformed\n\t */\n\tconstructor(options: SessionOptions) {\n\t\t// Every option is read once, here, before the engine reads the command and spawns anything.\n\t\t// Reading a property runs the caller's own getter, so a read after the spawn would let that\n\t\t// getter throw while a live child exists and nobody holds a reference to it. The engine\n\t\t// receives the plain values in the following literal and validates each one before it spawns,\n\t\t// so an invalid option and a throwing getter alike refuse construction while nothing has\n\t\t// started.\n\t\tconst command = options.command\n\t\tconst workspace = options.workspace\n\t\tconst grace = options.grace\n\t\tconst drain = options.drain\n\t\tconst evidence = options.evidence\n\t\tconst delivery = options.delivery\n\t\tconst signal = options.signal\n\t\tconst on = options.on\n\t\tconst error = options.error\n\t\tthis.#emitter = new Emitter<SessionEventMap>({\n\t\t\t...(on === undefined ? {} : { on }),\n\t\t\t...(error === undefined ? {} : { error }),\n\t\t})\n\t\tthis.#output = this.#publish.bind(this)\n\t\tthis.#engine = new Supervisor(\n\t\t\t{\n\t\t\t\tcommand,\n\t\t\t\tworkspace,\n\t\t\t\t// The channel stays open from the spawn until `end` closes it, so a session selects\n\t\t\t\t// nothing here and declares no `writable` option of its own.\n\t\t\t\twritable: true,\n\t\t\t\t...(grace === undefined ? {} : { grace }),\n\t\t\t\t...(drain === undefined ? {} : { drain }),\n\t\t\t\t...(evidence === undefined ? {} : { evidence }),\n\t\t\t\t...(delivery === undefined ? {} : { delivery }),\n\t\t\t\t...(signal === undefined ? {} : { signal }),\n\t\t\t},\n\t\t\t{\n\t\t\t\tchunk: this.#reportStderr.bind(this),\n\t\t\t\tfault: this.#reportFault.bind(this),\n\t\t\t\tclose: this.#closeOutput.bind(this),\n\t\t\t\tterminal: this.#reportExit.bind(this),\n\t\t\t\tteardown: this.#emitter.destroy.bind(this.#emitter),\n\t\t\t},\n\t\t)\n\t\t// The host delivers no output before this synchronous constructor returns, so the consumer\n\t\t// attaches here without losing a byte the engine already spawned for. Attaching is also what\n\t\t// puts stdout in flowing mode, which is what a session wants: it retains nothing, and a paused\n\t\t// stream would hold the child's own write and therefore its exit.\n\t\tthis.#engine.stdout.on('data', this.#output)\n\t}\n\n\t/** Holds the host process id, fixed when construction returns, or `undefined` when the spawn produced none. */\n\tget pid(): number | undefined {\n\t\treturn this.#engine.pid\n\t}\n\n\t/** Holds the exit code the host recorded, or `null` while the child has not exited and when a signal ended it. */\n\tget code(): number | null {\n\t\treturn this.#engine.code\n\t}\n\n\t/** Holds the terminating signal name the host recorded, or `null` while the child has not exited and when it exited on its own. */\n\tget signal(): string | null {\n\t\treturn this.#engine.signal\n\t}\n\n\t/** Holds the typed lifecycle observation surface. */\n\tget emitter(): EmitterInterface<SessionEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\t/** Holds the decoded byte-bounded stderr tail, frozen at the terminal moment. */\n\tget evidence(): string {\n\t\treturn this.#engine.evidence\n\t}\n\n\t/** Reports whether the terminal moment arrived and `exit` settled. */\n\tget settled(): boolean {\n\t\treturn this.#engine.settled\n\t}\n\n\t/** Reports whether termination began, including after the terminal moment. `end` never turns it true. */\n\tget stopping(): boolean {\n\t\treturn this.#engine.stopping\n\t}\n\n\t/** Settles at the child's own ending, awaited without the terminal moment's drain window. */\n\tget ending(): Promise<void> {\n\t\treturn this.#engine.ending\n\t}\n\n\t/** Settles with the terminal child state, observed once after stream close or the drain cutoff. */\n\tget exit(): Promise<ProcessExit> {\n\t\treturn this.#engine.exit\n\t}\n\n\t/**\n\t * Writes raw bytes to the open standard-input channel.\n\t *\n\t * @remarks\n\t * Never rejects, and appends no terminator: the child receives exactly these bytes. `true` means\n\t * the host accepted them without reporting a fault; it does not prove that the child read them.\n\t * The channel can queue the payload, so treat the array as owned by the channel until the\n\t * returned promise settles.\n\t *\n\t * @param bytes - The payload to write, already framed by the caller\n\t * @returns True if the host accepted the bytes without reporting a fault; false otherwise (the channel was closed, destroyed, ended, failed, or the write remained unconfirmed through `delivery`)\n\t */\n\twrite(bytes: Uint8Array): Promise<boolean> {\n\t\treturn this.#engine.deliver(bytes)\n\t}\n\n\t/**\n\t * Closes the standard-input channel and leaves the child running.\n\t *\n\t * @remarks\n\t * Never rejects and terminates nothing: `stopping` stays false and the terminal moment does not\n\t * arrive. Every call shares one barrier, which resolves after the host flushes the writes it had\n\t * already accepted. A later `write` resolves `false`.\n\t *\n\t * @returns The stable barrier shared by every call\n\t */\n\tend(): Promise<void> {\n\t\treturn this.#engine.end()\n\t}\n\n\t/**\n\t * Terminates the child process tree and reaches the terminal observation moment.\n\t *\n\t * @remarks\n\t * Never rejects, and every call shares one termination bounded by `grace` and `drain`.\n\t *\n\t * @returns True if the child's native exit was observed; false otherwise (the confirmation deadline elapsed without it)\n\t */\n\tstop(): Promise<boolean> {\n\t\treturn this.#engine.stop()\n\t}\n\n\t/**\n\t * Stops the child and destroys the observation emitter after the terminal state freezes.\n\t *\n\t * @remarks\n\t * Always resolves, including when termination was never confirmed. Every call shares one barrier.\n\t *\n\t * @returns The stable barrier shared by every call\n\t */\n\tdestroy(): Promise<void> {\n\t\treturn this.#engine.destroy()\n\t}\n\n\t// One owned copy per host chunk, taken before the payload leaves this class. The settled check\n\t// keeps the other invariant this publisher owns: the engine hands over its terminal moment before\n\t// it destroys the read ends, so nothing this stream still holds arrives after the `exit` event.\n\t#publish(chunk: unknown): void {\n\t\tif (!Buffer.isBuffer(chunk) || this.#engine.settled) return\n\t\tthis.#emitter.emit('stdout', new Uint8Array(chunk))\n\t}\n\n\t// The engine publishes nothing itself, so each moment it hands over is republished here on this\n\t// face's own typed event map. A generic `emit` cannot be bound to one event without collapsing\n\t// its payload to the first member of the map.\n\t#reportStderr(chunk: string): void {\n\t\tthis.#emitter.emit('stderr', chunk)\n\t}\n\n\t#reportFault(cause: unknown): void {\n\t\tthis.#emitter.emit('error', cause)\n\t}\n\n\t#reportExit(exit: ProcessExit): void {\n\t\tthis.#emitter.emit('exit', exit)\n\t}\n\n\t// Releasing the consumer at the terminal moment, rather than letting the engine's stream\n\t// destruction reach it, is what keeps a `stdout` event from following the `exit` event.\n\t#closeOutput(): void {\n\t\tthis.#engine.stdout.off('data', this.#output)\n\t}\n}\n","import type {\n\tProcessInterface,\n\tProcessManagerInterface,\n\tProcessManagerOptions,\n\tProcessOptions,\n\tSessionInterface,\n\tSessionOptions,\n} from '@src/core'\nimport { Process } from './processes/Process.js'\nimport { ProcessManager } from './processes/ProcessManager.js'\nimport { Session } from './processes/Session.js'\n\n/**\n * Creates one supervised child process and returns it as a {@link ProcessInterface}, so a caller\n * holds the published contract rather than the `Process` class.\n *\n * @param options - Command, workspace, termination, evidence, stdin, and observation settings\n * @returns The launched {@link ProcessInterface}\n *\n * @example Supervise a child and read its lines\n * ```ts\n * import { createProcess } from '@orkestrel/process/server'\n *\n * const child = createProcess({\n * \tcommand: { file: 'node', arguments: ['-e', 'console.log(\"ready\"); console.log(\"done\")'] },\n * \tworkspace: process.cwd(),\n * \tgrace: 5_000, // POSIX only: the window between SIGTERM and SIGKILL\n * })\n *\n * const lines: string[] = []\n * for await (const line of child.lines) lines.push(line)\n * lines // ['ready', 'done']\n *\n * const exit = await child.exit\n * exit.code // 0\n * await child.destroy()\n * ```\n */\nexport function createProcess(options: ProcessOptions): ProcessInterface {\n\treturn new Process(options)\n}\n\n/**\n * Creates one raw byte session over a supervised child process and returns it as a\n * {@link SessionInterface}, so a caller holds the published contract rather than the `Session` class.\n *\n * @param options - Command, workspace, termination, evidence, stdin, and observation settings\n * @returns The launched {@link SessionInterface}\n *\n * @example\n * ```ts\n * import { createSession } from '@orkestrel/process/server'\n *\n * const session = createSession({\n * \tcommand: { file: 'node', arguments: ['server.js', '--stdio'] },\n * \tworkspace: process.cwd(),\n * \tgrace: 5000,\n * })\n * ```\n */\nexport function createSession(options: SessionOptions): SessionInterface {\n\treturn new Session(options)\n}\n\n/**\n * Creates one empty keyed registry of supervised child processes and returns it as a\n * {@link ProcessManagerInterface}, so a caller holds the published contract rather than the\n * `ProcessManager` class.\n *\n * @param options - Initial fleet-level observation hooks and listener-error handling\n * @returns The {@link ProcessManagerInterface} registry\n *\n * @example\n * ```ts\n * import { createProcessManager } from '@orkestrel/process/server'\n *\n * const manager = createProcessManager()\n * ```\n */\nexport function createProcessManager(options?: ProcessManagerOptions): ProcessManagerInterface {\n\treturn new ProcessManager(options)\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["hostPlatform"],"sources":["../../../src/server/cloners.ts","../../../src/server/helpers.ts","../../../src/server/processes/Supervisor.ts","../../../src/server/processes/Process.ts","../../../src/server/processes/ProcessManager.ts","../../../src/server/processes/Session.ts","../../../src/server/factories.ts","../../../src/server/processes/Execution.ts","../../../src/server/execution/execute.ts","../../../src/server/execution/executeSync.ts"],"sourcesContent":["import type { ProcessCommand } from '@src/core'\n\n/**\n * Takes one owned frozen snapshot of a caller's command.\n *\n * @remarks\n * Every public entry point snapshots before it validates, so the object validated is the object\n * spawned. Each property is read exactly once, because reading one runs the caller's own getter: a\n * command whose `file` changes between reads would otherwise validate one executable and spawn\n * another. The argument vector and the environment record are copied and frozen, so a caller\n * mutating either after the call cannot reach the spawn. An absent optional stays absent rather than\n * becoming an explicit `undefined`.\n *\n * @param command - The caller's command, whose properties may be getters\n * @returns A frozen command carrying the values read at this instant\n *\n * @example\n * ```ts\n * snapshotCommand({ file: 'git', arguments: ['status'] }) // { file: 'git', arguments: ['status'] }\n * ```\n */\nexport function snapshotCommand(command: ProcessCommand): ProcessCommand {\n\tconst file = command.file\n\tconst argumentsList = Object.freeze([...command.arguments])\n\tconst sourceEnvironment = command.environment\n\tconst environment =\n\t\tsourceEnvironment === undefined ? undefined : Object.freeze({ ...sourceEnvironment })\n\tconst input = command.input\n\tconst isolated = command.isolated\n\treturn Object.freeze({\n\t\tfile,\n\t\targuments: argumentsList,\n\t\t...(environment === undefined ? {} : { environment }),\n\t\t...(input === undefined ? {} : { input }),\n\t\t...(isolated === undefined ? {} : { isolated }),\n\t})\n}\n","import type {\n\tDetachOptions,\n\tExecutableOptions,\n\tExecuteInput,\n\tExecuteResult,\n\tProcessCommand,\n\tSpawnInput,\n} from '@src/core'\nimport type { ProcessChildInterface } from './types.js'\nimport { Buffer } from 'node:buffer'\nimport { spawn } from 'node:child_process'\nimport { statSync } from 'node:fs'\nimport { join, posix, win32 } from 'node:path'\nimport { platform as hostPlatform } from 'node:process'\nimport {\n\tboundsOf,\n\tholds,\n\tisError,\n\tisNonEmptyString,\n\tisNonNegativeInteger,\n\tisString,\n} from '@orkestrel/contract'\nimport { createInvalidError, PROCESS_PATHEXT, PROCESS_TIMER } from '@src/core'\nimport { snapshotCommand } from './cloners.js'\n\n/**\n * Trims a buffer to at most `limit` trailing bytes without splitting a UTF-8 sequence.\n *\n * @remarks\n * Keeps the tail — the diagnostic end of a stderr stream. When the cut point lands inside a\n * multibyte sequence, the start advances past the leading continuation bytes so the retained\n * bytes always begin on a code-point boundary.\n *\n * @param bytes - The accumulated bytes\n * @param limit - The maximum retained byte count\n * @returns The trailing bytes, at most `limit` and never starting mid-sequence\n *\n * @example\n * ```ts\n * trimTail(Buffer.from('hello'), 3) // <Buffer 6c 6c 6f>\n * ```\n */\nexport function trimTail(bytes: Uint8Array, limit: number): Buffer {\n\tconst buffer = Buffer.isBuffer(bytes) ? bytes : Buffer.from(bytes)\n\tif (buffer.byteLength <= limit) return buffer\n\tconst offset = buffer.byteLength - limit\n\tif (!(offset < buffer.byteLength)) return Buffer.from(buffer.subarray(offset))\n\tfor (const start of Array.from(\n\t\t{ length: Math.ceil(buffer.byteLength - offset) },\n\t\t(_, index) => offset + index,\n\t)) {\n\t\tconst byte = buffer[start]\n\t\tif (byte === undefined || (byte & 0xc0) !== 0x80) return Buffer.from(buffer.subarray(start))\n\t}\n\treturn Buffer.from(buffer.subarray(buffer.byteLength))\n}\n\n/**\n * Trims a buffer to at most `limit` leading bytes without splitting a UTF-8 sequence.\n *\n * @remarks\n * Keeps the head — the captured start of a one-shot run's output. The end retreats only when a\n * sequence genuinely spans the cut: the byte at `limit` carries the continuation bit pattern, and a\n * lead byte within the preceding three bytes declares a length that reaches it. The retained bytes\n * then end on a code-point boundary and decode without a replacement character. A byte at `limit`\n * that carries the continuation pattern without such a lead byte is invalid UTF-8 rather than a\n * split sequence, so the full `limit` survives instead of a valid byte being dropped for it.\n *\n * @param bytes - The accumulated bytes\n * @param limit - The maximum retained byte count\n * @returns The leading bytes, at most `limit` and never ending mid-sequence\n *\n * @example\n * ```ts\n * trimHead(Buffer.from('hello'), 3) // <Buffer 68 65 6c>\n * ```\n */\nexport function trimHead(bytes: Uint8Array, limit: number): Buffer {\n\tconst buffer = Buffer.isBuffer(bytes) ? bytes : Buffer.from(bytes)\n\tif (buffer.byteLength <= limit) return buffer\n\tconst excluded = buffer[limit]\n\tif (excluded === undefined || (excluded & 0xc0) !== 0x80)\n\t\treturn Buffer.from(buffer.subarray(0, limit))\n\t// A lead byte opens at most a four-byte sequence, so only the three bytes before the cut can hold\n\t// the lead of a sequence that reaches it.\n\tconst floor = Math.max(0, limit - 3)\n\tfor (const start of Array.from(\n\t\t{ length: Math.max(0, Math.floor(limit - floor)) },\n\t\t(_, index) => limit - 1 - index,\n\t)) {\n\t\tconst lead = buffer[start]\n\t\tif (lead !== undefined && (lead & 0xc0) !== 0x80) {\n\t\t\tconst span =\n\t\t\t\t(lead & 0xe0) === 0xc0 ? 2 : (lead & 0xf0) === 0xe0 ? 3 : (lead & 0xf8) === 0xf0 ? 4 : 1\n\t\t\tif (start + span > limit) return Buffer.from(buffer.subarray(0, start))\n\t\t\tbreak\n\t\t}\n\t}\n\treturn Buffer.from(buffer.subarray(0, limit))\n}\n\n/**\n * Bounds one delivered stream chunk to the bytes a capture still has room for.\n *\n * @remarks\n * A chunk that is not a buffer contributes nothing and reports `undefined` rather than throwing,\n * because a stream `data` listener receives an `unknown` payload. The cut is byte-exact and might\n * land inside a multibyte sequence, because {@link buildExecuteResult} performs the single\n * code-point-boundary trim over the whole capture rather than over each chunk. Give the capture one\n * byte more room than its limit, so that final trim can read the first excluded byte and retreat off\n * a split sequence. A chunk that fits its room is returned as the delivered buffer itself rather\n * than a copy, because a capture appending it copies again and never writes through it; a chunk that\n * overruns its room returns a copy of the bytes that fit. Treat the return as read-only either way.\n *\n * @param chunk - The delivered chunk, ignored when it is not a buffer\n * @param room - The bytes the capture still accepts\n * @returns The bytes to retain, or `undefined` when the chunk contributes none\n *\n * @example\n * ```ts\n * captureChunk(Buffer.from('hello'), 3) // <Buffer 68 65 6c>\n * ```\n */\nexport function captureChunk(chunk: unknown, room: number): Buffer | undefined {\n\tif (!Buffer.isBuffer(chunk) || room <= 0) return undefined\n\tif (chunk.byteLength <= room) return chunk\n\treturn Buffer.from(chunk.subarray(0, room))\n}\n\n/**\n * Renders one command into its diagnostic command line.\n *\n * @param command - The executable and its argument vector\n * @returns The space-joined command line, for an {@link ExecuteResult} and error messages\n *\n * @example\n * ```ts\n * formatCommand({ file: 'git', arguments: ['status'] }) // 'git status'\n * ```\n */\nexport function formatCommand(command: ProcessCommand): string {\n\treturn [command.file, ...command.arguments].join(' ')\n}\n\n/**\n * Reads one environment variable under an explicit platform's key rules.\n *\n * @remarks\n * Windows environment keys are case-insensitive, so a merged record can hold `Path` where the\n * caller asks for `PATH`. The exact key is tried first and a folded scan runs only for `win32`.\n *\n * @param environment - The environment record to read\n * @param name - The variable name\n * @param platform - The platform whose key rules apply\n * @returns The value, or `undefined` when the environment declares no such variable\n *\n * @example\n * ```ts\n * readPlatformVariable({ Path: 'C:\\\\Windows' }, 'PATH', 'win32') // 'C:\\\\Windows'\n * ```\n */\nexport function readPlatformVariable(\n\tenvironment: Readonly<Record<string, string | undefined>>,\n\tname: string,\n\tplatform: NodeJS.Platform,\n): string | undefined {\n\tconst direct = environment[name]\n\tif (direct !== undefined) return direct\n\tif (platform !== 'win32') return undefined\n\tconst target = name.toUpperCase()\n\tfor (const [key, value] of Object.entries(environment)) {\n\t\tif (key.toUpperCase() === target) return value\n\t}\n\treturn undefined\n}\n\n/**\n * Reads one environment variable the way the current host resolves it.\n *\n * @param environment - The environment record to read\n * @param name - The variable name\n * @returns The value, or `undefined` when the environment declares no such variable\n *\n * @example\n * ```ts\n * readVariable({ PATH: '/usr/bin' }, 'PATH') // '/usr/bin'\n * ```\n */\nexport function readVariable(\n\tenvironment: Readonly<Record<string, string | undefined>>,\n\tname: string,\n): string | undefined {\n\treturn readPlatformVariable(environment, name, hostPlatform)\n}\n\n/**\n * Merges environment layers under an explicit platform's key rules.\n *\n * @remarks\n * Later maps override earlier ones and an `undefined` value unsets a key. For `win32` the keys fold\n * case-insensitively and the last writer wins, so `PATH` followed by `Path` yields one variable\n * rather than two the host would resolve unpredictably.\n *\n * @param platform - The platform whose key rules apply\n * @param parent - The parent environment layer\n * @param isolated - If `true`, the parent environment is excluded; if `false`, the overrides layer over it\n * @param base - The command's own environment overrides\n * @param override - Per-invocation overrides applied last\n * @returns The environment for a spawn, carrying no unset key\n *\n * @example\n * ```ts\n * mergePlatformEnvironment('linux', {}, false, { TOKEN: 'a' }, { TOKEN: undefined }) // TOKEN unset\n * ```\n */\nexport function mergePlatformEnvironment(\n\tplatform: NodeJS.Platform,\n\tparent: Readonly<Record<string, string | undefined>>,\n\tisolated: boolean,\n\tbase?: Readonly<Record<string, string | undefined>>,\n\toverride?: Readonly<Record<string, string | undefined>>,\n): NodeJS.ProcessEnv {\n\tconst folded = platform === 'win32'\n\tconst layers: ReadonlyArray<Readonly<Record<string, string | undefined>>> = [\n\t\tisolated ? {} : parent,\n\t\tbase ?? {},\n\t\toverride ?? {},\n\t]\n\tconst entries = new Map<string, readonly [key: string, value: string]>()\n\tfor (const layer of layers) {\n\t\tfor (const [key, value] of Object.entries(layer)) {\n\t\t\tconst token = folded ? key.toUpperCase() : key\n\t\t\tif (value === undefined) {\n\t\t\t\tentries.delete(token)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tentries.set(token, [key, value])\n\t\t}\n\t}\n\tconst merged: NodeJS.ProcessEnv = {}\n\tfor (const [key, value] of entries.values()) merged[key] = value\n\treturn merged\n}\n\n/**\n * Merges environment overrides into the environment one child receives on the current host.\n *\n * @param isolated - If `true`, the parent environment is excluded; if `false`, the overrides layer over it\n * @param base - The command's own environment overrides\n * @param override - Per-invocation overrides applied last\n * @returns The environment for a spawn, carrying no unset key\n *\n * @example\n * ```ts\n * mergeEnvironment(true, { TOKEN: 'a' }) // { TOKEN: 'a' }\n * ```\n */\nexport function mergeEnvironment(\n\tisolated: boolean,\n\tbase?: Readonly<Record<string, string | undefined>>,\n\toverride?: Readonly<Record<string, string | undefined>>,\n): NodeJS.ProcessEnv {\n\treturn mergePlatformEnvironment(hostPlatform, process.env, isolated, base, override)\n}\n\n/**\n * Checks whether a path names a regular file.\n *\n * @remarks\n * Existence alone does not make a lookup hit: a directory named `git` on `PATH` is not the `git`\n * command. An unreadable or malformed path reports `false` rather than throwing.\n *\n * @param target - The absolute or relative path to inspect\n * @returns True if the path resolves to a regular file; false otherwise\n *\n * @example\n * ```ts\n * isFile(process.execPath) // true\n * ```\n */\nexport function isFile(target: string): boolean {\n\treturn holds(() => statSync(target, { throwIfNoEntry: false })?.isFile() === true)\n}\n\n/**\n * Builds the executable candidates an explicit platform would search.\n *\n * @remarks\n * Windows alone needs this list: the host searches the working directory before `PATH` and applies\n * `PATHEXT`, and Node reproduces neither for a direct spawn. Within each searched directory,\n * {@link buildExecutableCandidates} enumerates `PATHEXT` candidates for an extensionless name. For\n * an extension-bearing name, it enumerates the literal path before `PATHEXT` candidates, so\n * `report.txt` resolves to a `report.txt` file where one exists and to `report.txt.cmd` where none\n * does. The lookup reads the child's effective environment, so an overridden `PATH` selects the\n * executable the child would have found. A POSIX host resolves the file itself, so the candidate\n * list there is empty. A `PATHEXT` candidate keeps the extension spelling from `PATHEXT`, which the\n * case-insensitive host treats as the same file. A non-Windows platform returns an empty list\n * because `execvp` performs its own lookup.\n *\n * @param file - The command executable name or path\n * @param workspace - The directory searched first\n * @param environment - The child's effective environment\n * @param platform - The platform whose lookup rules apply\n * @returns The ordered absolute candidate paths\n *\n * @example\n * ```ts\n * buildExecutableCandidates('git', 'C:\\\\work', { PATH: 'C:\\\\bin' }, 'win32')\n * ```\n */\nexport function buildExecutableCandidates(\n\tfile: string,\n\tworkspace: string,\n\tenvironment: Readonly<Record<string, string | undefined>>,\n\tplatform: NodeJS.Platform,\n): readonly string[] {\n\tif (platform !== 'win32') return Object.freeze([])\n\tconst extensions = (readPlatformVariable(environment, 'PATHEXT', platform) ?? PROCESS_PATHEXT)\n\t\t.split(';')\n\t\t.filter((extension) => extension.length > 0)\n\tconst candidates =\n\t\twin32.extname(file).length === 0\n\t\t\t? extensions.map((extension) => `${file}${extension}`)\n\t\t\t: [file, ...extensions.map((extension) => `${file}${extension}`)]\n\tconst rooted = file.includes('/') || file.includes('\\\\')\n\tconst directories = rooted\n\t\t? [workspace]\n\t\t: [workspace, ...(readPlatformVariable(environment, 'PATH', platform) ?? '').split(';')]\n\tconst targets: string[] = []\n\tfor (const directory of directories) {\n\t\tif (directory.length === 0) continue\n\t\tfor (const candidate of candidates) {\n\t\t\ttargets.push(win32.resolve(directory, candidate))\n\t\t}\n\t}\n\treturn Object.freeze(targets)\n}\n\n/**\n * Resolves a command file to the executable path the host would launch, or to `undefined` on a POSIX\n * host, which performs its own lookup.\n *\n * @remarks\n * A Windows lookup miss also returns `undefined`. {@link buildSpawn} preserves the command file as\n * written for native spawning.\n *\n * @param file - The command executable name or path\n * @param options - The directory searched first and the child's effective environment\n * @returns The resolved absolute path, or `undefined` when no candidate is a regular file\n *\n * @example\n * ```ts\n * resolveExecutable('git', {}) ?? 'git' // an absolute path on Windows, 'git' elsewhere\n * ```\n */\nexport function resolveExecutable(file: string, options?: ExecutableOptions): string | undefined {\n\tconst environment = options?.environment ?? process.env\n\tconst workspace = options?.workspace ?? process.cwd()\n\tconst candidates = buildExecutableCandidates(file, workspace, environment, hostPlatform)\n\tfor (const target of candidates) {\n\t\tif (isFile(target)) return target\n\t}\n\treturn undefined\n}\n\n/**\n * Quotes one command-line token for a `cmd.exe` command line.\n *\n * @remarks\n * A token carrying whitespace or a shell metacharacter is wrapped in double quotes so `cmd.exe`\n * passes it as one literal argument; an embedded double quote is doubled, which is how `cmd.exe`\n * reads a literal quote inside a quoted token. The quoted set includes `%`, although quoting cannot\n * stop `cmd.exe` expansion; {@link buildSpawn} therefore refuses `%` in an argument to a Windows\n * batch target.\n *\n * @param value - The token to quote\n * @returns The token, quoted only when `cmd.exe` would otherwise split or interpret it\n *\n * @example\n * ```ts\n * quoteArgument('a&b') // '\"a&b\"'\n * ```\n */\nexport function quoteArgument(value: string): string {\n\tif (value.length > 0 && !/[\\s\"&|<>^()%!]/.test(value)) return value\n\treturn `\"${value.replaceAll('\"', '\"\"')}\"`\n}\n\n/**\n * Builds a spawn form from a resolved file and an explicit platform.\n *\n * @remarks\n * A resolved `.cmd` or `.bat` script cannot be spawned directly **on Windows**, so it runs there\n * through an explicitly quoted `cmd.exe /d /s /c` command line with the argument vector passed\n * verbatim. No path uses a shell, so a metacharacter in an argument is never interpreted. `cmd.exe`\n * expands `%NAME%` before it parses quotes, so no quoting can carry a percent sign through to a\n * Windows batch target: an argument carrying one is refused there rather than silently rewritten.\n * The whole batch path is Windows-only. A POSIX host has no `cmd.exe` and no restriction on spawning\n * a file directly, so a target named `worker.cmd` spawns directly there and receives a percent sign\n * as literal text.\n *\n * @param command - The executable and its argument vector\n * @param file - The resolved executable file\n * @param environment - The child's effective environment\n * @param platform - The platform whose batch rules apply\n * @returns The file, argument vector, and verbatim flag to spawn with\n * @throws A {@link ProcessError} coded `invalid` when `platform` is `win32`, the resolved target is a batch script, and an argument carries a percent sign\n *\n * @example\n * ```ts\n * buildPlatformSpawn({ file: 'node', arguments: ['--version'] }, 'node', {}, 'linux').verbatim // false\n * ```\n */\nexport function buildPlatformSpawn(\n\tcommand: ProcessCommand,\n\tfile: string,\n\tenvironment: Readonly<Record<string, string | undefined>>,\n\tplatform: NodeJS.Platform,\n): SpawnInput {\n\tconst extension = (platform === 'win32' ? win32.extname(file) : posix.extname(file)).toLowerCase()\n\t// Windows alone cannot spawn a batch script directly, and `cmd.exe` is what expands `%NAME%`.\n\t// A POSIX host has neither restriction, so a file whose name ends in `.cmd` is an ordinary\n\t// executable there and its extension changes nothing about how it spawns.\n\tconst batch = platform === 'win32' && (extension === '.cmd' || extension === '.bat')\n\tif (!batch) {\n\t\treturn Object.freeze({\n\t\t\tfile,\n\t\t\targuments: Object.freeze([...command.arguments]),\n\t\t\tverbatim: false,\n\t\t})\n\t}\n\tfor (const argument of command.arguments) {\n\t\tif (argument.includes('%')) throw createInvalidError('command argument', argument)\n\t}\n\tconst line = [`\"${file}\"`, ...command.arguments.map(quoteArgument)].join(' ')\n\treturn Object.freeze({\n\t\tfile: readPlatformVariable(environment, 'ComSpec', platform) ?? 'cmd.exe',\n\t\targuments: Object.freeze(['/d', '/s', '/c', `\"${line}\"`]),\n\t\tverbatim: true,\n\t})\n}\n\n/**\n * Builds the resolved spawn form of one command for the current host.\n *\n * @remarks\n * When executable lookup returns no regular-file candidate, {@link buildSpawn} preserves the\n * command file as written for native spawning.\n *\n * @param command - The executable and its argument vector\n * @param options - The directory searched first and the child's effective environment\n * @returns The file, argument vector, and verbatim flag to spawn with\n * @throws A {@link ProcessError} coded `invalid` when the host is Windows, the resolved target is a batch script, and an argument carries a percent sign\n *\n * @example\n * ```ts\n * buildSpawn({ file: 'node', arguments: ['--version'] }).verbatim // false\n * ```\n */\nexport function buildSpawn(command: ProcessCommand, options?: ExecutableOptions): SpawnInput {\n\tconst file = resolveExecutable(command.file, options) ?? command.file\n\tconst environment = options?.environment ?? process.env\n\treturn buildPlatformSpawn(command, file, environment, hostPlatform)\n}\n\n/**\n * Validates one spawn-bound string.\n *\n * @remarks\n * A NUL character terminates a string for the host, so it is refused everywhere rather than\n * reaching the spawn as a raw `ERR_INVALID_ARG_VALUE`.\n *\n * @param value - The value to inspect\n * @param subject - The rejected input named as the caller wrote it, such as `command file`\n * @param required - If `true`, an empty string is refused; if `false`, it is accepted\n * @returns Nothing; a successful return means the string is spawn-safe\n * @throws A {@link ProcessError} coded `invalid` when the value is not a string, carries a NUL, or is required and empty\n *\n * @example\n * ```ts\n * validateText('status', 'command argument', false) // returns\n * ```\n */\nexport function validateText(value: unknown, subject: string, required: boolean): void {\n\tif (!isString(value) || value.includes('\\0')) throw createInvalidError(subject, value)\n\tif (required && !isNonEmptyString(value)) throw createInvalidError(subject, value)\n}\n\n/**\n * Validates one timer-valued option in milliseconds.\n *\n * @remarks\n * The host truncates a fractional delay and converts anything above {@link PROCESS_TIMER} to one\n * millisecond, so a requested 25-day timeout would otherwise fire immediately.\n *\n * @param value - The value to inspect, or `undefined` when the option was omitted\n * @param subject - The rejected input named as the caller wrote it, such as `option 'grace'`\n * @returns Nothing; a successful return means the value schedules as written\n * @throws A {@link ProcessError} coded `invalid` when the value is not a non-negative integer at or below `PROCESS_TIMER`\n *\n * @example\n * ```ts\n * validateTimer(5_000, \"option 'grace'\") // returns\n * ```\n */\nexport function validateTimer(value: number | undefined, subject: string): void {\n\tif (value === undefined) return\n\tif (!isNonNegativeInteger(value) || !boundsOf(0, PROCESS_TIMER)(value)) {\n\t\tthrow createInvalidError(subject, value)\n\t}\n}\n\n/**\n * Validates one byte-valued option.\n *\n * @param value - The value to inspect, or `undefined` when the option was omitted\n * @param subject - The rejected input named as the caller wrote it, such as `option 'limit'`\n * @param minimum - The smallest accepted value\n * @returns Nothing; a successful return means the value bounds a real byte count\n * @throws A {@link ProcessError} coded `invalid` when the value is not a safe integer at or above `minimum`\n *\n * @example\n * ```ts\n * validateBytes(1_024, \"option 'limit'\", 0) // returns\n * ```\n */\nexport function validateBytes(value: number | undefined, subject: string, minimum: number): void {\n\tif (value === undefined) return\n\tif (!isNonNegativeInteger(value) || !boundsOf(minimum, Number.MAX_SAFE_INTEGER)(value)) {\n\t\tthrow createInvalidError(subject, value)\n\t}\n}\n\n/**\n * Validates every spawn-bound string of one environment override map.\n *\n * @remarks\n * The host refuses a NUL in a variable name or value with a raw `ERR_INVALID_ARG_VALUE`, so the same\n * refusal runs here for a command's own overrides and for a per-invocation override map alike.\n *\n * @param environment - The override map, or `undefined` when none was supplied\n * @returns Nothing; a successful return means every name and value reaches the host intact\n * @throws A {@link ProcessError} coded `invalid` when a name is empty or a name or value carries a NUL\n *\n * @example\n * ```ts\n * validateEnvironment({ TOKEN: 'a' }) // returns\n * ```\n */\nexport function validateEnvironment(\n\tenvironment: Readonly<Record<string, string | undefined>> | undefined,\n): void {\n\tif (environment === undefined) return\n\tfor (const [key, value] of Object.entries(environment)) {\n\t\tvalidateText(key, 'environment key', true)\n\t\tif (value !== undefined) validateText(value, 'environment value', false)\n\t}\n}\n\n/**\n * Validates every spawn-bound string of one command.\n *\n * @param command - The executable, arguments, and optional environment overrides\n * @returns Nothing; a successful return means the command reaches the host intact\n * @throws A {@link ProcessError} coded `invalid` when the file is empty or any string carries a NUL\n *\n * @example\n * ```ts\n * validateCommand({ file: 'git', arguments: ['status'] }) // returns\n * ```\n */\nexport function validateCommand(command: ProcessCommand): void {\n\tvalidateText(command.file, 'command file', true)\n\tfor (const argument of command.arguments) validateText(argument, 'command argument', false)\n\tvalidateEnvironment(command.environment)\n}\n\n/**\n * Validates the working directory one child starts in.\n *\n * @param workspace - The directory, or `undefined` when the option was omitted\n * @returns Nothing; a successful return means the directory reaches the host intact\n * @throws A {@link ProcessError} coded `invalid` when the directory is empty or carries a NUL\n *\n * @example\n * ```ts\n * validateWorkspace(process.cwd()) // returns\n * ```\n */\nexport function validateWorkspace(workspace: string | undefined): void {\n\tif (workspace === undefined) return\n\tvalidateText(workspace, 'workspace', true)\n}\n\n/**\n * Checks whether a child process has reached its native exit.\n *\n * @remarks\n * The host sets exactly one of these fields when the process ends, so together they are the\n * authoritative liveness answer. Reading them before each signal is what keeps a signal from being\n * initiated against a pid the host may have reused.\n *\n * @param child - The child boundary\n * @returns True if the process has exited; false otherwise\n *\n * @example\n * ```ts\n * isExited({ exitCode: 0, signalCode: null }) // true\n * ```\n */\nexport function isExited(child: Pick<ProcessChildInterface, 'exitCode' | 'signalCode'>): boolean {\n\treturn child.exitCode !== null || child.signalCode !== null\n}\n\n/**\n * Reports whether a process or POSIX process group still exists.\n *\n * @param pid - A positive process id, or a negative POSIX process-group id\n * @returns True when the host confirms existence or refuses permission; false for ESRCH; undefined for another host failure\n * @throws A {@link ProcessError} coded `invalid` for an unsafe integer, zero, minus one, or a negative id on Windows\n * @remarks Negative ids probe POSIX process groups. The `process.platform` branch refuses negative ids on Windows, where the host supports positive process ids only.\n * @example\n * ```ts\n * inspectProcess(process.pid) // true\n * ```\n */\nexport function inspectProcess(pid: number): boolean | undefined {\n\tif (\n\t\t!Number.isSafeInteger(pid) ||\n\t\tpid === 0 ||\n\t\tpid === -1 ||\n\t\t(process.platform === 'win32' && pid < 0)\n\t) {\n\t\tthrow createInvalidError('process id', pid)\n\t}\n\ttry {\n\t\treturn process.kill(pid, 0)\n\t} catch (error) {\n\t\tconst code = isError(error) && 'code' in error ? error.code : undefined\n\t\treturn code === 'ESRCH' ? false : code === 'EPERM' ? true : undefined\n\t}\n}\n\n/**\n * Signals one owned child process, or its detached process group on a POSIX host.\n *\n * @remarks\n * On a POSIX host a child spawned `detached` leads its own process group, so signalling the\n * negated pid reaches the whole tree. When no group owns the pid and the host reports `ESRCH`, the\n * signal falls back to the child directly. On Windows, or when no pid is available, the signal also\n * goes to the child directly. Every other throw during signalling is swallowed: the process can\n * exit between the caller's liveness check and this call, and the child's native exit remains the\n * authoritative terminal state.\n *\n * @param child - The child boundary\n * @param signal - The signal to deliver\n * @returns Nothing\n *\n * @example\n * ```ts\n * killProcess(child, 'SIGTERM')\n * ```\n */\nexport function killProcess(\n\tchild: Pick<ProcessChildInterface, 'pid' | 'kill'>,\n\tsignal: NodeJS.Signals,\n): void {\n\ttry {\n\t\tif (process.platform === 'win32' || child.pid === undefined) {\n\t\t\tchild.kill(signal)\n\t\t\treturn\n\t\t}\n\t\tprocess.kill(-child.pid, signal)\n\t} catch (error) {\n\t\tif (isError(error) && 'code' in error && error.code === 'ESRCH') {\n\t\t\tholds(() => child.kill(signal))\n\t\t\treturn\n\t\t}\n\t\t// Exit can win the signal race; the native exit remains authoritative.\n\t}\n}\n\n/**\n * Kills one Windows process tree through `taskkill`.\n *\n * @remarks\n * Windows has no process group a signal can reach, so the whole tree is ended by the host utility,\n * addressed by its absolute `System32` path so a `PATH` override cannot substitute another program.\n * The call is bounded: it is killed itself when `timeout` elapses, which is what keeps a termination\n * from waiting on the host indefinitely. A tree is discoverable only while its root lives, so a\n * descendant that outlives the root is beyond this mechanism.\n *\n * @param pid - The root process id of the tree to end\n * @param timeout - The milliseconds the utility is given before it is killed\n * @returns True if the utility reported success; false otherwise (it failed, was unavailable, or was cut off)\n *\n * @example\n * ```ts\n * await killTree(child.pid ?? 0, 5_000)\n * ```\n */\nexport function killTree(pid: number, timeout: number): Promise<boolean> {\n\tconst settled = Promise.withResolvers<boolean>()\n\tconst executable = join(process.env.SystemRoot ?? 'C:\\\\Windows', 'System32', 'taskkill.exe')\n\tconst killer = spawn(executable, ['/F', '/T', '/PID', String(pid)], {\n\t\tstdio: 'ignore',\n\t\twindowsHide: true,\n\t\ttimeout,\n\t})\n\tkiller.once('error', () => settled.resolve(false))\n\tkiller.once('close', (code: number | null) => settled.resolve(code === 0))\n\treturn settled.promise\n}\n\n/**\n * Waits for one child process's native exit, bounded by a deadline.\n *\n * @param child - The child boundary\n * @param timeout - The milliseconds to wait before giving up\n * @returns A promise that resolves on the native exit or when the deadline elapses, whichever comes first\n *\n * @example\n * ```ts\n * await waitForExit(child, 5_000)\n * ```\n */\nexport function waitForExit(\n\tchild: Pick<ProcessChildInterface, 'exitCode' | 'signalCode' | 'once' | 'off'>,\n\ttimeout: number,\n): Promise<void> {\n\tif (isExited(child)) return Promise.resolve()\n\tconst settled = Promise.withResolvers<void>()\n\tconst timer = setTimeout(() => {\n\t\tchild.off('exit', settled.resolve)\n\t\tsettled.resolve()\n\t}, timeout)\n\tchild.once('exit', settled.resolve)\n\treturn settled.promise.finally(() => clearTimeout(timer))\n}\n\n/**\n * Waits for one child process's streams to close, bounded by a deadline.\n *\n * @param child - The child boundary\n * @param timeout - The milliseconds to wait before giving up\n * @returns True if the host close arrived inside the deadline; false otherwise\n *\n * @example\n * ```ts\n * const closed = await waitForClose(child, 5_000)\n * ```\n */\nexport function waitForClose(\n\tchild: Pick<ProcessChildInterface, 'once' | 'off'>,\n\ttimeout: number,\n): Promise<boolean> {\n\tconst closed = Promise.withResolvers<void>()\n\tconst expired = Promise.withResolvers<boolean>()\n\tconst timer = setTimeout(() => expired.resolve(false), timeout)\n\tchild.once('close', closed.resolve)\n\treturn Promise.race([closed.promise.then(() => true), expired.promise]).finally(() => {\n\t\tclearTimeout(timer)\n\t\tchild.off('close', closed.resolve)\n\t})\n}\n\n/**\n * Terminates one child process tree and reports whether its native exit was observed.\n *\n * @remarks\n * An already-exited child is returned on before any route to its pid runs, because the host has\n * reaped that number and may have handed it to another process. Windows ends the whole tree at once\n * through {@link killTree}, falling back to a direct kill after the utility fails, because the host\n * has no cooperative termination to offer. A POSIX host signals the process group `SIGTERM`, falls\n * back to the direct child when no group owns its pid, waits `grace`, then sends `SIGKILL` through\n * the same route. No signal is initiated after the native exit is observed; the window between\n * initiating a signal and the host delivering it belongs to the operating system. `confirm` bounds\n * each awaited step rather than the call as a whole: on Windows it bounds the `taskkill` call and\n * then the final wait, and on a POSIX host `grace` bounds the cooperative wait and `confirm` the\n * final one. Never rejects.\n *\n * @param child - The child boundary\n * @param grace - The cooperative POSIX window in milliseconds between `SIGTERM` and `SIGKILL`\n * @param confirm - The milliseconds the native exit is awaited after the final kill\n * @returns True if the native exit was observed; false otherwise (`confirm` elapsed without it)\n *\n * @example\n * ```ts\n * const confirmed = await stopChild(child, 5_000, 5_000)\n * ```\n */\nexport async function stopChild(\n\tchild: ProcessChildInterface,\n\tgrace: number,\n\tconfirm: number,\n): Promise<boolean> {\n\tif (isExited(child)) return true\n\tif (process.platform === 'win32') {\n\t\tconst killed = child.pid === undefined ? false : await killTree(child.pid, confirm)\n\t\tif (!killed && !isExited(child)) killProcess(child, 'SIGKILL')\n\t} else {\n\t\tkillProcess(child, 'SIGTERM')\n\t\tawait waitForExit(child, grace)\n\t\tif (!isExited(child)) killProcess(child, 'SIGKILL')\n\t}\n\tif (isExited(child)) return true\n\tawait waitForExit(child, confirm)\n\treturn isExited(child)\n}\n\n/**\n * Builds one settled {@link ExecuteResult} from a completed run's captured bytes and terminal facts.\n *\n * @remarks\n * `failed` is derived: a run failed when it timed out, was aborted, ended on a host fault, was ended\n * by a signal, or exited with a code other than `0` — a `null` code from a spawn fault is therefore\n * a failure. Each byte field is bounded by `limit` on a code-point boundary here, which is the one\n * place the captured bytes are decoded.\n *\n * @param input - The captured bytes, terminal state, and capture limit\n * @returns The frozen run outcome\n *\n * @example\n * ```ts\n * buildExecuteResult({\n * \tcommand: 'git status',\n * \tstdout: Buffer.from('ok'),\n * \tstderr: Buffer.alloc(0),\n * \tcode: 0,\n * \tsignal: null,\n * \texpired: false,\n * \taborted: false,\n * \ttruncated: false,\n * \tlimit: 1_024,\n * }).failed // false\n * ```\n */\nexport function buildExecuteResult(input: ExecuteInput): ExecuteResult {\n\treturn Object.freeze({\n\t\tcommand: input.command,\n\t\tstdout: trimHead(input.stdout, input.limit).toString('utf8'),\n\t\tstderr: trimHead(input.stderr, input.limit).toString('utf8'),\n\t\tcode: input.code,\n\t\tsignal: input.signal,\n\t\tfailed:\n\t\t\tinput.expired ||\n\t\t\tinput.aborted ||\n\t\t\tinput.cause !== undefined ||\n\t\t\tinput.signal !== null ||\n\t\t\tinput.code !== 0,\n\t\texpired: input.expired,\n\t\taborted: input.aborted,\n\t\ttruncated: input.truncated,\n\t})\n}\n\n/**\n * Spawns one command as a detached process and returns without waiting for it.\n *\n * @remarks\n * The child owns no stdio and is unreferenced, so it outlives this process and nothing here observes\n * its outcome. The error listener is attached before the child is unreferenced, so a post-spawn host\n * fault is swallowed rather than crashing the caller; an invalid command is refused before anything\n * is spawned.\n *\n * @param command - The executable, arguments, and optional environment\n * @param options - The working directory the detached child starts in\n * @returns Nothing\n * @throws A {@link ProcessError} coded `invalid` when the working directory or a command string is malformed\n *\n * @example\n * ```ts\n * detach({ file: 'node', arguments: ['daemon.js'] }, { workspace: process.cwd() })\n * ```\n */\nexport function detach(command: ProcessCommand, options?: DetachOptions): void {\n\tconst snapshot = snapshotCommand(command)\n\tconst optionWorkspace = options?.workspace\n\tvalidateCommand(snapshot)\n\tvalidateWorkspace(optionWorkspace)\n\tconst workspace = optionWorkspace ?? process.cwd()\n\tconst environment = mergeEnvironment(snapshot.isolated === true, snapshot.environment)\n\tconst plan = buildSpawn(snapshot, { workspace, environment })\n\tconst child = spawn(plan.file, [...plan.arguments], {\n\t\tcwd: workspace,\n\t\tdetached: true,\n\t\tenv: environment,\n\t\tstdio: 'ignore',\n\t\twindowsHide: true,\n\t\twindowsVerbatimArguments: plan.verbatim,\n\t})\n\tchild.once('error', () => undefined)\n\tchild.unref()\n}\n","import type { ChildProcessWithoutNullStreams } from 'node:child_process'\nimport type { Readable } from 'node:stream'\nimport type { ProcessExit, ProcessOptions } from '@src/core'\nimport type { SupervisorFace } from '../types.js'\nimport { Buffer } from 'node:buffer'\nimport { spawn } from 'node:child_process'\nimport { StringDecoder } from 'node:string_decoder'\nimport {\n\tProcessError,\n\tPROCESS_CONFIRMATION,\n\tPROCESS_DRAIN,\n\tPROCESS_EVIDENCE,\n\tPROCESS_GRACE,\n} from '@src/core'\nimport { snapshotCommand } from '../cloners.js'\nimport {\n\tbuildSpawn,\n\tmergeEnvironment,\n\tstopChild,\n\ttrimTail,\n\tvalidateBytes,\n\tvalidateCommand,\n\tvalidateTimer,\n\tvalidateWorkspace,\n\twaitForClose,\n} from '../helpers.js'\n\n/**\n * Supervises one child process and reports each lifecycle moment to the face composing it.\n *\n * @remarks\n * This is the engine every supervised-child face shares. It owns the eager spawn, the byte-bounded\n * stderr tail and its decoded chunks, the standard-input channel and its bounded confirmation, the\n * termination sequence, and the progression from the child's native exit through the bounded `drain`\n * window to one terminal moment. It owns no output framing and no observation surface: a face\n * attaches its own consumer to `stdout`, frames bytes however its contract promises, and owns the\n * emitter and event map its consumers subscribe to.\n *\n * The child's ending and the supervision's ending are distinct. `pid`, `code`, and `signal` read the\n * host child directly, so they expose native exit as soon as the host records it, and `ended`\n * settles at that same moment. `settled`, `exit`, and `evidence` reach one terminal moment after the\n * read channels close or the bounded `drain` window cuts them off. That window is armed by the\n * child's native exit and by a termination this package initiated, so every way a child can end\n * reaches the moment. The terminal routine hands the face its `close` and `terminal` moments before\n * it destroys stdout and stderr, so a face's own pull surfaces are final while its read ends still\n * exist.\n *\n * The face is a set of callbacks rather than an emitter, because each face publishes a different\n * event map over the same moments. `chunk` and `fault` carry the live stderr text and the child or\n * channel faults, `relieve` reports that a termination began so the face can release whatever\n * backpressure it holds, `close` ends the face's read pipeline at the terminal moment, `terminal`\n * carries the frozen {@link ProcessExit}, and `teardown` releases the face's own surface after the\n * termination completes. `relieve` is optional because a face that never pauses the child's output\n * holds no backpressure to release, and a face with nothing to do there would otherwise declare an\n * empty method to say so.\n *\n * @example\n * ```ts\n * import { Supervisor } from '@orkestrel/process/server'\n *\n * const engine = new Supervisor(\n * \t{ command: { file: 'node', arguments: ['--version'] }, workspace: process.cwd() },\n * \t{\n * \t\tchunk: () => undefined,\n * \t\tfault: () => undefined,\n * \t\tclose: () => undefined,\n * \t\tterminal: () => undefined,\n * \t\tteardown: () => undefined,\n * \t},\n * )\n * const exit = await engine.exit\n * exit.code // 0\n * await engine.destroy()\n * ```\n */\nexport class Supervisor {\n\treadonly #chunk: (text: string) => void\n\treadonly #fault: (cause: unknown) => void\n\treadonly #relieve: (() => void) | undefined\n\treadonly #close: () => void\n\treadonly #terminal: (exit: ProcessExit) => void\n\treadonly #teardown: () => void\n\treadonly #child: ChildProcessWithoutNullStreams\n\treadonly #grace: number\n\treadonly #drain: number\n\treadonly #evidence: number\n\treadonly #delivery: number\n\treadonly #decoder = new StringDecoder('utf8')\n\treadonly #exit = Promise.withResolvers<ProcessExit>()\n\treadonly #ended = Promise.withResolvers<void>()\n\treadonly #signal: AbortSignal | undefined\n\treadonly #abort: (() => void) | undefined\n\treadonly #writes = new Map<\n\t\tPromiseWithResolvers<boolean>,\n\t\tReturnType<typeof setTimeout> | undefined\n\t>()\n\t#tail: Buffer = Buffer.alloc(0)\n\t// A guard reads `#terminated`, never `#termination !== undefined`. `#kill` assigns the boolean in\n\t// its synchronous prefix, which runs while `stop` is still evaluating\n\t// `this.#termination = this.#kill()`, so the boolean also covers the retention and backpressure\n\t// decisions a face takes while `#termination` is still `undefined`.\n\t#terminated = false\n\t#settled = false\n\t#input = 0\n\t#failure: Error | undefined\n\t#waiting: Promise<void> | undefined\n\t#closure: Promise<void> | undefined\n\t#termination: Promise<boolean> | undefined\n\t#destruction: Promise<void> | undefined\n\n\t/**\n\t * Spawns one child process and begins standard-error capture.\n\t *\n\t * @remarks\n\t * The face's callbacks are captured before anything is read or spawned, so the first moment the\n\t * child can produce already has somewhere to go. `options` supplies the command, workspace,\n\t * termination, capture, and standard-input settings; a face's own settings, such as an output\n\t * retention bound, are read and validated by that face before it constructs this engine, so an\n\t * invalid one refuses construction while nothing has been spawned.\n\t *\n\t * @param options - Command, workspace, termination, capture, and stdin settings\n\t * @param face - The composing face's callbacks for each lifecycle moment\n\t * @throws A {@link ProcessError} coded `invalid` when an option or command string is malformed\n\t */\n\tconstructor(options: ProcessOptions, face: SupervisorFace) {\n\t\tthis.#chunk = face.chunk\n\t\tthis.#fault = face.fault\n\t\tthis.#relieve = face.relieve\n\t\tthis.#close = face.close\n\t\tthis.#terminal = face.terminal\n\t\tthis.#teardown = face.teardown\n\t\t// Every option and command property is read once, here, before anything is spawned. Reading a\n\t\t// property runs the caller's own getter, so a read after the spawn would let that getter throw\n\t\t// while a live child exists and no one holds a reference to it. Hoisting the reads is what\n\t\t// makes a construction failure unable to strand a process.\n\t\tconst source = options.command\n\t\tconst workspace = options.workspace\n\t\tconst grace = options.grace\n\t\tconst drain = options.drain\n\t\tconst evidence = options.evidence\n\t\tconst delivery = options.delivery\n\t\tconst writable = options.writable\n\t\tconst signal = options.signal\n\t\tconst command = snapshotCommand(source)\n\t\tconst input = command.input\n\t\tvalidateCommand(command)\n\t\tvalidateWorkspace(workspace)\n\t\tvalidateTimer(grace, \"option 'grace'\")\n\t\tvalidateTimer(drain, \"option 'drain'\")\n\t\tvalidateTimer(delivery, \"option 'delivery'\")\n\t\tvalidateBytes(evidence, \"option 'evidence'\", 0)\n\t\tthis.#grace = grace ?? PROCESS_GRACE\n\t\tthis.#drain = drain ?? PROCESS_DRAIN\n\t\tthis.#evidence = evidence ?? PROCESS_EVIDENCE\n\t\tthis.#delivery = delivery ?? 0\n\t\tthis.#signal = signal\n\t\tconst childEnvironment = mergeEnvironment(command.isolated === true, command.environment)\n\t\tconst plan = buildSpawn(command, { workspace, environment: childEnvironment })\n\t\tthis.#child = spawn(plan.file, [...plan.arguments], {\n\t\t\tcwd: workspace,\n\t\t\tdetached: process.platform !== 'win32',\n\t\t\tenv: childEnvironment,\n\t\t\tstdio: ['pipe', 'pipe', 'pipe'],\n\t\t\twindowsHide: true,\n\t\t\twindowsVerbatimArguments: plan.verbatim,\n\t\t})\n\t\tthis.#child.once('error', this.#fault)\n\t\tthis.#child.once('exit', this.#expire.bind(this))\n\t\tthis.#child.once('close', this.#complete.bind(this))\n\t\tthis.#child.stdin.on('error', this.#failInputStream.bind(this))\n\t\tthis.#child.stderr.on('data', this.#retain.bind(this))\n\t\tif (input !== undefined) {\n\t\t\tthis.#input += 1\n\t\t\tthis.#child.stdin.write(input, this.#completeInput.bind(this))\n\t\t}\n\t\tif (writable !== true) {\n\t\t\tthis.#input += 1\n\t\t\tthis.#child.stdin.end(this.#completeInput.bind(this))\n\t\t}\n\t\tif (signal !== undefined) {\n\t\t\tthis.#abort = this.#terminate.bind(this)\n\t\t\tsignal.addEventListener('abort', this.#abort, { once: true })\n\t\t\tif (signal.aborted) void this.stop()\n\t\t}\n\t}\n\n\t/** Holds the child's standard-output stream, for the composing face to attach its own consumer to. */\n\tget stdout(): Readable {\n\t\treturn this.#child.stdout\n\t}\n\n\t/** Holds the host process id, fixed when construction returns, or `undefined` when the spawn produced none. */\n\tget pid(): number | undefined {\n\t\treturn this.#child.pid\n\t}\n\n\t/** Holds the exit code the host recorded, or `null` while the child has not exited and when a signal ended it. */\n\tget code(): number | null {\n\t\treturn this.#child.exitCode\n\t}\n\n\t/** Holds the terminating signal name the host recorded, or `null` while the child has not exited and when it exited on its own. */\n\tget signal(): string | null {\n\t\treturn this.#child.signalCode\n\t}\n\n\t/** Holds the decoded byte-bounded stderr tail, frozen at the terminal moment. */\n\tget evidence(): string {\n\t\treturn this.#tail.toString('utf8')\n\t}\n\n\t/** Reports whether the terminal moment arrived and `exit` settled. */\n\tget settled(): boolean {\n\t\treturn this.#settled\n\t}\n\n\t/** Reports whether termination began, including after the terminal moment. */\n\tget terminated(): boolean {\n\t\treturn this.#terminated\n\t}\n\n\t/**\n\t * Settles at the child's own ending, awaited without the terminal moment's drain window.\n\t *\n\t * @remarks\n\t * Never rejects, and resolves no value: `code` and `signal` carry the terminal facts as soon as\n\t * the host records them. It settles at the native exit, and at the terminal moment for a child\n\t * whose spawn produced no native exit at all, so it can never outlive the supervision.\n\t */\n\tget ended(): Promise<void> {\n\t\treturn this.#ended.promise\n\t}\n\n\t/** Settles with the terminal child state, observed once after stream close or the drain cutoff. */\n\tget exit(): Promise<ProcessExit> {\n\t\treturn this.#exit.promise\n\t}\n\n\t/**\n\t * Writes raw bytes to the open standard-input channel.\n\t *\n\t * @remarks\n\t * Never rejects, and adds no framing: a face composes whatever terminator its contract promises\n\t * before it calls this. `true` means the host accepted the bytes without reporting a fault; it\n\t * does not prove that the child read them. An ordinary write settles when the kernel accepts it.\n\t * Only a full pipe can hold the write unconfirmed. The `delivery` option can bound that wait, and\n\t * every terminal teardown path settles pending writes. After `stop` or `destroy` begins, a later\n\t * call settles `false`, because teardown cannot confirm delivery for bytes it is about to\n\t * discard.\n\t *\n\t * @param bytes - The payload to write, already framed by the caller\n\t * @returns True if the host accepted the bytes without reporting a fault; false otherwise (the channel was closed, destroyed, ended, failed, or the write remained unconfirmed through `delivery`)\n\t *\n\t * @example\n\t * ```ts\n\t * import { Supervisor } from '@orkestrel/process/server'\n\t *\n\t * const engine = new Supervisor(\n\t * \t{\n\t * \t\tcommand: { file: 'node', arguments: ['-e', 'process.stdin.pipe(process.stdout)'] },\n\t * \t\tworkspace: process.cwd(),\n\t * \t\twritable: true,\n\t * \t},\n\t * \t{\n\t * \t\tchunk: () => undefined,\n\t * \t\tfault: () => undefined,\n\t * \t\tclose: () => undefined,\n\t * \t\tterminal: () => undefined,\n\t * \t\tteardown: () => undefined,\n\t * \t},\n\t * )\n\t * const accepted = await engine.deliver(new TextEncoder().encode('ping\\n'))\n\t * accepted // true\n\t * await engine.destroy()\n\t * ```\n\t */\n\tdeliver(bytes: Uint8Array): Promise<boolean> {\n\t\tconst stdin = this.#child.stdin\n\t\tif (this.#settled || this.#terminated || this.#failure !== undefined || !stdin.writable) {\n\t\t\treturn Promise.resolve(false)\n\t\t}\n\t\tconst settled = Promise.withResolvers<boolean>()\n\t\tthis.#writes.set(settled, undefined)\n\t\ttry {\n\t\t\tstdin.write(bytes, this.#confirmWrite.bind(this, settled))\n\t\t} catch {\n\t\t\tthis.#settleWrite(settled, false)\n\t\t\treturn settled.promise\n\t\t}\n\t\tif (this.#delivery > 0 && this.#writes.has(settled)) {\n\t\t\tconst timer = setTimeout(() => this.#settleWrite(settled, false), this.#delivery)\n\t\t\ttimer.unref()\n\t\t\tthis.#writes.set(settled, timer)\n\t\t}\n\t\treturn settled.promise\n\t}\n\n\t/**\n\t * Closes the standard-input channel while leaving the child running.\n\t *\n\t * @remarks\n\t * Never rejects, and terminates nothing: no signal is sent, `terminated` stays false, no drain\n\t * window is armed, and the terminal moment does not arrive. The child observes end of input and\n\t * decides for itself what to do about it, which is what separates this from `stop`.\n\t *\n\t * Every call shares one barrier, and it resolves after the host flushes the writes it had already\n\t * accepted, or reports that it cannot. A `deliver` after this call resolves `false`, because the\n\t * host stops reporting the channel writable the moment it is ended. That same flag keeps the\n\t * ended channel quiet for its remaining life, so a later host fault on it settles pending writes\n\t * and reaches no face. After `stop` or `destroy` has begun, or after the terminal moment, the\n\t * call resolves and changes nothing, because the channel is already being discarded.\n\t *\n\t * @returns The stable barrier shared by every call\n\t */\n\tend(): Promise<void> {\n\t\tif (this.#closure !== undefined) return this.#closure\n\t\tthis.#closure = this.#endInput()\n\t\treturn this.#closure\n\t}\n\n\t/**\n\t * Terminates the child process tree and reaches the terminal observation moment.\n\t *\n\t * @remarks\n\t * Never rejects, and every call shares one termination. After the termination sequence returns,\n\t * confirmed or not, it waits at most `drain` for the read channels to close, then cuts them off\n\t * and settles `exit` when they remain open. A cutoff reached before the native exit reports the\n\t * `code` and `signal` the host had recorded by then, which is `null` for a child still running.\n\t *\n\t * @returns True if the child's native exit was observed; false otherwise (the confirmation deadline elapsed without it)\n\t */\n\tstop(): Promise<boolean> {\n\t\tif (this.#termination !== undefined) return this.#termination\n\t\tthis.#termination = this.#kill()\n\t\treturn this.#termination\n\t}\n\n\t/**\n\t * Stops the child and releases the composing face after the terminal state freezes.\n\t *\n\t * @remarks\n\t * Always resolves, including when termination was never confirmed. Every call shares one barrier.\n\t *\n\t * @returns The stable barrier shared by every call\n\t */\n\tdestroy(): Promise<void> {\n\t\tif (this.#destruction !== undefined) return this.#destruction\n\t\tthis.#destruction = this.#conclude()\n\t\treturn this.#destruction\n\t}\n\n\t#retain(chunk: unknown): void {\n\t\tif (!Buffer.isBuffer(chunk) || this.#settled) return\n\t\tthis.#tail = trimTail(Buffer.concat([this.#tail, chunk]), this.#evidence)\n\t\tconst text = this.#decoder.write(chunk)\n\t\tif (text.length > 0) this.#chunk(text)\n\t}\n\n\t#complete(): void {\n\t\tif (this.#settled) return\n\t\tthis.#settle(true)\n\t}\n\n\t// A native exit does not close the read ends: a descendant that inherited them holds them open\n\t// for its own remaining life, and one that never ends never closes them at all. Arming the same\n\t// bounded wait a requested termination awaits is what makes every ending reach the terminal\n\t// moment. `ended` settles here rather than at that moment, because it reports the child's own\n\t// exit and not the release of the channels a descendant may still hold.\n\t#expire(): void {\n\t\tthis.#ended.resolve()\n\t\tif (this.#settled) return\n\t\tvoid this.#wait()\n\t}\n\n\t// One bounded wait per close, created once and shared: the native exit arms it and a termination\n\t// awaits the same one, so a close never carries two overlapping bounds. `waitForClose` clears its\n\t// own timer on either outcome. The constructor registers `#complete` before this listener exists,\n\t// so a natural close settles drained and the following continuation finds the latch already set.\n\t#wait(): Promise<void> {\n\t\tthis.#waiting ??= waitForClose(this.#child, this.#drain).then(() => {\n\t\t\tif (!this.#settled) this.#settle(false)\n\t\t})\n\t\treturn this.#waiting\n\t}\n\n\t#settle(drained: boolean): void {\n\t\t// Flush the decoder while the face's stderr channel is still live.\n\t\tconst suffix = this.#decoder.end()\n\t\tif (suffix.length > 0) this.#chunk(suffix)\n\t\t// Latch before the following lines resolve and deliver the terminal value, so a consumer\n\t\t// handed that value never reads a child still reporting itself unfinished.\n\t\tthis.#settled = true\n\t\tthis.#removeAbortListener()\n\t\t// Ending the face's read pipeline here preserves whatever it has already framed and queued.\n\t\tthis.#close()\n\t\tconst exit = Object.freeze({ code: this.code, signal: this.signal, drained })\n\t\tthis.#exit.resolve(exit)\n\t\t// A spawn that produced no child reports no native exit, so the terminal moment is the last\n\t\t// place `ended` can settle rather than wait forever.\n\t\tthis.#ended.resolve()\n\t\tthis.#terminal(exit)\n\t\t// Release read handles only after every pull surface is final.\n\t\tthis.#child.stdout.destroy()\n\t\tthis.#child.stderr.destroy()\n\t}\n\n\t#terminate(): void {\n\t\tvoid this.stop()\n\t}\n\n\t#removeAbortListener(): void {\n\t\tif (this.#signal === undefined || this.#abort === undefined) return\n\t\tthis.#signal.removeEventListener('abort', this.#abort)\n\t}\n\n\t#confirmWrite(settled: PromiseWithResolvers<boolean>, error?: Error | null): void {\n\t\tif (error === undefined || error === null) {\n\t\t\tthis.#settleWrite(settled, true)\n\t\t\treturn\n\t\t}\n\t\tthis.#failInputCallback(error)\n\t}\n\n\t#completeInput(): void {\n\t\tthis.#input -= 1\n\t}\n\n\t// A channel already ended, destroyed, or being discarded has nothing left to close, so the\n\t// barrier resolves without touching the stream: calling `end` on a destroyed stream raises a\n\t// host error that no consumer asked for. Otherwise Node's own `end` flushes whatever it already\n\t// accepted and reports through the callback either way, which is why this never rejects.\n\t#endInput(): Promise<void> {\n\t\tconst stdin = this.#child.stdin\n\t\tif (this.#terminated || this.#settled || stdin.writableEnded || stdin.destroyed) {\n\t\t\treturn Promise.resolve()\n\t\t}\n\t\tconst ended = Promise.withResolvers<void>()\n\t\tstdin.end(() => ended.resolve())\n\t\treturn ended.promise\n\t}\n\n\t#settleWrite(settled: PromiseWithResolvers<boolean>, accepted: boolean): void {\n\t\tif (!this.#writes.has(settled)) return\n\t\tconst timer = this.#writes.get(settled)\n\t\tthis.#writes.delete(settled)\n\t\tclearTimeout(timer)\n\t\tsettled.resolve(accepted)\n\t}\n\n\t#settleWrites(): void {\n\t\tfor (const settled of this.#writes.keys()) this.#settleWrite(settled, false)\n\t}\n\n\t#failInputStream(cause: Error): void {\n\t\t// The constructor's own input phase is quiet while it runs, because the package initiated that\n\t\t// write and its closing `end`. Every other quieting rule lives in the following classifier,\n\t\t// which both the stream's error event and a write callback reach.\n\t\tif (this.#input > 0) {\n\t\t\tthis.#settleWrites()\n\t\t\treturn\n\t\t}\n\t\tthis.#failInputCallback(cause)\n\t}\n\n\t#failInputCallback(cause: Error): void {\n\t\t// An ended channel stays quiet for its remaining life, whether the package ended it at\n\t\t// construction or a consumer ended it through `end`: the closure was asked for, so the fault it\n\t\t// produces is not news to report. Pending writes still settle, because nothing left is going to\n\t\t// confirm them. A `writable: true` channel never sets `writableEnded` until ended, so a later\n\t\t// host fault on an open channel stays classifiable.\n\t\tif (this.#child.stdin.writableEnded) {\n\t\t\tthis.#settleWrites()\n\t\t\treturn\n\t\t}\n\t\tif (this.#failure !== undefined || this.#terminated) return\n\t\tthis.#failure = cause\n\t\tthis.#settleWrites()\n\t\tthis.#fault(new ProcessError('The standard-input channel failed', { code: 'protocol', cause }))\n\t}\n\n\tasync #kill(): Promise<boolean> {\n\t\t// A paused stdout holds the child's own write, and therefore its exit. The face releases its\n\t\t// backpressure before anything is signalled; later output drops at the face's teardown bound\n\t\t// instead of pausing the stream again.\n\t\tthis.#terminated = true\n\t\tthis.#relieve?.()\n\t\tconst confirmed = await stopChild(this.#child, this.#grace, PROCESS_CONFIRMATION)\n\t\tthis.#settleWrites()\n\t\tthis.#child.stdin.destroy()\n\t\tif (!this.#settled) await this.#wait()\n\t\tif (!this.#settled) this.#settle(false)\n\t\treturn confirmed\n\t}\n\n\t// The composite `destroy` performs, named apart from the public `end` that closes standard input.\n\tasync #conclude(): Promise<void> {\n\t\tawait this.stop()\n\t\tthis.#teardown()\n\t}\n}\n","import type { Interface as ReadLineInterface } from 'node:readline'\nimport type { EmitterInterface } from '@orkestrel/emitter'\nimport type { ProcessEventMap, ProcessExit, ProcessInterface, ProcessOptions } from '@src/core'\nimport { Buffer } from 'node:buffer'\nimport { createInterface } from 'node:readline'\nimport { Emitter } from '@orkestrel/emitter'\nimport { PROCESS_BACKLOG } from '@src/core'\nimport { snapshotCommand } from '../cloners.js'\nimport { validateBytes, validateCommand, validateTimer, validateWorkspace } from '../helpers.js'\nimport { Supervisor } from './Supervisor.js'\n\n/**\n * Supervises one child, frames its standard output into lines under a bounded backlog, and keeps\n * every observation channel aligned at termination.\n *\n * @remarks\n * The child's ending and the supervision's ending are distinct. `pid`, `code`, and `signal` read\n * the host child directly, so they expose native exit as soon as the host records it. `settled`,\n * `exit`, `evidence`, and `lines` reach one terminal moment after the read channels close or the\n * bounded `drain` window cuts them off. That window is armed by the child's native exit and by a\n * termination this package initiated, so every way a child can end reaches the moment. The terminal\n * routine freezes `evidence` and ends `lines` before it destroys stdout, stderr, or the emitter, so\n * the push channel never disappears while a pull channel can still change or wait indefinitely.\n *\n * Standard output is framed through `readline` into a single-consumer stream. Lines already framed\n * and queued remain available through the terminal moment, while bytes arriving after a requested\n * termination may be cut off. Standard error is forwarded through the live `stderr` event and\n * retained as a byte-bounded raw tail until that same moment. `stop` ends the child tree and the\n * observation surfaces. `destroy` performs that stop and then destroys the emitter after the\n * frozen terminal state exists.\n *\n * @example\n * ```ts\n * import { Process } from '@orkestrel/process/server'\n *\n * const child = new Process({\n * \tcommand: { file: 'node', arguments: ['--version'] },\n * \tworkspace: process.cwd(),\n * })\n * const exit = await child.exit\n * await child.destroy()\n * ```\n */\nexport class Process implements ProcessInterface {\n\treadonly #emitter: Emitter<ProcessEventMap>\n\treadonly #engine: Supervisor\n\treadonly #reader: ReadLineInterface\n\treadonly #backlog: number\n\treadonly #lines: AsyncIterable<string>\n\treadonly #queue: string[] = []\n\treadonly #waiters: Array<PromiseWithResolvers<IteratorResult<string, void>>> = []\n\t#head = 0\n\t#pending = 0\n\t#requested = false\n\t#paused = false\n\t#truncated = false\n\t#ended = false\n\n\t/**\n\t * Spawns one child process and begins stream capture.\n\t *\n\t * @param options - Command, workspace, termination, capture, stdin, and observation settings\n\t * @throws A {@link ProcessError} coded `invalid` when an option or command string is malformed\n\t */\n\tconstructor(options: ProcessOptions) {\n\t\t// Every option and command property is read once, here, before the engine spawns. Reading a\n\t\t// property runs the caller's own getter, so the engine receives these plain values and re-reads\n\t\t// none of them: a getter runs once whether the construction succeeds or is refused.\n\t\t// The engine's own options are validated first, in the order the engine reads them, and the\n\t\t// line pipeline's `backlog` after them, so a construction carrying more than one invalid option\n\t\t// reports the same option a single supervised face has always reported, and a malformed\n\t\t// `backlog` still refuses while nothing has been spawned.\n\t\tconst source = options.command\n\t\tconst workspace = options.workspace\n\t\tconst grace = options.grace\n\t\tconst drain = options.drain\n\t\tconst evidence = options.evidence\n\t\tconst backlog = options.backlog\n\t\tconst delivery = options.delivery\n\t\tconst writable = options.writable\n\t\tconst signal = options.signal\n\t\tconst on = options.on\n\t\tconst error = options.error\n\t\tconst command = snapshotCommand(source)\n\t\tvalidateCommand(command)\n\t\tvalidateWorkspace(workspace)\n\t\tvalidateTimer(grace, \"option 'grace'\")\n\t\tvalidateTimer(drain, \"option 'drain'\")\n\t\tvalidateTimer(delivery, \"option 'delivery'\")\n\t\tvalidateBytes(evidence, \"option 'evidence'\", 0)\n\t\tvalidateBytes(backlog, \"option 'backlog'\", 1)\n\t\tthis.#emitter = new Emitter<ProcessEventMap>({\n\t\t\t...(on === undefined ? {} : { on }),\n\t\t\t...(error === undefined ? {} : { error }),\n\t\t})\n\t\tthis.#backlog = backlog ?? PROCESS_BACKLOG\n\t\tthis.#lines = Object.freeze({ [Symbol.asyncIterator]: this.#iterate.bind(this) })\n\t\tthis.#engine = new Supervisor(\n\t\t\t{\n\t\t\t\tcommand,\n\t\t\t\tworkspace,\n\t\t\t\t...(grace === undefined ? {} : { grace }),\n\t\t\t\t...(drain === undefined ? {} : { drain }),\n\t\t\t\t...(evidence === undefined ? {} : { evidence }),\n\t\t\t\t...(delivery === undefined ? {} : { delivery }),\n\t\t\t\t...(writable === undefined ? {} : { writable }),\n\t\t\t\t...(signal === undefined ? {} : { signal }),\n\t\t\t},\n\t\t\t{\n\t\t\t\tchunk: this.#reportStderr.bind(this),\n\t\t\t\tfault: this.#reportFault.bind(this),\n\t\t\t\trelieve: this.#releaseBackpressure.bind(this),\n\t\t\t\tclose: this.#closeReader.bind(this),\n\t\t\t\tterminal: this.#reportExit.bind(this),\n\t\t\t\tteardown: this.#emitter.destroy.bind(this.#emitter),\n\t\t\t},\n\t\t)\n\t\t// The host delivers no output before this synchronous constructor returns, so framing attaches\n\t\t// here without losing a byte the engine already spawned for.\n\t\tthis.#reader = createInterface({ input: this.#engine.stdout, crlfDelay: Infinity })\n\t\tthis.#reader.on('line', this.#push.bind(this))\n\t\tthis.#reader.once('close', this.#finish.bind(this))\n\t}\n\n\t/** Holds the host process id, fixed when construction returns, or `undefined` when the spawn produced none. */\n\tget pid(): number | undefined {\n\t\treturn this.#engine.pid\n\t}\n\n\t/** Holds the exit code the host recorded, or `null` while the child has not exited and when a signal ended it. */\n\tget code(): number | null {\n\t\treturn this.#engine.code\n\t}\n\n\t/** Holds the terminating signal name the host recorded, or `null` while the child has not exited and when it exited on its own. */\n\tget signal(): string | null {\n\t\treturn this.#engine.signal\n\t}\n\n\t/** Holds the typed lifecycle observation surface. */\n\tget emitter(): EmitterInterface<ProcessEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\t/** Yields the captured stdout lines, in arrival order, ending after queued lines at the terminal moment. */\n\tget lines(): AsyncIterable<string> {\n\t\treturn this.#lines\n\t}\n\n\t/** Holds the decoded byte-bounded stderr tail, frozen at the terminal moment. */\n\tget evidence(): string {\n\t\treturn this.#engine.evidence\n\t}\n\n\t/** Reports whether the `lines` stream omitted output after a retention bound was reached. */\n\tget truncated(): boolean {\n\t\treturn this.#truncated\n\t}\n\n\t/** Reports whether the terminal moment arrived and `exit` settled. */\n\tget settled(): boolean {\n\t\treturn this.#engine.settled\n\t}\n\n\t/** Reports whether termination began, including after the terminal moment. */\n\tget terminated(): boolean {\n\t\treturn this.#engine.terminated\n\t}\n\n\t/** Settles with the terminal child state, observed once after stream close or the drain cutoff. */\n\tget exit(): Promise<ProcessExit> {\n\t\treturn this.#engine.exit\n\t}\n\n\t/**\n\t * Writes one line to the open standard-input channel.\n\t *\n\t * @remarks\n\t * Never rejects. `true` means the host accepted the bytes without reporting a fault; it does not\n\t * prove that the child read them. An ordinary write settles when the kernel accepts it. Only a\n\t * full pipe can hold the write unconfirmed. The `delivery` option can bound that wait, and every\n\t * terminal teardown path settles pending writes. On Windows 11 with Node v24.18.1, measured on\n\t * 2026-08-21, a child that closes its own file descriptor 0 can leave the parent pipe writable:\n\t * the write can settle `true` without a callback error or a stream error while the child remains\n\t * alive. After `stop` or `destroy` begins, a later call settles `false`. Version 0.0.4 could settle\n\t * that call `true` before teardown destroyed the pipe; returning `false` avoids claiming delivery\n\t * for bytes the package is about to discard.\n\t *\n\t * @param text - The line text without its trailing newline\n\t * @returns True if the host accepted the bytes without reporting a fault; false otherwise (the channel was closed, destroyed, ended, failed, or the write remained unconfirmed through `delivery`)\n\t */\n\tsend(text: string): Promise<boolean> {\n\t\treturn this.#engine.deliver(Buffer.from(`${text}\\n`, 'utf8'))\n\t}\n\n\t/**\n\t * Terminates the child process tree and reaches the terminal observation moment.\n\t *\n\t * @remarks\n\t * Never rejects, and every call shares one termination. After the termination sequence returns,\n\t * confirmed or not, it waits at most `drain` for the read channels to close, then cuts them off\n\t * and settles `exit` when they remain open. A cutoff reached before the native exit reports the\n\t * `code` and `signal` the host had recorded by then, which is `null` for a child still running.\n\t *\n\t * @returns True if the child's native exit was observed; false otherwise (the confirmation deadline elapsed without it)\n\t */\n\tstop(): Promise<boolean> {\n\t\treturn this.#engine.stop()\n\t}\n\n\t/**\n\t * Stops the child and destroys the observation emitter after the terminal state freezes.\n\t *\n\t * @remarks\n\t * Always resolves, including when termination was never confirmed. Every call shares one barrier.\n\t *\n\t * @returns The stable barrier shared by every call\n\t */\n\tdestroy(): Promise<void> {\n\t\treturn this.#engine.destroy()\n\t}\n\n\t#iterate(): AsyncIterator<string, void, void> {\n\t\tthis.#requested = true\n\t\treturn Object.freeze({ next: this.#next.bind(this) })\n\t}\n\n\t#next(): Promise<IteratorResult<string, void>> {\n\t\tconst line = this.#take()\n\t\tif (line !== undefined) return Promise.resolve(Object.freeze({ done: false, value: line }))\n\t\tif (this.#ended) return Promise.resolve(Object.freeze({ done: true, value: undefined }))\n\t\tconst waiter = Promise.withResolvers<IteratorResult<string, void>>()\n\t\tthis.#waiters.push(waiter)\n\t\treturn waiter.promise\n\t}\n\n\t// Dequeues through a read index, so draining a long backlog stays linear.\n\t#take(): string | undefined {\n\t\tif (this.#head >= this.#queue.length) return undefined\n\t\tconst line = this.#queue[this.#head]\n\t\tthis.#queue[this.#head] = ''\n\t\tthis.#head += 1\n\t\tif (this.#head >= this.#queue.length) {\n\t\t\tthis.#queue.length = 0\n\t\t\tthis.#head = 0\n\t\t}\n\t\tif (line === undefined) return undefined\n\t\tthis.#pending -= Buffer.byteLength(line) + 1\n\t\tthis.#relieve()\n\t\treturn line\n\t}\n\n\t#push(line: string): void {\n\t\tif (this.#ended) return\n\t\tconst waiter = this.#waiters.shift()\n\t\tif (waiter !== undefined) {\n\t\t\twaiter.resolve(Object.freeze({ done: false, value: line }))\n\t\t\treturn\n\t\t}\n\t\t// A retained line costs its payload plus the newline that framed it, so an empty line still\n\t\t// costs a byte and a flood of them reaches the mark.\n\t\tconst bytes = Buffer.byteLength(line) + 1\n\t\t// With no consumer ever attached, retention stops at the mark and the stream keeps draining\n\t\t// so the child can exit; a consumer attaching later receives the head, a gap, then the live\n\t\t// stream.\n\t\tconst terminated = this.#engine.terminated\n\t\tconst limit = terminated ? this.#backlog * 2 : this.#backlog\n\t\tif ((!this.#requested || terminated) && this.#pending + bytes > limit) {\n\t\t\tthis.#truncated = true\n\t\t\treturn\n\t\t}\n\t\tthis.#queue.push(line)\n\t\tthis.#pending += bytes\n\t\tthis.#restrain()\n\t}\n\n\t#restrain(): void {\n\t\tif (this.#paused || this.#engine.terminated || !this.#requested) return\n\t\tif (this.#pending < this.#backlog) return\n\t\tthis.#paused = true\n\t\tthis.#reader.pause()\n\t}\n\n\t#relieve(): void {\n\t\tif (!this.#paused || this.#ended) return\n\t\tif (!this.#engine.terminated && this.#pending > this.#backlog / 2) return\n\t\tthis.#paused = false\n\t\tthis.#reader.resume()\n\t}\n\n\t#finish(): void {\n\t\tif (this.#ended) return\n\t\tthis.#ended = true\n\t\tthis.#paused = false\n\t\tfor (const waiter of this.#waiters) {\n\t\t\twaiter.resolve(Object.freeze({ done: true, value: undefined }))\n\t\t}\n\t\tthis.#waiters.length = 0\n\t}\n\n\t// The engine publishes nothing itself, so each moment it hands over is republished here on this\n\t// face's own typed event map. A generic `emit` cannot be bound to one event without collapsing\n\t// its payload to the first member of the map.\n\t#reportStderr(chunk: string): void {\n\t\tthis.#emitter.emit('stderr', chunk)\n\t}\n\n\t#reportFault(cause: unknown): void {\n\t\tthis.#emitter.emit('error', cause)\n\t}\n\n\t#reportExit(exit: ProcessExit): void {\n\t\tthis.#emitter.emit('exit', exit)\n\t}\n\n\t// Closing readline ends pending reads while preserving lines already framed and queued.\n\t#closeReader(): void {\n\t\tthis.#reader.close()\n\t}\n\n\t// A paused stdout holds the child's own write, and therefore its exit. Bound the retained head,\n\t// then release backpressure before the engine signals; later lines drop at the teardown cap\n\t// instead of pausing the reader again.\n\t#releaseBackpressure(): void {\n\t\tthis.#capBacklog()\n\t\tthis.#relieve()\n\t}\n\n\t#capBacklog(): void {\n\t\tconst limit = this.#backlog * 2\n\t\twhile (this.#pending > limit && this.#queue.length > this.#head) {\n\t\t\tconst line = this.#queue.pop()\n\t\t\tif (line === undefined) break\n\t\t\tthis.#pending -= Buffer.byteLength(line) + 1\n\t\t\tthis.#truncated = true\n\t\t}\n\t}\n}\n","import type { EmitterInterface } from '@orkestrel/emitter'\nimport type {\n\tProcessExit,\n\tProcessInterface,\n\tProcessManagerEventMap,\n\tProcessManagerInterface,\n\tProcessManagerOptions,\n\tProcessOptions,\n} from '@src/core'\nimport { isString } from '@orkestrel/contract'\nimport { Emitter } from '@orkestrel/emitter'\nimport { createDuplicateError, createProtocolError } from '@src/core'\nimport { Process } from './Process.js'\n\n/**\n * Launches supervised children under caller-chosen ids, evicts each one as it settles, and destroys\n * every live child on teardown.\n *\n * @remarks\n * A child launched under an id joins the registry and emits `launch`; when it settles it removes\n * itself and emits `exit`, so `count` and `processes` reflect only live children. The id is reserved\n * before the child is constructed and released when construction throws, so a refused launch never\n * strands its key. Eviction follows the child's own `exit` promise, which no listener can forge, so\n * it lands one microtask after the child's public `exit` event: a listener on that event still sees\n * the child registered. `launch` throws a {@link createDuplicateError} when the id is already live\n * and a {@link createProtocolError} after `destroy` has begun, including when the caller's own option\n * getter begins that teardown mid-construction — a spawn fault surfaces through the returned child's\n * `exit`, never from `launch`. `destroy` awaits every child's own teardown, including the teardown\n * of a child a lost race refused, which destroys each child's observation emitter and leaves every\n * subscription on it silently inert, then destroys the registry emitter last.\n *\n * @example\n * ```ts\n * import { ProcessManager } from '@orkestrel/process/server'\n *\n * const manager = new ProcessManager()\n * const child = manager.launch('build', {\n * \tcommand: { file: 'node', arguments: ['build.js'] },\n * \tworkspace: process.cwd(),\n * })\n * await child.exit\n * await manager.destroy()\n * ```\n */\nexport class ProcessManager implements ProcessManagerInterface {\n\treadonly #emitter: Emitter<ProcessManagerEventMap>\n\treadonly #children = new Map<string, ProcessInterface>()\n\treadonly #ids = new Set<string>()\n\t// The children a launch spawned into a registry that was already being destroyed. They are never\n\t// registered, so `#teardown` cannot reach them through `#children`, and it drains this set instead.\n\treadonly #orphans = new Set<ProcessInterface>()\n\t// A guard reads `#destroying`, never `#ended !== undefined`. `destroy` assigns the boolean before\n\t// it assigns the barrier, so the boolean also covers the synchronous prefix of the teardown, which\n\t// runs while `#ended` is still `undefined`.\n\t#destroying = false\n\t#ended: Promise<void> | undefined\n\n\t/**\n\t * Constructs a process registry.\n\t *\n\t * @param options - Initial fleet-level observation hooks and listener-error handling\n\t */\n\tconstructor(options?: ProcessManagerOptions) {\n\t\tconst on = options?.on\n\t\tconst error = options?.error\n\t\tthis.#emitter = new Emitter<ProcessManagerEventMap>({\n\t\t\t...(on === undefined ? {} : { on }),\n\t\t\t...(error === undefined ? {} : { error }),\n\t\t})\n\t}\n\n\t/** Holds the typed fleet-level observation surface. */\n\tget emitter(): EmitterInterface<ProcessManagerEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\t/** Counts the live children. */\n\tget count(): number {\n\t\treturn this.#children.size\n\t}\n\n\t/**\n\t * Returns the live child under `id`, or `undefined` when none is.\n\t *\n\t * @param id - The registry key\n\t * @returns The child, or `undefined`\n\t */\n\tprocess(id: string): ProcessInterface | undefined {\n\t\treturn this.#children.get(id)\n\t}\n\n\t/**\n\t * Returns a snapshot of every live child.\n\t *\n\t * @returns The live children in launch order\n\t */\n\tprocesses(): readonly ProcessInterface[] {\n\t\treturn [...this.#children.values()]\n\t}\n\n\t/**\n\t * Spawns and registers one child under `id`.\n\t *\n\t * @remarks\n\t * {@link Process} reads every option before it spawns, so a caller's own option getter runs while\n\t * nothing has started and a throw from one strands no process. A getter that begins `destroy`\n\t * without throwing is the one remaining race: the child is already spawned, so the launch is\n\t * refused with a {@link createProtocolError} and that child is destroyed rather than adopted, its\n\t * teardown bounded by `grace` plus the confirmation window. The `protocol` refusal throws\n\t * synchronously, and the `destroy` barrier covers that teardown, so the refused child reaches its\n\t * terminal moment before the barrier resolves.\n\t *\n\t * @param id - The registry key, unique among live children\n\t * @param options - The child construction options\n\t * @returns The launched child\n\t * @throws A {@link ProcessError} coded `duplicate` when `id` is already live, `protocol` when the registry is being destroyed, or `invalid` when an option or command string is malformed\n\t */\n\tlaunch(id: string, options: ProcessOptions): ProcessInterface {\n\t\tif (this.#destroying) throw createProtocolError(id)\n\t\tif (this.#ids.has(id)) throw createDuplicateError(id)\n\t\tthis.#ids.add(id)\n\t\tconst child = this.#construct(id, options)\n\t\t// Reading an option runs the caller's own code, so teardown can begin between the check above\n\t\t// and the child that is now spawned. A registry being destroyed adopts nothing: the child is\n\t\t// torn down here, the reservation goes back, and the launch is refused. The child joins\n\t\t// `#orphans` before its teardown starts, so `#teardown` covers it however far that teardown\n\t\t// has already progressed.\n\t\tif (this.#destroying) {\n\t\t\tthis.#ids.delete(id)\n\t\t\tthis.#orphans.add(child)\n\t\t\tvoid child.destroy()\n\t\t\tthrow createProtocolError(id)\n\t\t}\n\t\tthis.#children.set(id, child)\n\t\tvoid child.exit.then((exit) => this.#evict(id, child, exit))\n\t\tthis.#emitter.emit('launch', id)\n\t\treturn child\n\t}\n\n\t/**\n\t * Terminates the named children and awaits their exit.\n\t *\n\t * @param ids - The registry keys to stop\n\t * @returns True if every named child was live and its exit was confirmed; false otherwise\n\t */\n\tstop(ids: readonly string[]): Promise<boolean>\n\t/**\n\t * Terminates one child and awaits its exit.\n\t *\n\t * @param id - The registry key to stop\n\t * @returns True if the child was live and its exit was confirmed; false otherwise (the id was not live, or the confirmation deadline elapsed)\n\t */\n\tstop(id: string): Promise<boolean>\n\t/**\n\t * Terminates every live child and awaits their exit.\n\t *\n\t * @returns A promise that resolves after every child stops\n\t */\n\tstop(): Promise<void>\n\tstop(target?: string | readonly string[]): Promise<boolean | void> {\n\t\tif (target === undefined) return this.#stopAll()\n\t\tif (isString(target)) return this.#stopOne(target)\n\t\treturn this.#stopMany(target)\n\t}\n\n\t/**\n\t * Stops every child, then destroys the registry emitter last.\n\t *\n\t * @remarks\n\t * Always resolves, and refuses a later `launch` with a {@link createProtocolError}. Each child is\n\t * destroyed rather than merely stopped, so its own observation emitter is destroyed too and every\n\t * subscription on it goes silently inert.\n\t *\n\t * @returns The stable barrier shared by every call\n\t */\n\tdestroy(): Promise<void> {\n\t\tif (this.#ended !== undefined) return this.#ended\n\t\tthis.#destroying = true\n\t\tthis.#ended = this.#teardown()\n\t\treturn this.#ended\n\t}\n\n\t// Releases the reservation when construction throws, so a refused launch strands no id.\n\t#construct(id: string, options: ProcessOptions): ProcessInterface {\n\t\ttry {\n\t\t\treturn new Process(options)\n\t\t} catch (error) {\n\t\t\tthis.#ids.delete(id)\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t#evict(id: string, child: ProcessInterface, exit: ProcessExit): void {\n\t\tif (this.#children.get(id) !== child) return\n\t\tthis.#children.delete(id)\n\t\tthis.#ids.delete(id)\n\t\tthis.#emitter.emit('exit', id, exit)\n\t}\n\n\tasync #stopOne(id: string): Promise<boolean> {\n\t\tconst child = this.#children.get(id)\n\t\tif (child === undefined) return false\n\t\treturn child.stop()\n\t}\n\n\tasync #stopMany(ids: readonly string[]): Promise<boolean> {\n\t\tconst stopped = await Promise.all(ids.map((id) => this.#stopOne(id)))\n\t\treturn stopped.every((ok) => ok)\n\t}\n\n\tasync #stopAll(): Promise<void> {\n\t\tawait Promise.allSettled([...this.#children.values()].map((child) => child.stop()))\n\t}\n\n\tasync #teardown(): Promise<void> {\n\t\tawait Promise.allSettled([...this.#children.values()].map((child) => child.destroy()))\n\t\t// A launch that lost the race spawns its child after the line above read the registry, so the\n\t\t// barrier picks those children up here. Each pass takes the whole set and empties it, so a\n\t\t// child that arrives while an earlier pass is still awaiting is covered by the next one and no\n\t\t// child is awaited twice; the loop ends only on a pass that found the set empty. `destroy` on\n\t\t// a child is idempotent, so awaiting it here joins the teardown `launch` already began rather\n\t\t// than starting a second one. Every loser of the race is therefore covered, however many of\n\t\t// them one turn produces: a loser can only be a `launch` that passed the guard before\n\t\t// `#destroying` was set, and every such call is already on the stack when this runs.\n\t\twhile (this.#orphans.size > 0) {\n\t\t\tconst orphans = [...this.#orphans]\n\t\t\tthis.#orphans.clear()\n\t\t\tawait Promise.allSettled(orphans.map((child) => child.destroy()))\n\t\t}\n\t\t// A destroyed registry holds nothing: a child whose stdio a descendant still holds would\n\t\t// otherwise linger here until a close event that may never arrive.\n\t\tthis.#children.clear()\n\t\tthis.#ids.clear()\n\t\tthis.#emitter.destroy()\n\t}\n}\n","import type { EmitterInterface } from '@orkestrel/emitter'\nimport type { ProcessExit, SessionEventMap, SessionInterface, SessionOptions } from '@src/core'\nimport { Buffer } from 'node:buffer'\nimport { Emitter } from '@orkestrel/emitter'\nimport { Supervisor } from './Supervisor.js'\n\n/**\n * Supervises one child and publishes its standard output as raw bytes.\n *\n * @remarks\n * This is the transport face of the supervision engine `Process` also composes. It frames nothing,\n * retains nothing, and decodes nothing on the output side: every chunk the host delivers becomes one\n * `stdout` event carrying that chunk's bytes, in arrival order, so a consumer speaking a\n * length-prefixed or delimiter-framed protocol reads exactly what the child wrote and frames it\n * itself. Standard error is decoded and forwarded as `stderr`, with the same byte-bounded `evidence`\n * tail a `Process` retains, because a diagnostic stream is read rather than parsed.\n *\n * Each emitted chunk is this session's own copy, and a plain `Uint8Array` rather than the host buffer\n * the read produced, so a consumer keeps it, mutates it, concatenates it, and reads its whole backing\n * buffer without reaching memory the host still manages and without depending on a host type.\n *\n * The standard-input channel is open from the spawn, and `end` closes it without terminating\n * anything. That is the member a cooperative protocol reaches for: the child observes end of input\n * and exits on its own, which `ended` reports. `stop` and `destroy` remain the terminations, and\n * `exit` remains the terminal moment — the native exit plus at most `drain` while a descendant holds\n * the inherited read ends.\n *\n * @example\n * ```ts\n * import { Session } from '@orkestrel/process/server'\n *\n * const session = new Session({\n * \tcommand: { file: 'node', arguments: ['-e', 'process.stdin.pipe(process.stdout)'] },\n * \tworkspace: process.cwd(),\n * })\n * ```\n */\nexport class Session implements SessionInterface {\n\treadonly #emitter: Emitter<SessionEventMap>\n\treadonly #engine: Supervisor\n\treadonly #output: (chunk: unknown) => void\n\n\t/**\n\t * Spawns one child process and begins byte capture.\n\t *\n\t * @param options - Command, workspace, termination, evidence, stdin, and observation settings\n\t * @throws A {@link ProcessError} coded `invalid` when an option or command string is malformed\n\t */\n\tconstructor(options: SessionOptions) {\n\t\t// Every option is read once, here, before the engine reads the command and spawns anything.\n\t\t// Reading a property runs the caller's own getter, so a read after the spawn would let that\n\t\t// getter throw while a live child exists and nobody holds a reference to it. The engine\n\t\t// receives the plain values in the following literal and validates each one before it spawns,\n\t\t// so an invalid option and a throwing getter alike refuse construction while nothing has\n\t\t// started.\n\t\tconst command = options.command\n\t\tconst workspace = options.workspace\n\t\tconst grace = options.grace\n\t\tconst drain = options.drain\n\t\tconst evidence = options.evidence\n\t\tconst delivery = options.delivery\n\t\tconst signal = options.signal\n\t\tconst on = options.on\n\t\tconst error = options.error\n\t\tthis.#emitter = new Emitter<SessionEventMap>({\n\t\t\t...(on === undefined ? {} : { on }),\n\t\t\t...(error === undefined ? {} : { error }),\n\t\t})\n\t\tthis.#output = this.#publish.bind(this)\n\t\tthis.#engine = new Supervisor(\n\t\t\t{\n\t\t\t\tcommand,\n\t\t\t\tworkspace,\n\t\t\t\t// The channel stays open from the spawn until `end` closes it, so a session selects\n\t\t\t\t// nothing here and declares no `writable` option of its own.\n\t\t\t\twritable: true,\n\t\t\t\t...(grace === undefined ? {} : { grace }),\n\t\t\t\t...(drain === undefined ? {} : { drain }),\n\t\t\t\t...(evidence === undefined ? {} : { evidence }),\n\t\t\t\t...(delivery === undefined ? {} : { delivery }),\n\t\t\t\t...(signal === undefined ? {} : { signal }),\n\t\t\t},\n\t\t\t{\n\t\t\t\tchunk: this.#reportStderr.bind(this),\n\t\t\t\tfault: this.#reportFault.bind(this),\n\t\t\t\tclose: this.#closeOutput.bind(this),\n\t\t\t\tterminal: this.#reportExit.bind(this),\n\t\t\t\tteardown: this.#emitter.destroy.bind(this.#emitter),\n\t\t\t},\n\t\t)\n\t\t// The host delivers no output before this synchronous constructor returns, so the consumer\n\t\t// attaches here without losing a byte the engine already spawned for. Attaching is also what\n\t\t// puts stdout in flowing mode, which is what a session wants: it retains nothing, and a paused\n\t\t// stream would hold the child's own write and therefore its exit.\n\t\tthis.#engine.stdout.on('data', this.#output)\n\t}\n\n\t/** Holds the host process id, fixed when construction returns, or `undefined` when the spawn produced none. */\n\tget pid(): number | undefined {\n\t\treturn this.#engine.pid\n\t}\n\n\t/** Holds the exit code the host recorded, or `null` while the child has not exited and when a signal ended it. */\n\tget code(): number | null {\n\t\treturn this.#engine.code\n\t}\n\n\t/** Holds the terminating signal name the host recorded, or `null` while the child has not exited and when it exited on its own. */\n\tget signal(): string | null {\n\t\treturn this.#engine.signal\n\t}\n\n\t/** Holds the typed lifecycle observation surface. */\n\tget emitter(): EmitterInterface<SessionEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\t/** Holds the decoded byte-bounded stderr tail, frozen at the terminal moment. */\n\tget evidence(): string {\n\t\treturn this.#engine.evidence\n\t}\n\n\t/** Reports whether the terminal moment arrived and `exit` settled. */\n\tget settled(): boolean {\n\t\treturn this.#engine.settled\n\t}\n\n\t/** Reports whether termination began, including after the terminal moment. `end` never turns it true. */\n\tget terminated(): boolean {\n\t\treturn this.#engine.terminated\n\t}\n\n\t/** Settles at the child's own ending, awaited without the terminal moment's drain window. */\n\tget ended(): Promise<void> {\n\t\treturn this.#engine.ended\n\t}\n\n\t/** Settles with the terminal child state, observed once after stream close or the drain cutoff. */\n\tget exit(): Promise<ProcessExit> {\n\t\treturn this.#engine.exit\n\t}\n\n\t/**\n\t * Writes raw bytes to the open standard-input channel.\n\t *\n\t * @remarks\n\t * Never rejects, and appends no terminator: the child receives exactly these bytes. `true` means\n\t * the host accepted them without reporting a fault; it does not prove that the child read them.\n\t * The channel can queue the payload, so treat the array as owned by the channel until the\n\t * returned promise settles.\n\t *\n\t * @param bytes - The payload to write, already framed by the caller\n\t * @returns True if the host accepted the bytes without reporting a fault; false otherwise (the channel was closed, destroyed, ended, failed, or the write remained unconfirmed through `delivery`)\n\t */\n\twrite(bytes: Uint8Array): Promise<boolean> {\n\t\treturn this.#engine.deliver(bytes)\n\t}\n\n\t/**\n\t * Closes the standard-input channel and leaves the child running.\n\t *\n\t * @remarks\n\t * Never rejects and terminates nothing: `terminated` stays false and the terminal moment does not\n\t * arrive. Every call shares one barrier, which resolves after the host flushes the writes it had\n\t * already accepted. A later `write` resolves `false`.\n\t *\n\t * @returns The stable barrier shared by every call\n\t */\n\tend(): Promise<void> {\n\t\treturn this.#engine.end()\n\t}\n\n\t/**\n\t * Terminates the child process tree and reaches the terminal observation moment.\n\t *\n\t * @remarks\n\t * Never rejects, and every call shares one termination bounded by `grace` and `drain`.\n\t *\n\t * @returns True if the child's native exit was observed; false otherwise (the confirmation deadline elapsed without it)\n\t */\n\tstop(): Promise<boolean> {\n\t\treturn this.#engine.stop()\n\t}\n\n\t/**\n\t * Stops the child and destroys the observation emitter after the terminal state freezes.\n\t *\n\t * @remarks\n\t * Always resolves, including when termination was never confirmed. Every call shares one barrier.\n\t *\n\t * @returns The stable barrier shared by every call\n\t */\n\tdestroy(): Promise<void> {\n\t\treturn this.#engine.destroy()\n\t}\n\n\t// One owned copy per host chunk, taken before the payload leaves this class. The settled check\n\t// keeps the other invariant this publisher owns: the engine hands over its terminal moment before\n\t// it destroys the read ends, so nothing this stream still holds arrives after the `exit` event.\n\t#publish(chunk: unknown): void {\n\t\tif (!Buffer.isBuffer(chunk) || this.#engine.settled) return\n\t\tthis.#emitter.emit('stdout', new Uint8Array(chunk))\n\t}\n\n\t// The engine publishes nothing itself, so each moment it hands over is republished here on this\n\t// face's own typed event map. A generic `emit` cannot be bound to one event without collapsing\n\t// its payload to the first member of the map.\n\t#reportStderr(chunk: string): void {\n\t\tthis.#emitter.emit('stderr', chunk)\n\t}\n\n\t#reportFault(cause: unknown): void {\n\t\tthis.#emitter.emit('error', cause)\n\t}\n\n\t#reportExit(exit: ProcessExit): void {\n\t\tthis.#emitter.emit('exit', exit)\n\t}\n\n\t// Releasing the consumer at the terminal moment, rather than letting the engine's stream\n\t// destruction reach it, is what keeps a `stdout` event from following the `exit` event.\n\t#closeOutput(): void {\n\t\tthis.#engine.stdout.off('data', this.#output)\n\t}\n}\n","import type {\n\tProcessInterface,\n\tProcessManagerInterface,\n\tProcessManagerOptions,\n\tProcessOptions,\n\tSessionInterface,\n\tSessionOptions,\n} from '@src/core'\nimport { Process } from './processes/Process.js'\nimport { ProcessManager } from './processes/ProcessManager.js'\nimport { Session } from './processes/Session.js'\n\n/**\n * Creates one supervised child process and returns it as a {@link ProcessInterface}, so a caller\n * holds the published contract rather than the `Process` class.\n *\n * @param options - Command, workspace, termination, evidence, stdin, and observation settings\n * @returns The launched {@link ProcessInterface}\n *\n * @example Supervise a child and read its lines\n * ```ts\n * import { createProcess } from '@orkestrel/process/server'\n *\n * const child = createProcess({\n * \tcommand: { file: 'node', arguments: ['-e', 'console.log(\"ready\"); console.log(\"done\")'] },\n * \tworkspace: process.cwd(),\n * \tgrace: 5_000, // POSIX only: the window between SIGTERM and SIGKILL\n * })\n *\n * const lines: string[] = []\n * for await (const line of child.lines) lines.push(line)\n * lines // ['ready', 'done']\n *\n * const exit = await child.exit\n * exit.code // 0\n * await child.destroy()\n * ```\n */\nexport function createProcess(options: ProcessOptions): ProcessInterface {\n\treturn new Process(options)\n}\n\n/**\n * Creates one raw byte session over a supervised child process and returns it as a\n * {@link SessionInterface}, so a caller holds the published contract rather than the `Session` class.\n *\n * @param options - Command, workspace, termination, evidence, stdin, and observation settings\n * @returns The launched {@link SessionInterface}\n *\n * @example\n * ```ts\n * import { createSession } from '@orkestrel/process/server'\n *\n * const session = createSession({\n * \tcommand: { file: 'node', arguments: ['server.js', '--stdio'] },\n * \tworkspace: process.cwd(),\n * \tgrace: 5000,\n * })\n * ```\n */\nexport function createSession(options: SessionOptions): SessionInterface {\n\treturn new Session(options)\n}\n\n/**\n * Creates one empty keyed registry of supervised child processes and returns it as a\n * {@link ProcessManagerInterface}, so a caller holds the published contract rather than the\n * `ProcessManager` class.\n *\n * @param options - Initial fleet-level observation hooks and listener-error handling\n * @returns The {@link ProcessManagerInterface} registry\n *\n * @example\n * ```ts\n * import { createProcessManager } from '@orkestrel/process/server'\n *\n * const manager = createProcessManager()\n * ```\n */\nexport function createProcessManager(options?: ProcessManagerOptions): ProcessManagerInterface {\n\treturn new ProcessManager(options)\n}\n","import type { ChildProcessWithoutNullStreams } from 'node:child_process'\nimport type { ExecuteOptions, ExecuteResult, ProcessCommand } from '@src/core'\nimport { Buffer } from 'node:buffer'\nimport { spawn } from 'node:child_process'\nimport {\n\tcreateExecuteError,\n\tPROCESS_CONFIRMATION,\n\tPROCESS_GRACE,\n\tPROCESS_OUTPUT,\n\tProcessError,\n} from '@src/core'\nimport { snapshotCommand } from '../cloners.js'\nimport {\n\tbuildExecuteResult,\n\tbuildSpawn,\n\tcaptureChunk,\n\tformatCommand,\n\tmergeEnvironment,\n\tstopChild,\n\tvalidateBytes,\n\tvalidateCommand,\n\tvalidateEnvironment,\n\tvalidateTimer,\n\tvalidateWorkspace,\n} from '../helpers.js'\n\n/** Owns the child, capture, cancellation, and terminal state of one buffered execution. */\nexport class Execution {\n\treadonly #child: ChildProcessWithoutNullStreams\n\treadonly #settled: PromiseWithResolvers<ExecuteResult>\n\treadonly #terminate: AbortController\n\treadonly #cleanup: AbortController\n\treadonly #finish: AbortController\n\treadonly #inputFailure: AbortController\n\treadonly #outChunks: Buffer[] = []\n\treadonly #errChunks: Buffer[] = []\n\treadonly #strict: boolean\n\t#spawned = false\n\t#expired = false\n\t#aborted = false\n\t#outRetained = 0\n\t#errRetained = 0\n\t#cause: unknown\n\t#timeoutTimer: ReturnType<typeof setTimeout> | undefined\n\t#confirmTimer: ReturnType<typeof setTimeout> | undefined\n\n\tconstructor(command: ProcessCommand, options?: ExecuteOptions) {\n\t\tconst snapshot = snapshotCommand(command)\n\t\tconst optionEnvironment = options?.environment\n\t\tconst optionWorkspace = options?.workspace\n\t\tconst optionInput = options?.input\n\t\tconst optionTimeout = options?.timeout\n\t\tconst optionGrace = options?.grace\n\t\tconst optionSignal = options?.signal\n\t\tconst optionStrict = options?.strict\n\t\tconst optionLimit = options?.limit\n\t\tvalidateCommand(snapshot)\n\t\tvalidateEnvironment(optionEnvironment)\n\t\tvalidateWorkspace(optionWorkspace)\n\t\tvalidateTimer(optionTimeout, \"option 'timeout'\")\n\t\tvalidateTimer(optionGrace, \"option 'grace'\")\n\t\tvalidateBytes(optionLimit, \"option 'limit'\", 0)\n\t\tconst limit = optionLimit ?? PROCESS_OUTPUT\n\t\tconst grace = optionGrace ?? PROCESS_GRACE\n\t\tconst timeout = optionTimeout ?? 0\n\t\tthis.#strict = optionStrict ?? true\n\t\tconst text = optionInput ?? snapshot.input\n\t\tconst line = formatCommand(snapshot)\n\t\tconst workspace = optionWorkspace ?? process.cwd()\n\t\tconst environment = mergeEnvironment(\n\t\t\tsnapshot.isolated === true,\n\t\t\tsnapshot.environment,\n\t\t\toptionEnvironment,\n\t\t)\n\t\tconst plan = buildSpawn(snapshot, { workspace, environment })\n\t\tthis.#settled = Promise.withResolvers<ExecuteResult>()\n\t\tthis.#terminate = new AbortController()\n\t\tthis.#cleanup = new AbortController()\n\t\tthis.#finish = new AbortController()\n\t\tthis.#inputFailure = new AbortController()\n\n\t\tthis.#child = spawn(plan.file, [...plan.arguments], {\n\t\t\tcwd: workspace,\n\t\t\tdetached: process.platform !== 'win32',\n\t\t\tenv: environment,\n\t\t\tstdio: ['pipe', 'pipe', 'pipe'],\n\t\t\twindowsHide: true,\n\t\t\twindowsVerbatimArguments: plan.verbatim,\n\t\t})\n\n\t\tthis.#finish.signal.addEventListener(\n\t\t\t'abort',\n\t\t\t() => {\n\t\t\t\tclearTimeout(this.#timeoutTimer)\n\t\t\t\tclearTimeout(this.#confirmTimer)\n\t\t\t\tthis.#cleanup.abort()\n\t\t\t\tthis.#settled.resolve(\n\t\t\t\t\tbuildExecuteResult({\n\t\t\t\t\t\tcommand: line,\n\t\t\t\t\t\tstdout: Buffer.concat(this.#outChunks),\n\t\t\t\t\t\tstderr: Buffer.concat(this.#errChunks),\n\t\t\t\t\t\tcode: this.#child.exitCode,\n\t\t\t\t\t\tsignal: this.#child.signalCode,\n\t\t\t\t\t\texpired: this.#expired,\n\t\t\t\t\t\taborted: this.#aborted,\n\t\t\t\t\t\ttruncated: this.#outRetained > limit || this.#errRetained > limit,\n\t\t\t\t\t\tlimit,\n\t\t\t\t\t\t...(this.#cause === undefined ? {} : { cause: this.#cause }),\n\t\t\t\t\t}),\n\t\t\t\t)\n\t\t\t},\n\t\t\t{ once: true },\n\t\t)\n\n\t\tthis.#terminate.signal.addEventListener(\n\t\t\t'abort',\n\t\t\t() => {\n\t\t\t\tif (this.#finish.signal.aborted) return\n\t\t\t\tclearTimeout(this.#timeoutTimer)\n\t\t\t\tthis.#cleanup.abort()\n\t\t\t\tvoid stopChild(this.#child, grace, PROCESS_CONFIRMATION).then(() => {\n\t\t\t\t\tif (this.#finish.signal.aborted) return\n\t\t\t\t\tthis.#confirmTimer = setTimeout(() => this.#finish.abort(), PROCESS_CONFIRMATION)\n\t\t\t\t})\n\t\t\t},\n\t\t\t{ once: true },\n\t\t)\n\n\t\tthis.#inputFailure.signal.addEventListener(\n\t\t\t'abort',\n\t\t\t() => {\n\t\t\t\tif (this.#finish.signal.aborted) return\n\t\t\t\tthis.#cause = this.#inputFailure.signal.reason\n\t\t\t\tthis.#terminate.abort()\n\t\t\t},\n\t\t\t{ once: true },\n\t\t)\n\n\t\tthis.#child.stdin.on('error', (error: Error) => this.#inputFailure.abort(error))\n\t\tthis.#child.stdout.on('data', (chunk: unknown) => {\n\t\t\tconst captured = captureChunk(chunk, limit + 1 - this.#outRetained)\n\t\t\tif (captured === undefined) return\n\t\t\tthis.#outRetained += captured.byteLength\n\t\t\tthis.#outChunks.push(captured)\n\t\t})\n\t\tthis.#child.stderr.on('data', (chunk: unknown) => {\n\t\t\tconst captured = captureChunk(chunk, limit + 1 - this.#errRetained)\n\t\t\tif (captured === undefined) return\n\t\t\tthis.#errRetained += captured.byteLength\n\t\t\tthis.#errChunks.push(captured)\n\t\t})\n\t\tthis.#child.once('spawn', () => {\n\t\t\tthis.#spawned = true\n\t\t})\n\t\tthis.#child.once('error', (error: unknown) => {\n\t\t\tif (this.#spawned) return\n\t\t\tthis.#cause = error\n\t\t\tthis.#finish.abort()\n\t\t})\n\t\tthis.#child.once('close', () => this.#finish.abort())\n\n\t\tif (text !== undefined) {\n\t\t\tthis.#child.stdin.write(text, (error?: Error | null) => {\n\t\t\t\tif (error !== undefined && error !== null) this.#inputFailure.abort(error)\n\t\t\t})\n\t\t}\n\t\tthis.#child.stdin.end()\n\t\tif (timeout > 0) {\n\t\t\tthis.#timeoutTimer = setTimeout(() => {\n\t\t\t\tthis.#expired = true\n\t\t\t\tthis.#terminate.abort()\n\t\t\t}, timeout)\n\t\t}\n\t\tif (optionSignal !== undefined) {\n\t\t\toptionSignal.addEventListener(\n\t\t\t\t'abort',\n\t\t\t\t() => {\n\t\t\t\t\tthis.#aborted = true\n\t\t\t\t\tthis.#terminate.abort()\n\t\t\t\t},\n\t\t\t\t{ once: true, signal: this.#cleanup.signal },\n\t\t\t)\n\t\t\tif (optionSignal.aborted) {\n\t\t\t\tthis.#aborted = true\n\t\t\t\tthis.#terminate.abort()\n\t\t\t}\n\t\t}\n\t}\n\n\tget settled(): Promise<ExecuteResult> {\n\t\treturn this.#settled.promise\n\t}\n\n\tread(result: ExecuteResult): ExecuteResult {\n\t\tif (result.failed && this.#strict) {\n\t\t\tif (this.#cause !== undefined && this.#cause === this.#inputFailure.signal.reason) {\n\t\t\t\tthrow new ProcessError(`Command '${result.command}' failed while writing standard input`, {\n\t\t\t\t\tcode: 'input',\n\t\t\t\t\tcontext: { command: result.command, code: result.code, signal: result.signal },\n\t\t\t\t\tcause: this.#inputFailure.signal.reason,\n\t\t\t\t\tresult,\n\t\t\t\t})\n\t\t\t}\n\t\t\tthrow createExecuteError(result, this.#cause)\n\t\t}\n\t\treturn result\n\t}\n}\n","import type { ExecuteOptions, ExecuteResult, ProcessCommand } from '@src/core'\nimport { Execution } from '../processes/Execution.js'\n\n/**\n * Runs one command to completion, buffering its output, and settles with the outcome.\n *\n * @remarks\n * The executable is resolved through {@link buildSpawn}, so no run uses a shell. On a POSIX host the\n * child is detached, which is what lets its whole process group be terminated. Standard output and\n * error are each byte-bounded by `limit` (default {@link PROCESS_OUTPUT}) and `truncated` reports\n * whether either stream exceeded it. Each capture keeps one byte beyond `limit`, so the single\n * code-point-boundary trim in {@link buildExecuteResult} reads the first excluded byte and never\n * delivers a split multibyte sequence. A positive `timeout` and an aborting `signal` both terminate the\n * child through the same bounded stop, and only the earliest is recorded: a timeout reports\n * `expired` and an abort reports `aborted`, never both. After termination the outcome is awaited for\n * a bounded window, so a descendant holding the child's stdio cannot keep the run pending. That bound\n * covers a terminated run alone: a run with no `timeout` and no `signal` settles on stdio completion\n * rather than on process exit, so a descendant that inherited the child's stdio holds the run open\n * after the child itself has gone. Give such a run a `timeout`. The child's `environment` merges over\n * the parent unless the command is `isolated`, then `options.environment` on top, and `options.input`\n * overrides `command.input`. A host fault while writing that input terminates the run by design and\n * marks its result failed; a strict rejection carries the host fault as its cause. This differs\n * from `Process` constructor input, whose package-initiated input phase stays quiet. Unless `strict`\n * is `false`, a failed run rejects with a {@link ProcessError} carrying the {@link ExecuteResult};\n * {@link createExecuteError} constructs every rejection outside the input-fault door. An invalid\n * option or command string rejects before the child is spawned, because an async function cannot\n * throw synchronously.\n *\n * @param command - The executable, arguments, and optional environment and input\n * @param options - Working directory, timeout, grace, signal, capture limit, and failure delivery\n * @returns The settled run outcome\n * @throws A {@link ProcessError} coded `invalid` for a malformed option, command string, or batch-bound argument, or one carrying the {@link ExecuteResult} when the run failed and `strict` is not `false`\n *\n * @example\n * ```ts\n * const result = await execute({ file: 'git', arguments: ['status'] }, { workspace: process.cwd() })\n * ```\n */\nexport async function execute(\n\tcommand: ProcessCommand,\n\toptions?: ExecuteOptions,\n): Promise<ExecuteResult> {\n\tconst execution = new Execution(command, options)\n\tconst result = await execution.settled\n\treturn execution.read(result)\n}\n","import type { ExecuteResult, ExecuteSyncOptions, ProcessCommand } from '@src/core'\nimport { Buffer } from 'node:buffer'\nimport { spawnSync } from 'node:child_process'\nimport { isString } from '@orkestrel/contract'\nimport { createExecuteError, PROCESS_OUTPUT } from '@src/core'\nimport { snapshotCommand } from '../cloners.js'\nimport {\n\tbuildExecuteResult,\n\tbuildSpawn,\n\tformatCommand,\n\tmergeEnvironment,\n\tvalidateBytes,\n\tvalidateCommand,\n\tvalidateEnvironment,\n\tvalidateTimer,\n\tvalidateWorkspace,\n} from '../helpers.js'\n\n/**\n * Runs one command to completion synchronously, buffering its output, and returns the outcome.\n *\n * @remarks\n * The synchronous counterpart of {@link execute}, spawned through the same resolver and never through a\n * shell. The host offers no cooperative termination window and no in-flight cancellation, so this\n * contract carries neither. A positive `timeout` ends only the root process and can leave\n * descendants running; use {@link execute} or {@link Process} when timeout must terminate the tree. A\n * timeout and an output overflow both end the root with `SIGKILL`: an overflow reports `truncated`\n * and `failed` together and trims the partial output to `limit`, where {@link execute} keeps reading and\n * reports `truncated` without failing. The environment and input follow the same merge as\n * {@link execute}. Unless `strict` is `false`, a failed run throws a {@link createExecuteError}\n * carrying the {@link ExecuteResult}.\n *\n * @param command - The executable, arguments, and optional environment and input\n * @param options - Working directory, timeout, capture limit, and failure delivery\n * @returns The run outcome\n * @throws A {@link ProcessError} coded `invalid` for a malformed option, command string, or batch-bound argument, or one carrying the {@link ExecuteResult} when the run failed and `strict` is not `false`\n *\n * @example\n * ```ts\n * const result = executeSync({ file: 'git', arguments: ['--version'] }, { strict: false })\n * ```\n */\nexport function executeSync(command: ProcessCommand, options?: ExecuteSyncOptions): ExecuteResult {\n\tconst snapshot = snapshotCommand(command)\n\tconst optionEnvironment = options?.environment\n\tconst optionWorkspace = options?.workspace\n\tconst optionInput = options?.input\n\tconst optionTimeout = options?.timeout\n\tconst optionStrict = options?.strict\n\tconst optionLimit = options?.limit\n\tvalidateCommand(snapshot)\n\tvalidateEnvironment(optionEnvironment)\n\tvalidateWorkspace(optionWorkspace)\n\tvalidateTimer(optionTimeout, \"option 'timeout'\")\n\tvalidateBytes(optionLimit, \"option 'limit'\", 0)\n\tconst limit = optionLimit ?? PROCESS_OUTPUT\n\tconst timeout = optionTimeout ?? 0\n\tconst strict = optionStrict ?? true\n\tconst text = optionInput ?? snapshot.input\n\tconst line = formatCommand(snapshot)\n\tconst workspace = optionWorkspace ?? process.cwd()\n\tconst environment = mergeEnvironment(\n\t\tsnapshot.isolated === true,\n\t\tsnapshot.environment,\n\t\toptionEnvironment,\n\t)\n\tconst plan = buildSpawn(snapshot, { workspace, environment })\n\tconst outcome = spawnSync(plan.file, [...plan.arguments], {\n\t\tcwd: workspace,\n\t\tenv: environment,\n\t\tencoding: 'buffer',\n\t\tmaxBuffer: limit,\n\t\tkillSignal: 'SIGKILL',\n\t\twindowsHide: true,\n\t\twindowsVerbatimArguments: plan.verbatim,\n\t\t...(text !== undefined ? { input: Buffer.from(text) } : {}),\n\t\t...(timeout > 0 ? { timeout } : {}),\n\t})\n\tconst error = outcome.error\n\tconst fault = error !== undefined && 'code' in error && isString(error.code) ? error.code : ''\n\tconst result = buildExecuteResult({\n\t\tcommand: line,\n\t\tstdout: Buffer.isBuffer(outcome.stdout) ? outcome.stdout : Buffer.alloc(0),\n\t\tstderr: Buffer.isBuffer(outcome.stderr) ? outcome.stderr : Buffer.alloc(0),\n\t\tcode: outcome.status,\n\t\tsignal: outcome.signal,\n\t\texpired: fault === 'ETIMEDOUT',\n\t\taborted: false,\n\t\ttruncated: fault === 'ENOBUFS',\n\t\tlimit,\n\t\t...(error === undefined ? {} : { cause: error }),\n\t})\n\tif (result.failed && strict) throw createExecuteError(result, error)\n\treturn result\n}\n"],"mappings":"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"}
|