mcproc 0.0.0-stage → 0.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +125 -2
- package/dist/cli.js +13579 -0
- package/dist/cli.js.map +1 -0
- package/docs/hosts.md +84 -0
- package/docs/incidents.md +39 -0
- package/docs/init.md +30 -0
- package/docs/logs.md +50 -0
- package/docs/manifest.md +83 -0
- package/docs/memory.md +57 -0
- package/docs/monit.md +40 -0
- package/docs/readiness.md +53 -0
- package/docs/reloads.md +67 -0
- package/docs/urls.md +56 -0
- package/docs/variables.md +34 -0
- package/docs/worktrees.md +47 -0
- package/package.json +76 -4
- package/runtime/package-lock.json +945 -0
- package/runtime/package.json +8 -0
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/program.ts","../src/version.ts","../src/core/errors.ts","../src/transport/quote.ts","../src/transport/spawn.ts","../src/transport/index.ts","../src/runtime/unpack.ts","../src/core/pm2.ts","../src/core/resolve.ts","../src/core/manifest.ts","../src/core/incidents/detect.ts","../src/core/names.ts","../src/core/override.ts","../src/core/sizes.ts","../src/core/template.ts","../src/core/urlcheck.ts","../src/shell/snippets.ts","../src/runtime/bundle.ts","../src/runtime/platform.ts","../src/runtime/decide.ts","../src/runtime/files.ts","../src/runtime/node-dist.ts","../src/runtime/probe.ts","../src/core/leases/view.ts","../src/core/memory.ts","../src/core/state.ts","../src/core/leases/ensure.ts","../src/core/ecosystem.ts","../src/core/leases/store.ts","../src/core/leases/watcher.ts","../src/core/actions.ts","../src/core/list.ts","../src/core/metrics.ts","../src/core/logs.ts","../src/core/incidents/cursor.ts","../src/core/logsince.ts","../src/core/stats.ts","../src/core/ports.ts","../src/core/logfollow.ts","../src/core/logwatch.ts","../src/core/hoststream.ts","../src/core/logchunk.ts","../src/core/reloads.ts","../src/core/logstream.ts","../src/mcp/render.ts","../src/core/wait.ts","../src/core/leases/admission.ts","../src/core/leases/siblings.ts","../src/core/slots.ts","../src/core/leases/gate.ts","../src/core/fleet.ts","../src/core/exec.ts","../src/core/worktree.ts","../src/core/incidents/store.ts","../src/core/incidents/taken.ts","../src/core/incidents/poll.ts","../src/core/doctor.ts","../src/core/init.ts","../src/core/turbo.ts","../src/core/adopt.ts","../src/core/reloadcount.ts","../src/mcp/server.ts","../src/mcp/tools/read.ts","../src/mcp/common.ts","../src/mcp/tools/write.ts","../src/mcp/tools/stands.ts","../src/monit/state.ts","../src/monit/screentext.ts","../src/monit/frame.ts","../src/monit/once.ts","../src/cli/install.ts","../src/monit/tui.ts","../src/monit/loop.ts","../src/monit/coalesce.ts","../src/monit/dispatch.ts","../src/cli.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { Command, Option } from 'commander';\nimport { VERSION } from '../version.js';\nimport { McprocError, isMcprocError } from '../core/errors.js';\nimport { createTransport } from '../transport/index.js';\nimport { unpack, defaultUnpackDeps } from '../runtime/unpack.js';\nimport type { WithNode } from '../runtime/decide.js';\nimport {\n prepare,\n connect,\n assertWritable,\n resolveProjectDir,\n type Context,\n} from '../core/resolve.js';\nimport { cancelLease, leasesView } from '../core/leases/view.js';\nimport { watcherEntry } from '../core/leases/ensure.js';\nimport {\n defaultWatcherDeps,\n leaseDirWatch,\n watchLeases,\n} from '../core/leases/watcher.js';\nimport { stateDir } from '../core/state.js';\nimport { assertExecHost, defaultExecDeps, runExec } from '../core/exec.js';\nimport {\n defaultWorktreeDeps,\n worktreeAdd,\n worktreeLs,\n worktreeRemove,\n} from '../core/worktree.js';\nimport { parseSizeMib } from '../core/sizes.js';\nimport type { WaitRecord } from '../core/actions.js';\nimport { portsReport, hostsInfo, describeProject } from '../core/list.js';\nimport { takeIncidents, clearLogs } from '../core/incidents/store.js';\nimport type { CursorState } from '../core/incidents/cursor.js';\nimport {\n streamLogs,\n defaultStreamDeps,\n resolveColor,\n formatLine,\n colorFor,\n type LogSource,\n type StreamOptions,\n} from '../core/logstream.js';\nimport {\n parseSince,\n readSince,\n LogMarks,\n type SinceSpec,\n} from '../core/logsince.js';\nimport { doctor } from '../core/doctor.js';\nimport { parseUntil, waitFor, WAIT_TIMEOUT_DEFAULT_MS } from '../core/wait.js';\nimport { initProject } from '../core/init.js';\nimport { adoptPorts } from '../core/adopt.js';\nimport { Fleet, actOn, describeFleetApp, type Act } from '../core/fleet.js';\nimport { listWithReloads } from '../core/reloadcount.js';\nimport {\n renderLs,\n renderPorts,\n renderHosts,\n renderDoctor,\n renderProject,\n renderUnpack,\n renderIncidents,\n renderFlushed,\n renderMutation,\n renderWait,\n renderAdopted,\n renderLeases,\n renderWorktreeAdded,\n renderWorktreeRemoved,\n renderWorktrees,\n hostsOf,\n sinceNotes,\n urlNote,\n} from '../mcp/render.js';\nimport { serveStdio } from '../mcp/server.js';\nimport { monitOnce } from '../monit/once.js';\nimport { installShortcut } from './install.js';\nimport { runMonit } from '../monit/tui.js';\n\nexport interface Io {\n out: (s: string) => void;\n err: (s: string) => void;\n}\ntype Globals = { project?: string; host?: string; json?: boolean };\ntype Opts = Record<string, string | boolean | undefined>;\n\nconst defaultIo: Io = {\n out: (s) => process.stdout.write(`${s}\\n`),\n err: (s) => process.stderr.write(`${s}\\n`),\n};\n\n/**\n * The one-shot read of `logs --since`: the merged lines since the cutoff on stdout, labeled and colored as the follow\n * labels them (the longest name, each app's index in host-group order), the notes on stderr, exit code 1 when a host\n * was not read. Returns where each app's follow starts, or null when the reader of stdout went away.\n */\nexport async function printSince(\n fleet: Fleet,\n apps: string[],\n since: SinceSpec,\n how: { stream: 'out' | 'err' | 'both'; color: boolean; json: boolean },\n io: Io,\n signal?: AbortSignal\n): Promise<StreamOptions['startAt'] | null> {\n const marks = new LogMarks();\n const a = await readSince(fleet, apps, {\n since,\n stream: how.stream,\n marks,\n keepColors: how.color && !how.json,\n });\n const order = fleet.groups(apps).flatMap((gr) => gr.apps);\n const width = Math.max(...apps.map((x) => x.length));\n let closed = false; // `| head` read enough: stop printing, no stack trace\n for (const l of a.lines) {\n if (closed || signal?.aborted) break;\n try {\n io.out(\n how.json\n ? JSON.stringify(l)\n : formatLine(\n { app: l.app, stream: l.stream, text: l.text },\n width,\n how.color ? colorFor(order.indexOf(l.app)) : null\n )\n );\n } catch (e) {\n if ((e as { code?: string }).code !== 'EPIPE') throw e;\n closed = true;\n }\n }\n for (const n of sinceNotes(a)) io.err(n);\n if (a.errors.length) process.exitCode = 1; // a host was not read: the lines of the others are printed, the exit code says so\n if (closed || signal?.aborted) return null;\n // a stream the read left without a mark (its app not started yet, or its read cut short) starts at its host's cutoff,\n // so what the app writes before its follower's first poll is still printed; an app on a host that was not read has\n // no cutoff and is followed from the file's end\n return Object.fromEntries(\n apps.map((x) => {\n const host = fleet.hostOf(x);\n const cutoff = a.since[host];\n return [\n x,\n {\n ...marks.get(LogMarks.key(fleet.manifest.path, host, x)),\n ...(typeof cutoff === 'string' ? { cutoff } : {}),\n },\n ];\n })\n );\n}\n\n/**\n * `ls`: the rows of the named apps, each from its own host, as a table or JSON; with reloads, each running app's\n * in-process reloads since its pm2 start, which reads the logs of each host once more. Exit code 1 when a host was not\n * probed or its logs were not read.\n */\nexport async function printLs(\n fleet: Fleet,\n names: string[],\n how: { reloads: boolean; json: boolean },\n io: Io\n): Promise<void> {\n const { rows, errors, unread } = await listWithReloads(\n fleet,\n names,\n how.reloads\n );\n io.out(\n how.json\n ? JSON.stringify(rows, null, 2)\n : renderLs(rows, fleet.fallback, unread)\n );\n if (errors.length) process.exitCode = 1; // the rows of the hosts that answered are printed; the exit code still says one did not\n}\n\nexport function buildProgram(io: Io = defaultIo): Command {\n const program = new Command()\n .name('mcproc')\n .description(\n 'pm2 process control for agents: one manifest per project, local and remote hosts, per-app ports'\n )\n .version(VERSION)\n .option(\n '--project <dir>',\n 'project root (default: MCPROC_PROJECT, CLAUDE_PROJECT_DIR, cwd)'\n )\n .option('--host <name>', 'host from the manifest (default: local)')\n .option('--json', 'print JSON instead of text');\n\n const emit = (g: Globals, text: string, data: unknown) =>\n io.out(g.json ? JSON.stringify(data, null, 2) : text);\n const wrap =\n (fn: (g: Globals, opts: Opts, args: string[]) => Promise<void>) =>\n async (...all: unknown[]) => {\n const cmd = all[all.length - 1] as Command;\n const opts = (all[all.length - 2] ?? {}) as Opts;\n const args = all.slice(0, -2) as string[];\n const g = cmd.optsWithGlobals() as Globals;\n try {\n await fn(g, opts, args);\n } catch (e) {\n if (!isMcprocError(e)) throw e;\n io.err(\n g.json\n ? JSON.stringify(e.toJSON())\n : `${e.code}: ${e.message}${e.hint ? `\\nHint: ${e.hint}` : ''}`\n );\n process.exitCode = 1;\n }\n };\n const ctxOf = (g: Globals) =>\n connect(prepare({ project: g.project, host: g.host }));\n // apps run at their own host (`host:` in the manifest); --host narrows a command to the apps that run there\n const fleetOf = (g: Globals) =>\n new Fleet(prepare({ project: g.project }).manifest, g.host);\n const mutate = async (\n g: Globals,\n target: string,\n act: Act,\n opts: { reload?: boolean; note?: string; lease?: string } = {}\n ) => {\n const fleet = fleetOf(g);\n const waits: WaitRecord[] = [];\n const rows = await actOn(fleet, target, act, { ...opts, waits });\n const { text, failed } = renderMutation(rows, fleet.fallback, act, waits);\n emit(g, text, { ...hostsOf(rows, fleet.fallback), rows, waits });\n if (failed) process.exitCode = 1; // a host failed or was skipped: the first line says so, the exit code too\n };\n\n program\n .command('init')\n .description(\n 'create .mcproc/ with a manifest draft discovered from the project'\n )\n .option('--force', 'overwrite an existing manifest')\n .option(\n '--adopt-ports',\n 'write the ports ls reports as undeclared for the running apps into the existing manifest (comments kept) and print the diff; needs that manifest, drafts nothing and ignores --force'\n )\n .action(\n wrap(async (g, o) => {\n if (o.adoptPorts) {\n const r = await adoptPorts(fleetOf(g));\n const { text, failed } = renderAdopted(r);\n emit(g, text, r);\n if (failed) process.exitCode = 1; // a host was not read: the line names it, the exit code says so\n return;\n }\n const r = initProject(resolveProjectDir(g.project), {\n force: Boolean(o.force),\n });\n emit(g, `Created ${r.path} (${r.candidates} candidates)\\n${r.next}`, r);\n })\n );\n program\n .command('hosts')\n .description('hosts declared in the manifest')\n .action(\n wrap(async (g) => {\n const { manifest } = prepare({ project: g.project });\n const h = hostsInfo(manifest);\n emit(g, renderHosts(h), h);\n })\n );\n program\n .command('doctor')\n .description(\n 'check hosts: reachability, node, pm2, tools, daemon, environment, where each url answers'\n )\n .action(\n wrap(async (g) => {\n const { manifest } = prepare({ project: g.project });\n const r = await doctor(manifest, g.host);\n emit(g, renderDoctor(r), r);\n })\n );\n program\n .command('ls [app]')\n .description(\n 'apps with status, pid and real vs declared ports, each from the host it runs on'\n )\n .option(\n '--reloads',\n \"also count each running app's in-process reloads since its pm2 start, shown as RESTARTS 0 (+3); reads each host's logs once more\"\n )\n .action(\n wrap(async (g, o, [app]) => {\n const fleet = fleetOf(g);\n await printLs(\n fleet,\n fleet.select(app ? [app] : ['all']),\n { reloads: Boolean(o.reloads), json: Boolean(g.json) },\n io\n );\n })\n );\n program\n .command('describe [app]')\n .description('project summary, or one app in detail')\n .action(\n wrap(async (g, _o, [app]) => {\n const fleet = fleetOf(g);\n if (!app) {\n const d = describeProject(fleet.manifest);\n emit(g, renderProject(d), d);\n return;\n }\n const d = await describeFleetApp(fleet, app);\n emit(\n g,\n [\n `${d.app.name} [${d.app.kind}]: ${d.app.description}`,\n `run: ${d.app.run}`,\n `cwd: ${d.app.cwd}`,\n renderLs([d.row], d.host),\n urlNote(d.row),\n `logs: ${d.logs ? `${d.logs.out} | ${d.logs.err}` : 'not started yet'}`,\n ]\n .filter(Boolean)\n .join('\\n'),\n d\n );\n })\n );\n program\n .command('logs [targets...]')\n .description(\n 'logs of apps or profiles (default: all apps), one labeled line per entry like docker compose; -f keeps streaming'\n )\n .option('-f, --follow', 'keep streaming until Ctrl-C')\n .option('-n, --lines <n>', 'history lines per app (default 100, max 2000)')\n .option('--out', 'stdout only')\n .option('--err', 'stderr only')\n .option('--interval <ms>', 'poll interval while following', '1000')\n .option(\n '--color',\n \"colors (labels and the apps' own) even when stdout is not a terminal; also FORCE_COLOR\"\n )\n .option(\n '--no-color',\n 'plain text (also when NO_COLOR is set or stdout is not a terminal)'\n )\n .option(\n '--since <time>',\n 'lines since a span (2m, 90s) or a host-local time (2026-10-14T07:30; add Z or +02:00 for an instant), merged across the targets; prints and exits, with -f then follows'\n )\n .action(\n wrap(async (g, o, args) => {\n const targets = (args[0] as unknown as string[] | undefined) ?? [];\n const fleet = fleetOf(g);\n const apps = fleet.select(targets.length ? targets : ['all']);\n const color = resolveColor(\n o.color as boolean | undefined,\n process.env,\n Boolean(process.stdout.isTTY)\n );\n const stream = o.out ? 'out' : o.err ? 'err' : 'both';\n let since: SinceSpec | undefined;\n if (o.since !== undefined) {\n if (o.lines !== undefined)\n throw new McprocError(\n 'BAD_ARGUMENT',\n '-n and --since do not combine: --since decides what is printed first',\n {\n hint: 'Drop -n; with -f the follow continues from where the since read ended.',\n }\n );\n since = parseSince(String(o.since));\n if (since.kind === 'last')\n throw new McprocError(\n 'BAD_ARGUMENT',\n 'since last needs an MCP session, which keeps the marks',\n {\n hint: 'Use a time such as --since 2m, or --since 2026-10-14T07:30.',\n }\n );\n }\n const ac = new AbortController();\n // a reader that closes early (`| head`) raises EPIPE asynchronously on stdout, possibly after the stream already returned:\n // the listener stays for the rest of the process, ends the stream and swallows the error instead of a crash\n process.stdout.on('error', (e: NodeJS.ErrnoException) => {\n if (e.code === 'EPIPE') ac.abort();\n else throw e;\n });\n let startAt: StreamOptions['startAt'];\n if (since) {\n const at = await printSince(\n fleet,\n apps,\n since,\n { stream, color, json: Boolean(g.json) },\n io,\n ac.signal\n );\n if (!o.follow || at === null) return;\n startAt = at;\n }\n // every host at once; one that cannot be reached becomes a note per app instead of ending the stream, and is\n // connected again later while following (fleet.ctx keeps no failed connection)\n const sources = await Promise.all(\n fleet.groups(apps).map(async (gr): Promise<LogSource> => {\n const connect = () => fleet.ctx(gr.host);\n try {\n return { ...gr, connect, ctx: await connect() };\n } catch (e) {\n return { ...gr, connect, error: e };\n }\n })\n );\n if (ac.signal.aborted) return; // the reader of the since lines went away meanwhile: nothing to follow for\n const stop = () => ac.abort();\n process.once('SIGINT', stop);\n try {\n await streamLogs(\n sources,\n {\n lines: since\n ? 0\n : Math.min(Math.max(1, Number(o.lines) || 100), 2000),\n follow: Boolean(o.follow),\n intervalMs: Math.max(200, Number(o.interval) || 1000),\n color,\n json: Boolean(g.json),\n stream,\n signal: ac.signal,\n startAt,\n },\n defaultStreamDeps()\n );\n } finally {\n process.off('SIGINT', stop);\n }\n })\n );\n program\n .command('incidents [targets...]')\n .description(\n 'new errors with context since they were last taken, plus crashes and restarts; -f keeps watching'\n )\n .option('--peek', 'look without taking: the pick-up point stays')\n .option(\n '--since <min>',\n 'first poll: minutes to look back in each log',\n '15'\n )\n .option('--max <n>', 'most incidents per poll, newest first', '20')\n .option(\n '--context <before,after>',\n 'lines of context (default per app, 3,5)'\n )\n .option(\n '--reloads',\n \"also each app's in-process reloads since the last poll (tsx/nodemon restarts, Vite/Next rebuilds, a repeated listening line), one line per app\"\n )\n .option('-f, --follow', 'keep polling and print each new incident')\n .option('--interval <s>', 'seconds between polls while following', '10')\n .option('--color', 'colors even when stdout is not a terminal')\n .option('--no-color', 'plain text')\n .action(\n wrap(async (g, o, args) => {\n const targets = (args[0] as unknown as string[] | undefined) ?? [];\n let context: [number, number] | undefined;\n if (o.context !== undefined) {\n const m = /^(\\d{1,2}),(\\d{1,2})$/.exec(String(o.context));\n if (!m)\n throw new McprocError(\n 'BAD_ARGUMENT',\n `--context must be before,after (e.g. 3,5), got \"${o.context}\"`\n );\n context = [Number(m[1]), Number(m[2])];\n }\n const fleet = fleetOf(g);\n const names = fleet.select(targets.length ? targets : ['all']);\n const color = resolveColor(\n o.color as boolean | undefined,\n process.env,\n Boolean(process.stdout.isTTY)\n );\n const peek = Boolean(o.peek);\n let cursor: CursorState | undefined; // a peeking follower's own position; taking always goes on from the stored point\n const poll = async () => {\n const r = await takeIncidents(fleet, names, {\n peek,\n cursor,\n sinceMin: Number(o.since) || 15,\n max: Number(o.max) || 20,\n context,\n includeReloads: Boolean(o.reloads),\n });\n if (peek) cursor = r.next;\n return r.answer;\n };\n const first = await poll();\n emit(g, renderIncidents(first, { color }), first);\n if (!o.follow) return;\n const ac = new AbortController();\n const stop = () => ac.abort();\n process.once('SIGINT', stop);\n try {\n while (!ac.signal.aborted) {\n await new Promise((r) =>\n setTimeout(r, Math.max(1, Number(o.interval) || 10) * 1000)\n );\n if (ac.signal.aborted) break;\n const a = await poll();\n if (a.incidents.length || a.errors.length)\n emit(g, renderIncidents(a, { color }), a);\n }\n } finally {\n process.off('SIGINT', stop);\n }\n })\n );\n program\n .command('wait <app>')\n .description(\n 'block until the app is listening, answers its url, exited, printed a matching line, went idle or reloaded; exit 1 when it was not reached'\n )\n .requiredOption(\n '--until <cond>',\n 'listening | url-ok | exited | log:<regex> | idle:<seconds> | reloaded (the next in-process reload after the call: a tsx/nodemon restart, a Vite/Next rebuild, a repeated listening line; answered once its burst is quiet for 2 s; for a server whose reload restarts it, wait --until listening next)'\n )\n .option(\n '-t, --timeout <s>',\n 'seconds to wait (max 600)',\n String(WAIT_TIMEOUT_DEFAULT_MS / 1000)\n )\n .action(\n wrap(async (g, o, [app]) => {\n const until = parseUntil(String(o.until)); // a bad request is refused before any host is touched\n const timeoutMs =\n Math.max(1, Number(o.timeout) || WAIT_TIMEOUT_DEFAULT_MS / 1000) *\n 1000; // waitFor holds the 600 s cap\n const fleet = fleetOf(g);\n const ctx = await fleet.ctx(fleet.one(app));\n const ac = new AbortController();\n const stop = () => ac.abort();\n process.once('SIGINT', stop);\n try {\n const r = await waitFor(ctx, app, until, {\n timeoutMs,\n signal: ac.signal,\n });\n emit(g, renderWait(app, r), { app, host: ctx.host.name, ...r });\n if (!r.ok) process.exitCode = 1; // not reached (timeout, process gone, Ctrl-C): scripts see it\n } finally {\n process.off('SIGINT', stop);\n }\n })\n );\n program\n .command('ports [port]')\n .description('who listens on which port on the host')\n .action(\n wrap(async (g, _o, [port]) => {\n const ctx = await ctxOf(g);\n const r = await portsReport(ctx, port ? Number(port) : undefined);\n emit(g, renderPorts(r, ctx.host.name), r);\n })\n );\n program\n .command('start <target>')\n .description('start an app or profile (dependencies first)')\n .option('--reload', 'restart apps that are already online')\n .option('--note <text>', 'what this start is for, kept on its lease')\n // internal: the watcher's child runs the start it admitted under this lease\n .addOption(new Option('--lease <id>').hideHelp())\n .action(\n wrap((g, o, [t]) =>\n mutate(g, t, 'start', {\n reload: Boolean(o.reload),\n note: o.note as string | undefined,\n lease: o.lease as string | undefined,\n })\n )\n );\n program\n .command('restart <target>')\n .description('restart app(s) with the current manifest config')\n .action(wrap((g, _o, [t]) => mutate(g, t, 'restart')));\n program\n .command('stop <target>')\n .description('stop app(s)')\n .action(wrap((g, _o, [t]) => mutate(g, t, 'stop')));\n program\n .command('delete <target>')\n .description('remove app(s) from pm2')\n .action(wrap((g, _o, [t]) => mutate(g, t, 'delete')));\n const leases = program\n .command('leases')\n .description(\n \"the host's lease queue: who is running, who waits and why, the memory reading and the watcher\"\n )\n .action(\n wrap(async (g) => {\n let ctx: Context | undefined;\n try {\n ctx = await ctxOf(g);\n } catch {\n ctx = undefined; // no manifest here: the queue is the host's and still reads\n }\n const v = await leasesView(undefined, ctx);\n emit(g, renderLeases(v), v);\n })\n );\n leases\n .command('cancel <id>')\n .description('cancel a pending lease')\n .action(\n wrap(async (g, _o, [id]) => {\n const l = await cancelLease(id);\n emit(g, `cancelled ${l.id} (${l.project} ${l.target})`, l);\n })\n );\n program\n .command('exec <command...>')\n .description(\n \"run a one-off command from the project root with the manifest's exec.env; with --memory, under a lease in the host's queue (use -- before the command)\"\n )\n // no passThroughOptions: it needs positional options on the program, which would refuse the global options written\n // after a command (`ls --json`); `--` already ends exec's options and hands the rest over verbatim\n .option(\n '--memory <size>',\n 'what the command needs, e.g. 4G: it waits its turn like a start'\n )\n .option('--note <text>', 'what this run is for, kept on its lease')\n .option(\n '--timeout <s>',\n 'seconds to wait in the queue (default 600, max 3600)'\n )\n .action(\n wrap(async (g, o, args) => {\n // the variadic <command...> arrives as one array argument\n const command = args.flat();\n // a bad request is refused before any host is touched\n let memoryMib: number | undefined;\n if (o.memory !== undefined)\n try {\n memoryMib = parseSizeMib(String(o.memory));\n } catch (e) {\n throw new McprocError('BAD_ARGUMENT', (e as Error).message);\n }\n const timeoutS =\n o.timeout === undefined ? undefined : Number(o.timeout);\n if (timeoutS !== undefined && !(timeoutS > 0))\n throw new McprocError(\n 'BAD_ARGUMENT',\n `--timeout is a number of seconds above 0, not \"${o.timeout}\"`\n );\n const prep = prepare({ project: g.project, host: g.host });\n assertExecHost(prep.host);\n const ctx = await connect(prep);\n const ac = new AbortController();\n const stop = () => ac.abort();\n // on, not once: a second Ctrl-C must not fall to Node's default exit, which skips the lease's cleanup; a closed\n // terminal (SIGHUP) ends the command and frees its lease the same way\n const signals = ['SIGINT', 'SIGTERM', 'SIGHUP'] as const;\n for (const s of signals) process.on(s, stop);\n try {\n const r = await runExec(\n ctx,\n {\n command,\n memoryMib,\n note: o.note === undefined ? undefined : String(o.note),\n timeoutMs: timeoutS === undefined ? undefined : timeoutS * 1000,\n capture: false,\n signal: ac.signal,\n },\n defaultExecDeps()\n );\n if (g.json)\n io.out(\n JSON.stringify(\n { code: r.code, lease: r.lease, waited_ms: r.waited_ms },\n null,\n 2\n )\n );\n process.exitCode = r.code;\n } finally {\n for (const s of signals) process.off(s, stop);\n }\n })\n );\n // git runs here: the worktree commands act on the local checkout; their notes go to stderr, the answer to stdout\n const worktreeCtx = async (g: Globals) => {\n const prep = prepare({ project: g.project, host: g.host });\n if (!prep.host.local)\n throw new McprocError(\n 'BAD_ARGUMENT',\n `worktree runs on the local host only, not on ${prep.host.name}`,\n { hint: 'Drop --host; the checkout is on this machine.' }\n );\n const ctx = await connect(prep);\n return {\n manifest: ctx.manifest,\n deps: await defaultWorktreeDeps(ctx, { out: io.err }),\n };\n };\n const worktree = program\n .command('worktree')\n .description(\n 'worktrees of this repository, each with its own slot, project slug and ports'\n );\n worktree\n .command('add <branch>')\n .description(\n \"a worktree in the sibling folder on that branch: copies and links from its manifest and the main checkout's override, the override with its slot, the install\"\n )\n .option(\n '--from <ref>',\n \"where a new branch starts (default: the main checkout's HEAD)\"\n )\n .option('--slot <n>', 'a specific slot (default: the lowest free one)')\n .option(\n '--slug <slug>',\n 'the project slug this checkout runs under (default: <project>-w<slot>)'\n )\n .option('--no-install', 'skip the install command')\n .action(\n wrap(async (g, o, [branch]) => {\n const { manifest, deps } = await worktreeCtx(g);\n const r = await worktreeAdd(\n manifest,\n {\n branch,\n from: o.from === undefined ? undefined : String(o.from),\n slot: o.slot === undefined ? undefined : Number(o.slot),\n project: o.slug === undefined ? undefined : String(o.slug),\n install: o.install !== false,\n },\n deps\n );\n emit(g, renderWorktreeAdded(r), r);\n })\n );\n worktree\n .command('ls')\n .description(\n 'every checkout: slot, project, branch, apps online, lease, path'\n )\n .action(\n wrap(async (g) => {\n const { manifest, deps } = await worktreeCtx(g);\n const rows = await worktreeLs(manifest, deps);\n emit(g, renderWorktrees(rows), rows);\n })\n );\n worktree\n .command('remove <ref>')\n .description(\n 'stop its apps, remove the worktree (by branch, path or slot) and free its slot; the branch stays'\n )\n .option('--force', 'remove even with uncommitted or untracked changes')\n .action(\n wrap(async (g, o, [ref]) => {\n const { manifest, deps } = await worktreeCtx(g);\n const r = await worktreeRemove(\n manifest,\n ref,\n { force: Boolean(o.force) },\n deps\n );\n emit(g, renderWorktreeRemoved(r), r);\n })\n );\n program\n .command('watch-leases', { hidden: true })\n .description('internal: the lease watcher the start launches under pm2')\n .action(\n wrap(async () => {\n const dir = stateDir();\n const deps = defaultWatcherDeps(dir, watcherEntry());\n const ac = new AbortController();\n const stop = () => ac.abort();\n process.once('SIGINT', stop);\n process.once('SIGTERM', stop);\n fs.mkdirSync(deps.store.dir, { recursive: true });\n deps.watch = leaseDirWatch(deps.store.dir);\n const r = await watchLeases(deps, { signal: ac.signal });\n io.out(`watcher ${r}`);\n })\n );\n program\n .command('flush [app]')\n .description('truncate pm2 log files; incidents start over from there')\n .action(\n wrap(async (g, _o, [app]) => {\n const fleet = fleetOf(g);\n const names = fleet.select(app ? [app] : ['all']);\n const multi = fleet.groups(names).length > 1;\n const r = await clearLogs(fleet, names);\n emit(g, renderFlushed(r, multi), r);\n })\n );\n program\n .command('monit')\n .description(\n 'terminal dashboard: apps with real memory/cpu/ports, log tail, details (--once prints one frame)'\n )\n .option('--once', 'print one frame as text and exit')\n .option('--interval <ms>', 'refresh interval', '2000')\n .option('--lines <n>', 'log lines of history', '200')\n .action(\n wrap(async (g, o) => {\n if (o.once) {\n io.out(\n await monitOnce({\n project: g.project,\n host: g.host,\n lines: Number(o.lines) || 200,\n })\n );\n return;\n }\n await runMonit({\n project: g.project,\n host: g.host,\n intervalMs: Math.max(500, Number(o.interval) || 2000),\n lines: Number(o.lines) || 200,\n });\n })\n );\n program\n .command('unpack')\n .description(\n 'bring pm2 (assembled with npm from the lockfile mcproc ships) and Node when missing to the host, into <cwd>/.mcproc/runtime or --dir'\n )\n .option('--dir <path>', 'absolute runtime directory on the host')\n .option('--with-node <mode>', 'auto | always | never', 'auto')\n .option(\n '--node-version <version>',\n 'exact Node version (default: newest LTS)'\n )\n .option(\n '--force',\n 'rewrite even when versions match; overwrite a hand-written manifest on the host'\n )\n .action(\n wrap(async (g, o) => {\n const p = prepare({ project: g.project, host: g.host });\n assertWritable(p.host);\n const mode = String(o.withNode ?? 'auto');\n if (!['auto', 'always', 'never'].includes(mode))\n throw new McprocError(\n 'BAD_ARGUMENT',\n `--with-node must be auto, always or never, got \"${mode}\"`\n );\n const r = await unpack(\n {\n manifest: p.manifest,\n host: p.host,\n transport: createTransport(p.host),\n },\n {\n dir: o.dir as string | undefined,\n withNode: mode as WithNode,\n nodeVersion: o.nodeVersion as string | undefined,\n force: Boolean(o.force),\n },\n defaultUnpackDeps()\n );\n emit(g, renderUnpack(r), r);\n })\n );\n program\n .command('install')\n .description(\n 'put a `mcproc` shortcut on your shell PATH for this checkout (a launcher in ~/.local/bin), or remove it'\n )\n .option('--bin-dir <dir>', 'where the launcher goes (default ~/.local/bin)')\n .option('--uninstall', 'remove the launcher written by a previous install')\n .action(\n wrap(async (g, o) => {\n const r = installShortcut({\n binDir: o.binDir as string | undefined,\n uninstall: Boolean(o.uninstall),\n });\n const lines = r.removed\n ? [`removed ${r.launcher}`]\n : r.written\n ? [\n `wrote ${r.launcher} → node ${r.cli}`,\n r.rcUpdated\n ? `added a PATH line for ${r.binDir} to ${r.rcFile}`\n : r.onPath\n ? `${r.binDir} is already on PATH`\n : `${r.rcFile} already has the PATH line`,\n ]\n : [];\n emit(g, [...lines, ...r.next.map((n) => `→ ${n}`)].join('\\n'), r);\n })\n );\n program\n .command('mcp')\n .description(\n 'run the MCP server on stdio (register this command in your agent client)'\n )\n .action(\n wrap(async (g) => {\n await serveStdio(g.project);\n })\n );\n return program;\n}\n","import { createRequire } from 'node:module';\n\nconst pkg = createRequire(import.meta.url)('../package.json') as {\n version: string;\n};\nexport const VERSION: string = pkg.version;\n\nconst NUM = '0|[1-9]\\\\d*';\nconst PRE = `(?:${NUM}|\\\\d*[A-Za-z-][0-9A-Za-z-]*)`;\n/** A semver version: x.y.z without leading zeros, optionally a pre-release (`-rc.1`) and build metadata (`+abc`). */\nexport const VERSION_PATTERN = new RegExp(\n `^(${NUM})\\\\.(${NUM})\\\\.(${NUM})(?:-(${PRE}(?:\\\\.${PRE})*))?(?:\\\\+[0-9A-Za-z-]+(?:\\\\.[0-9A-Za-z-]+)*)?$`\n);\n\n/** Two digit strings without leading zeros, compared exactly at any length. */\nconst byDigits = (a: string, b: string): number =>\n a.length !== b.length ? a.length - b.length : a < b ? -1 : a > b ? 1 : 0;\n\n/** Orders two versions like semver: x.y.z numerically, a pre-release before its release, build metadata ignored. */\nexport function compareVersions(a: string, b: string): number {\n const pa = VERSION_PATTERN.exec(a);\n const pb = VERSION_PATTERN.exec(b);\n if (!pa || !pb) return a.localeCompare(b);\n for (let i = 1; i <= 3; i++) {\n const d = byDigits(pa[i], pb[i]);\n if (d !== 0) return d;\n }\n const [ra, rb] = [pa[4], pb[4]];\n if (ra === rb) return 0;\n if (ra === undefined) return 1;\n if (rb === undefined) return -1;\n const xa = ra.split('.');\n const xb = rb.split('.');\n for (let i = 0; i < Math.max(xa.length, xb.length); i++) {\n if (xa[i] === undefined) return -1;\n if (xb[i] === undefined) return 1;\n if (xa[i] === xb[i]) continue;\n const na = /^\\d+$/.test(xa[i]);\n const nb = /^\\d+$/.test(xb[i]);\n if (na && nb) return byDigits(xa[i], xb[i]);\n if (na !== nb) return na ? -1 : 1;\n return xa[i] < xb[i] ? -1 : 1;\n }\n return 0;\n}\n","export const ERROR_CODES = [\n 'MANIFEST_NOT_FOUND',\n 'MANIFEST_INVALID',\n 'UNKNOWN_APP',\n 'UNKNOWN_HOST',\n 'READONLY_HOST',\n 'PM2_NOT_FOUND',\n 'NODE_NOT_FOUND',\n 'TAR_NOT_FOUND',\n 'PM2_HOME_TOO_LONG',\n 'DOWNLOAD_FAILED',\n 'TRANSPORT_FAILED',\n 'TIMEOUT',\n 'PM2_FAILED',\n 'NOT_STARTED',\n 'ALREADY_EXISTS',\n 'NAME_COLLISION',\n 'BAD_ARGUMENT',\n 'BUNDLE_INVALID',\n 'WRONG_HOST',\n 'UNKNOWN_VAR',\n 'BAD_TEMPLATE',\n 'VAR_CYCLE',\n 'NEVER_FITS',\n 'LEASE_UNSUPPORTED_HOST',\n 'LEASE_NOT_PENDING',\n 'NO_FREE_SLOT',\n 'SLOT_TAKEN',\n 'WORKTREE_EXISTS',\n 'WORKTREE_DIRTY',\n 'NOT_A_WORKTREE',\n] as const;\nexport type ErrorCode = (typeof ERROR_CODES)[number];\n\nexport class McprocError extends Error {\n readonly code: ErrorCode;\n readonly hint?: string;\n readonly details?: unknown;\n constructor(\n code: ErrorCode,\n message: string,\n opts: { hint?: string; details?: unknown } = {}\n ) {\n super(message);\n this.name = 'McprocError';\n this.code = code;\n this.hint = opts.hint;\n this.details = opts.details;\n }\n toJSON(): {\n code: ErrorCode;\n message: string;\n hint?: string;\n details?: unknown;\n } {\n return {\n code: this.code,\n message: this.message,\n hint: this.hint,\n details: this.details,\n };\n }\n}\n\nexport function isMcprocError(e: unknown): e is McprocError {\n return (\n e instanceof McprocError ||\n (typeof e === 'object' &&\n e !== null &&\n (e as { name?: string }).name === 'McprocError')\n );\n}\n\n/** describeError plus the error's hint: for a note that stands in for an error the caller goes on past. */\nexport const describeErrorWithHint = (e: unknown): string =>\n isMcprocError(e) && e.hint\n ? `${describeError(e)}; ${e.hint}`\n : describeError(e);\n\n/** `CODE: message` for mcproc errors, the bare message for anything else: the one-line form screens and partial results show. */\nexport const describeError = (e: unknown): string =>\n isMcprocError(e)\n ? `${e.code}: ${e.message}`\n : e instanceof Error\n ? e.message\n : String(e);\n","/** POSIX single-quote quoting: safe for any byte sequence, including newlines. */\nexport function shq(s: string): string {\n return `'${s.replace(/'/g, `'\\\\''`)}'`;\n}\n\nexport function shjoin(argv: string[]): string {\n return argv.map(shq).join(' ');\n}\n","import { spawn, spawnSync } from 'node:child_process';\nimport { McprocError } from '../core/errors.js';\nimport type { Spawner, Streamer } from './types.js';\n\n/**\n * The pids under `root` (its children, their children, …) from one `ps` listing. A timeout must take the whole command\n * down, not only its shell: a child left running would keep the pipes, and the caller's process, alive.\n */\nfunction descendants(root: number): number[] {\n const r = spawnSync('ps', ['-A', '-o', 'pid=,ppid='], { encoding: 'utf8' });\n if (r.status !== 0) return [];\n const kids = new Map<number, number[]>();\n for (const line of r.stdout.split('\\n')) {\n const [pid, ppid] = line.trim().split(/\\s+/).map(Number);\n if (pid > 0 && ppid >= 0) kids.set(ppid, [...(kids.get(ppid) ?? []), pid]);\n }\n const out: number[] = [];\n const stack = [root];\n while (stack.length)\n for (const c of kids.get(stack.pop()!) ?? []) {\n out.push(c);\n stack.push(c);\n }\n return out;\n}\n\nexport const nodeSpawner: Spawner = (argv, { stdin, timeoutMs }) =>\n new Promise((resolve, reject) => {\n const child = spawn(argv[0], argv.slice(1), {\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n let out = '',\n err = '',\n done = false;\n const timer = setTimeout(() => {\n if (done) return;\n done = true;\n for (const pid of child.pid ? descendants(child.pid) : []) {\n try {\n process.kill(pid, 'SIGKILL');\n } catch {\n /* gone already */\n }\n }\n child.kill('SIGKILL');\n child.stdout.destroy();\n child.stderr.destroy();\n child.stdin.destroy();\n reject(\n new McprocError(\n 'TIMEOUT',\n `Command timed out after ${timeoutMs} ms: ${argv.slice(0, 4).join(' ')}`,\n { details: { stderr: err.slice(-2000) } }\n )\n );\n }, timeoutMs);\n child.stdout.setEncoding('utf8'); // decode across chunk boundaries: a multi-byte character may be split between reads\n child.stderr.setEncoding('utf8');\n child.stdout.on('data', (d) => {\n out += d;\n });\n child.stderr.on('data', (d) => {\n err += d;\n });\n child.on('error', (e) => {\n if (done) return;\n done = true;\n clearTimeout(timer);\n reject(\n new McprocError(\n 'TRANSPORT_FAILED',\n `Cannot spawn ${argv[0]}: ${e.message}`\n )\n );\n });\n child.on('close', (code) => {\n if (done) return;\n done = true;\n clearTimeout(timer);\n resolve({ code: code ?? -1, stdout: out, stderr: err });\n });\n child.stdin.on('error', () => {\n /* EPIPE when the command exits before reading stdin */\n });\n child.stdin.end(stdin ?? '');\n });\n\n/**\n * Starts a long-running command; stderr is dropped. Its stdin stays open and silent while it runs: when this process\n * kills it or goes away, the stdin closes, and that is how the command on the far side learns it is no longer read.\n */\nexport const nodeStreamer: Streamer = (argv) => {\n const child = spawn(argv[0], argv.slice(1), {\n stdio: ['pipe', 'pipe', 'ignore'],\n });\n child.stdin.on('error', () => {\n /* EPIPE: the command ended first */\n });\n let exited = false;\n const exits: ((code: number | null) => void)[] = [];\n const finish = (code: number | null) => {\n if (exited) return;\n exited = true;\n for (const cb of exits) cb(code);\n };\n child.on('error', () => finish(null));\n child.on('close', (code) => finish(code));\n return {\n onData: (cb) => void child.stdout.on('data', cb),\n onExit: (cb) => void exits.push(cb),\n kill: () => {\n child.kill('SIGTERM');\n child.stdin.destroy();\n child.stdout.destroy();\n },\n };\n};\n","import type { Host } from '../core/manifest.js';\nimport { McprocError } from '../core/errors.js';\nimport { shq, shjoin } from './quote.js';\nimport { nodeSpawner, nodeStreamer } from './spawn.js';\nimport type {\n ExecOptions,\n ExecResult,\n Spawner,\n Streamer,\n Transport,\n} from './types.js';\n\nexport type {\n ExecOptions,\n ExecResult,\n Spawner,\n StreamProc,\n Streamer,\n Transport,\n} from './types.js';\nexport { nodeSpawner, nodeStreamer } from './spawn.js';\n\nexport const DEFAULT_TIMEOUT_MS = 30_000;\n\nexport function withEnv(cmd: string, env?: Record<string, string>): string {\n const entries = Object.entries(env ?? {});\n if (entries.length === 0) return cmd;\n return `${entries.map(([k, v]) => `export ${k}=${shq(v)};`).join(' ')} ${cmd}`;\n}\n\ntype Shell = Host['shell'];\n/** no login profile: for a loop that only needs POSIX tools */\nconst PLAIN_SH: Shell = { bin: 'sh', flags: ['-c'] };\n\nfunction shellArgv(shell: Shell, cmd: string): string[] {\n return [shell.bin, ...shell.flags, cmd];\n}\n\nfunction dockerArgv(host: Host, cmd: string, shell: Shell): string[] {\n const d = host.docker!;\n return [\n 'docker',\n 'exec',\n ...(d.user ? ['-u', d.user] : []),\n '-i',\n d.container,\n ...shellArgv(shell, cmd),\n ];\n}\n\nexport const SSH_CONNECT_TIMEOUT_S = 10;\n\nexport function buildArgv(\n host: Host,\n cmd: string,\n shell: Shell = host.shell\n): string[] {\n const inner = host.docker\n ? dockerArgv(host, cmd, shell)\n : shellArgv(shell, cmd);\n // a host that does not answer at all must fail in seconds, not hang a whole fleet of probes; after ssh_args, so a\n // ConnectTimeout given there wins (ssh keeps the first value it sees)\n if (host.ssh)\n return [\n 'ssh',\n '-o',\n 'BatchMode=yes',\n ...host.ssh_args,\n '-o',\n `ConnectTimeout=${SSH_CONNECT_TIMEOUT_S}`,\n host.ssh,\n shjoin(inner),\n ];\n return inner;\n}\n\nexport function describeHost(host: Host): string {\n const parts: string[] = [];\n if (host.ssh) parts.push(`ssh ${host.ssh}`);\n if (host.docker)\n parts.push(\n `docker ${host.docker.container}${host.docker.user ? ` (${host.docker.user})` : ''}`\n );\n return parts.length ? parts.join(' → ') : 'local';\n}\n\nexport function createTransport(\n host: Host,\n spawner: Spawner = nodeSpawner,\n streamer: Streamer = nodeStreamer\n): Transport {\n return {\n describe: () => describeHost(host),\n exec(cmd: string, opts: ExecOptions = {}) {\n const argv = buildArgv(host, withEnv(cmd, opts.env));\n return spawner(argv, {\n stdin: opts.stdin,\n timeoutMs: opts.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n });\n },\n stream: (cmd: string) => streamer(buildArgv(host, cmd, PLAIN_SH)),\n };\n}\n\n/** Turns transport-level failures into TRANSPORT_FAILED; leaves command exit codes to the caller. */\nexport function ensureOk(\n res: ExecResult,\n host: Host,\n what: string\n): ExecResult {\n const tail = (res.stderr || res.stdout)\n .trim()\n .split('\\n')\n .slice(-5)\n .join('\\n');\n if (host.ssh && res.code === 255) {\n throw new McprocError(\n 'TRANSPORT_FAILED',\n `ssh to ${host.ssh} failed while running ${what}: ${tail}`,\n {\n hint: 'Check the ssh alias in ~/.ssh/config and that key-based login works non-interactively (BatchMode).',\n }\n );\n }\n if (\n host.docker &&\n /No such container|is not running|Cannot connect to the Docker daemon|permission denied while trying to connect|OCI runtime exec failed|executable file not found|unable to find user/i.test(\n res.stderr\n )\n ) {\n throw new McprocError(\n 'TRANSPORT_FAILED',\n `docker exec into ${host.docker.container} failed while running ${what}: ${tail}`\n );\n }\n return res;\n}\n","import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { McprocError } from '../core/errors.js';\nimport type { Host, Manifest } from '../core/manifest.js';\nimport { runtimeDir } from '../core/pm2.js';\nimport { clearResolutionCache } from '../core/resolve.js';\nimport { ensureOk } from '../transport/index.js';\nimport { shq } from '../transport/quote.js';\nimport type { ExecOptions, Transport } from '../transport/types.js';\nimport { VERSION } from '../version.js';\nimport { ensurePm2Bundle, type Pm2Bundle } from './bundle.js';\nimport { needsNode, plannedWrites, type UnpackOptions } from './decide.js';\nimport {\n manifestCopy,\n renderLock,\n renderWrapper,\n stagedVerifyScript,\n verifyScript,\n type RuntimeLock,\n} from './files.js';\nimport { fetchNodeTarball, resolveNodeVersion } from './node-dist.js';\nimport type { NodePlatform } from './platform.js';\nimport { UNPACK_MARK, parseUnpackProbe, unpackProbeScript } from './probe.js';\n\nexport interface UnpackDeps {\n pm2Bundle(): Promise<Pm2Bundle>;\n nodeVersion(\n requested: string | undefined,\n platform: NodePlatform\n ): Promise<string>;\n nodeTarball(\n version: string,\n platform: NodePlatform\n ): Promise<{ data: Buffer; sha256: string }>;\n hostname(): string;\n now(): Date;\n}\n\nexport function defaultUnpackDeps(): UnpackDeps {\n return {\n pm2Bundle: () => ensurePm2Bundle(),\n nodeVersion: (requested, platform) =>\n resolveNodeVersion(requested, platform),\n nodeTarball: async (version, platform) => {\n const t = await fetchNodeTarball(version, platform);\n return { data: fs.readFileSync(t.path), sha256: t.sha256 };\n },\n hostname: () => os.hostname(),\n now: () => new Date(),\n };\n}\n\nexport interface UnpackTarget {\n manifest: Manifest;\n host: Host;\n transport: Transport;\n}\nexport interface UnpackResult {\n host: string;\n runtime_dir: string;\n noop: boolean;\n pm2: { version: string; written: boolean };\n node: { version: string; platform: NodePlatform; written: boolean } | null;\n manifest_copy: 'written' | 'kept-hand-written' | 'not-needed-local';\n runtime_line: string | null;\n monit: string;\n update_hint: string | null;\n}\n\nexport async function unpack(\n target: UnpackTarget,\n opts: UnpackOptions,\n deps: UnpackDeps\n): Promise<UnpackResult> {\n const { manifest, host, transport } = target;\n const rt = opts.dir ?? runtimeDir(host);\n if (!rt.startsWith('/')) {\n throw new McprocError(\n 'BAD_ARGUMENT',\n `dir must be an absolute path on host \"${host.name}\", got \"${rt}\"`,\n { hint: '\"~\" and relative paths are not expanded.' }\n );\n }\n const env = host.pm2_home ? { PM2_HOME: host.pm2_home } : undefined;\n const run = async (what: string, cmd: string, o: ExecOptions = {}) => {\n const res = ensureOk(await transport.exec(cmd, { env, ...o }), host, what);\n if (res.code !== 0) {\n throw new McprocError(\n 'TRANSPORT_FAILED',\n `${what} failed on ${transport.describe()} (exit ${res.code}): ${(res.stderr || res.stdout).trim().split('\\n').slice(-5).join('\\n')}`\n );\n }\n return res;\n };\n const dotDir = path.posix.join(host.cwd, '.mcproc');\n const remoteManifest = path.posix.join(dotDir, 'mcproc.yaml');\n\n // 1. one probe round trip\n const pr = ensureOk(\n await transport.exec(unpackProbeScript(rt, remoteManifest), { env }),\n host,\n 'unpack probe'\n );\n if (!pr.stdout.includes(UNPACK_MARK)) {\n throw new McprocError(\n 'TRANSPORT_FAILED',\n `the shell on ${transport.describe()} did not run the unpack probe (exit ${pr.code}): ${(pr.stderr || pr.stdout).trim()}`,\n {\n hint: `Check hosts.${host.name}.shell; hosts without bash need shell: /bin/sh -c`,\n }\n );\n }\n const facts = parseUnpackProbe(pr.stdout);\n if (!facts.tar)\n throw new McprocError(\n 'TAR_NOT_FOUND',\n `${transport.describe()} has no tar; unpack streams its archives into tar -xzf -`,\n { hint: 'Install tar on that host (busybox tar is enough).' }\n );\n if (facts.foreignBin && !opts.force) {\n throw new McprocError(\n 'BAD_ARGUMENT',\n `${rt}/bin already holds a pm2 or node that mcproc did not write (no mcproc lock in ${rt}/lock.json); refusing to overwrite it`,\n {\n hint: 'Point dir at a directory of its own (the default is <cwd>/.mcproc/runtime), or pass force: true to replace those files.',\n }\n );\n }\n\n // 2. everything that can fail without touching the host happens first\n const node = needsNode(facts, opts);\n const bundle = await deps.pm2Bundle();\n // an unpacked Node stays at its locked version: upgrades happen only on an explicit node_version or force, never because a newer LTS appeared\n const wanted =\n opts.nodeVersion ??\n (opts.force ? undefined : (facts.lock?.node ?? undefined));\n const nodeVersion = node.need\n ? await deps.nodeVersion(wanted, node.platform!)\n : null;\n const writes = plannedWrites(facts, opts, bundle.version, nodeVersion);\n const nodeTar = writes.writeNode\n ? await deps.nodeTarball(nodeVersion!, node.platform!)\n : null;\n\n // 3. writes on the host\n // a tree swap cut off between its two renames (`<v>` → `<v>.old`, `<v>.part` → `<v>`) left `<v>` missing: put it back before anything else is written\n await run(\n 'heal',\n `for d in ${shq(rt)}/pm2/*.old ${shq(rt)}/node/*.old; do [ -e \"$d\" ] || continue; t=\"\\${d%.old}\"; [ -e \"$t\" ] || mv \"$d\" \"$t\"; done; true`\n );\n\n const pm2Dir = `${rt}/pm2/${bundle.version}`;\n const nodeDir = nodeVersion ? `${rt}/node/${nodeVersion}` : '';\n // each new tree is unpacked beside its place (`.part`): a cut stream never leaves half a tree where one is expected\n const stage = (dir: string, strip: string) =>\n `rm -rf ${shq(`${dir}.part`)} && mkdir -p ${shq(`${dir}.part`)} && tar -xzf - -C ${shq(`${dir}.part`)}${strip}`;\n if (writes.writePm2)\n await run('pm2 extraction', stage(pm2Dir, ''), {\n stdin: bundle.data,\n timeoutMs: 300_000,\n });\n if (writes.writeNode)\n await run('node extraction', stage(nodeDir, ' --strip-components=1'), {\n stdin: nodeTar!.data,\n timeoutMs: 600_000,\n });\n const placed = [\n ...(writes.writePm2 ? [pm2Dir] : []),\n ...(writes.writeNode ? [nodeDir] : []),\n ];\n if (placed.length) {\n // nothing in use changes before the staged runtime answers with the Node it will run under (a new Node that cannot start stops here)\n const staged = await run(\n 'staged runtime check',\n stagedVerifyScript(rt, bundle.version, {\n pm2Tree: writes.writePm2 ? `${pm2Dir}.part` : undefined,\n nodeBin: writes.writeNode ? `${nodeDir}.part/bin/node` : null,\n })\n );\n const answer = staged.stdout.trim().split('\\n').pop()?.trim() ?? '';\n if (answer !== bundle.version) {\n throw new McprocError(\n 'PM2_FAILED',\n `the new runtime at ${rt} answers \"${answer}\", expected pm2 ${bundle.version}; the one in use was left as it was`,\n {\n hint: 'Run unpack again; with node_version, check that this Node build runs on the host.',\n }\n );\n }\n // then every switch is a rename: each tree into its place (the one in use, a forced reinstall's, kept as .old until the\n // switch is done), the wrapper — mcproc's mark — then the node link, then the lock\n await run(\n 'trees',\n placed\n .map(\n (d) =>\n `{ [ ! -e ${shq(d)} ] || { rm -rf ${shq(`${d}.old`)} && mv ${shq(d)} ${shq(`${d}.old`)}; }; } && mv ${shq(`${d}.part`)} ${shq(d)}`\n )\n .join(' && ')\n );\n const link = writes.writeNode\n ? ` && ln -sfn ${shq(`${nodeDir}/bin/node`)} ${shq(`${rt}/bin/node.next`)} && mv -f ${shq(`${rt}/bin/node.next`)} ${shq(`${rt}/bin/node`)}`\n : '';\n await run(\n 'wrapper',\n `mkdir -p ${shq(`${rt}/bin`)} && cat > ${shq(`${rt}/bin/pm2.next`)} && chmod 755 ${shq(`${rt}/bin/pm2.next`)} && mv -f ${shq(`${rt}/bin/pm2.next`)} ${shq(`${rt}/bin/pm2`)}${link}`,\n { stdin: renderWrapper(rt, bundle.version) }\n );\n const lock: RuntimeLock = {\n mcproc: VERSION,\n pm2: bundle.version,\n pm2_sha256: bundle.sha256,\n node: writes.writeNode ? nodeVersion : (facts.lock?.node ?? null),\n node_sha256: writes.writeNode\n ? nodeTar!.sha256\n : (facts.lock?.node_sha256 ?? null),\n platform: writes.writeNode\n ? node.platform\n : (facts.lock?.platform ?? null),\n written_at: deps.now().toISOString(),\n by: deps.hostname(),\n };\n await run(\n 'lock',\n `cat > ${shq(`${rt}/lock.json.next`)} && mv -f ${shq(`${rt}/lock.json.next`)} ${shq(`${rt}/lock.json`)}`,\n { stdin: renderLock(lock) }\n );\n await run(\n 'cleanup',\n `rm -rf ${placed.map((d) => shq(`${d}.old`)).join(' ')}`\n );\n }\n\n // 4. manifest copy on remote hosts; a hand-written manifest there is never overwritten without force\n let manifestState: UnpackResult['manifest_copy'] = 'not-needed-local';\n if (!host.local) {\n if (facts.manifest === 'hand-written' && !opts.force) {\n manifestState = 'kept-hand-written';\n } else {\n const gi = `${dotDir}/.gitignore`;\n await run(\n 'manifest copy',\n `mkdir -p ${shq(`${dotDir}/.generated`)} && { [ -e ${shq(gi)} ] || printf '*\\\\n' > ${shq(gi)}; } && cat > ${shq(remoteManifest)}`,\n {\n stdin: manifestCopy(\n fs.readFileSync(manifest.path, 'utf8'),\n deps.hostname(),\n deps.now()\n ),\n }\n );\n const readme = path.join(manifest.root, '.mcproc', 'README.md');\n if (fs.existsSync(readme))\n await run(\n 'readme copy',\n `[ -e ${shq(`${dotDir}/README.md`)} ] || cat > ${shq(`${dotDir}/README.md`)}`,\n { stdin: fs.readFileSync(readme, 'utf8') }\n );\n manifestState = 'written';\n }\n }\n\n // 5. verify without starting a daemon (pm2 -v would spawn one)\n const v = await run('runtime check', verifyScript(rt, bundle.version));\n const got = v.stdout.trim().split('\\n').pop()?.trim() ?? '';\n if (got !== bundle.version) {\n throw new McprocError(\n 'PM2_FAILED',\n `the runtime at ${rt} reports pm2 \"${got}\", expected ${bundle.version}`,\n { hint: 'Run unpack again with force: true.' }\n );\n }\n\n clearResolutionCache(); // the next connect re-probes and finds <rt>/bin/pm2\n const pm2Home = host.pm2_home ? `PM2_HOME=${shq(host.pm2_home)} ` : '';\n const pm2Cmd = `${pm2Home}${shq(`${rt}/bin/pm2`)}`;\n return {\n host: host.name,\n runtime_dir: rt,\n noop: !writes.writePm2 && !writes.writeNode,\n pm2: { version: bundle.version, written: writes.writePm2 },\n node: nodeVersion\n ? {\n version: nodeVersion,\n platform: node.platform!,\n written: writes.writeNode,\n }\n : null,\n manifest_copy: manifestState,\n runtime_line:\n opts.dir && opts.dir !== runtimeDir(host)\n ? `hosts.${host.name}.runtime: ${opts.dir}`\n : null,\n monit: `${pm2Cmd} monit`,\n // any runtime change under a live daemon: it keeps running the old pm2 and/or node until `update` restarts it\n update_hint:\n facts.daemonUp &&\n ((writes.writePm2 && facts.lock?.pm2 !== bundle.version) ||\n (writes.writeNode && facts.lock?.node !== nodeVersion))\n ? `a pm2 daemon is already running there${facts.lock ? ` (started from pm2 ${facts.lock.pm2}${facts.lock.node ? `, node ${facts.lock.node}` : ''})` : ''}; to move it to the new runtime run: ${pm2Cmd} update`\n : null,\n };\n}\n","import { createRequire } from 'node:module';\nimport path from 'node:path';\nimport { McprocError } from './errors.js';\nimport type { Host } from './manifest.js';\nimport { shq } from '../transport/quote.js';\nimport { ensureOk } from '../transport/index.js';\nimport type { ExecResult, Transport } from '../transport/types.js';\n\nexport interface Pm2Process {\n pm_id: number;\n name: string;\n namespace: string;\n pid: number;\n status: string;\n cwd: string;\n out_log: string;\n err_log: string;\n restarts: number;\n unstable_restarts: number;\n /** pm2's last recorded exit code for the process, any app; null when pm2 has recorded none (it never exited, or the field is absent) */\n exit_code: number | null;\n uptime_ms: number | null;\n /** when pm2 last started the process (pm_uptime, epoch ms), any status: a stopped process keeps its last start; null when absent */\n started_at: number | null;\n cpu: number;\n memory: number;\n watch: boolean;\n}\n\nconst RUNNING = new Set(['online', 'launching']);\n/** Whether a pm2 status is a process that is running, or about to be: the only one with a current run to look at. */\nexport const isRunning = (status: string): boolean => RUNNING.has(status);\n\nexport const PM2_NOT_FOUND_HINT =\n 'No usable pm2 on this host. Run unpack for it (brings pm2, and Node when missing), install pm2 there (Node 18 or newer), or set hosts.<host>.pm2.';\n\ntype RawProc = {\n pid?: number;\n name: string;\n pm_id: number;\n monit?: { memory?: number; cpu?: number };\n pm2_env?: Record<string, unknown>;\n};\n\nfunction normalize(p: RawProc): Pm2Process {\n const env = p.pm2_env ?? {};\n const status = String(env.status ?? 'unknown');\n const up = typeof env.pm_uptime === 'number' ? env.pm_uptime : null;\n return {\n pm_id: p.pm_id,\n name: p.name,\n namespace: String(env.namespace ?? 'default'),\n pid: p.pid ?? 0,\n status,\n cwd: String(env.pm_cwd ?? ''),\n out_log: String(env.pm_out_log_path ?? ''),\n err_log: String(env.pm_err_log_path ?? ''),\n restarts: Number(env.restart_time ?? 0),\n unstable_restarts: Number(env.unstable_restarts ?? 0),\n exit_code: typeof env.exit_code === 'number' ? env.exit_code : null,\n uptime_ms: status === 'online' && up ? Math.max(0, Date.now() - up) : null,\n started_at: up,\n cpu: p.monit?.cpu ?? 0,\n memory: p.monit?.memory ?? 0,\n watch: Boolean(env.watch),\n };\n}\n\n/**\n * pm2 prints coloured \"[PM2] …\" lines before the JSON when it spawns the daemon, and an update notice on any\n * command; take the last line that opens a JSON array. Real pm2 prints the array on one line; a pretty-printed\n * array (a wrapper, a fixture) is accepted too by parsing from that line to the end of the output.\n */\nexport function parseJlist(stdout: string): Pm2Process[] {\n const lines = stdout.split('\\n');\n const asArray = (text: string): RawProc[] | null => {\n try {\n const v = JSON.parse(text);\n return Array.isArray(v) ? (v as RawProc[]) : null;\n } catch {\n return null;\n }\n };\n for (let i = lines.length - 1; i >= 0; i--) {\n const l = lines[i].trim();\n if (!l.startsWith('[') || l.startsWith('[PM2]')) continue;\n const arr = asArray(l) ?? asArray(lines.slice(i).join('\\n'));\n if (arr) return arr.map(normalize);\n }\n throw new McprocError('PM2_FAILED', 'pm2 jlist returned no JSON array', {\n details: stdout.slice(-500),\n });\n}\n\n/**\n * The pm2 process name of a manifest app. pm2 matches processes by NAME only (`start`/`startOrRestart --only`\n * ignore the namespace), so a bare app name would let one project take over another project's process on a\n * shared daemon. The project prefix keeps names unique per project; the namespace is still set for grouping.\n */\nexport function pm2Name(project: string, app: string): string {\n return `${project}-${app}`;\n}\n\nexport function findProcess(\n procs: Pm2Process[],\n project: string,\n app: string\n): Pm2Process | undefined {\n const name = pm2Name(project, app);\n return procs.find((p) => p.namespace === project && p.name === name);\n}\n\nexport class Pm2Client {\n constructor(\n readonly transport: Transport,\n readonly host: Host,\n readonly bin: string,\n readonly pm2Home?: string\n ) {}\n env(): Record<string, string> | undefined {\n return this.pm2Home ? { PM2_HOME: this.pm2Home } : undefined;\n }\n async run(\n args: string[],\n opts: { timeoutMs?: number } = {}\n ): Promise<ExecResult> {\n const cmd = `${this.bin} ${args.map(shq).join(' ')}`;\n const res = ensureOk(\n await this.transport.exec(cmd, {\n env: this.env(),\n timeoutMs: opts.timeoutMs,\n }),\n this.host,\n `pm2 ${args[0]}`\n );\n if (res.code === 127 && !/pm2/i.test(res.stderr))\n throw new McprocError(\n 'TRANSPORT_FAILED',\n `the shell on ${this.transport.describe()} could not run pm2 ${args[0]}: ${res.stderr.trim()}`\n );\n if (res.code === 127)\n throw new McprocError(\n 'PM2_NOT_FOUND',\n `pm2 not found on ${this.transport.describe()}: ${res.stderr.trim()}`,\n { hint: PM2_NOT_FOUND_HINT }\n );\n if (res.code !== 0) {\n const tail = (res.stderr || res.stdout)\n .trim()\n .split('\\n')\n .slice(-5)\n .join('\\n');\n throw new McprocError(\n 'PM2_FAILED',\n `pm2 ${args[0]} failed (exit ${res.code}): ${tail}`\n );\n }\n return res;\n }\n async jlist(): Promise<Pm2Process[]> {\n return parseJlist((await this.run(['jlist'])).stdout);\n }\n startOrRestart(file: string, app: string) {\n return this.run(['startOrRestart', file, '--only', app, '--update-env'], {\n timeoutMs: 90_000,\n });\n }\n stop(id: number) {\n return this.run(['stop', String(id)]);\n }\n delete(id: number) {\n return this.run(['delete', String(id)]);\n }\n async version(): Promise<string> {\n return (await this.run(['-v'])).stdout.trim().split('\\n').pop() ?? '';\n }\n}\n\nexport interface Pm2Resolution {\n bin: string;\n source: 'explicit' | 'runtime' | 'path' | 'bundled';\n node: string | null;\n pm2Version: string | null;\n reason: string;\n}\n\nexport function runtimeDir(host: Host): string {\n return host.runtime ?? path.posix.join(host.cwd, '.mcproc', 'runtime');\n}\n\nexport function bundledPm2Bin(): string {\n const req = createRequire(import.meta.url);\n const pm2Path = req.resolve('pm2/bin/pm2');\n return `${shq(process.execPath)} ${shq(pm2Path)}`;\n}\n\nexport function nodeMajor(v: string | null): number {\n const m = /^v?(\\d+)/.exec(v ?? '');\n return m ? Number(m[1]) : 0;\n}\n\nexport async function resolvePm2Bin(\n host: Host,\n transport: Transport\n): Promise<Pm2Resolution> {\n if (host.pm2)\n return {\n bin: host.pm2,\n source: 'explicit',\n node: null,\n pm2Version: null,\n reason: `hosts.${host.name}.pm2`,\n };\n const rt = path.posix.join(runtimeDir(host), 'bin', 'pm2');\n // the runtime bundle wins without running any other pm2 (a hanging shim cannot block it); `pm2 -v` talks to a daemon,\n // so it runs with the host's PM2_HOME, never against the default one\n const probe = [\n `if [ -x ${shq(rt)} ]; then echo RUNTIME; elif command -v pm2 >/dev/null 2>&1; then echo PATH_OK; pm2 -v 2>/dev/null | tail -n 1; echo; else echo PATH_NONE; fi`,\n `node -v 2>/dev/null || echo NODE_NONE`,\n ].join('; ');\n const res = ensureOk(\n await transport.exec(probe, {\n env: host.pm2_home ? { PM2_HOME: host.pm2_home } : undefined,\n }),\n host,\n 'pm2 probe'\n );\n const lines = res.stdout.split('\\n').map((l) => l.trim());\n if (\n !lines.includes('RUNTIME') &&\n !lines.includes('PATH_OK') &&\n !lines.includes('PATH_NONE')\n ) {\n const tail = (res.stderr || res.stdout)\n .trim()\n .split('\\n')\n .slice(-5)\n .join('\\n');\n throw new McprocError(\n 'TRANSPORT_FAILED',\n `the shell on ${transport.describe()} did not run the pm2 probe (exit ${res.code}): ${tail}`,\n {\n hint: `Check hosts.${host.name}.shell (default /bin/bash -lc) exists on that host.`,\n }\n );\n }\n const node = lines.find((l) => /^v\\d+\\./.test(l)) ?? null;\n if (lines.includes('RUNTIME'))\n return {\n bin: shq(rt),\n source: 'runtime',\n node,\n pm2Version: null,\n reason: `runtime bundle at ${runtimeDir(host)}`,\n };\n const i = lines.indexOf('PATH_OK');\n const pm2Version =\n i >= 0 && /^\\d+\\.\\d+/.test(lines[i + 1] ?? '') ? lines[i + 1] : null;\n if (pm2Version && nodeMajor(node) >= 18)\n return {\n bin: 'pm2',\n source: 'path',\n node,\n pm2Version,\n reason: 'pm2 on the login-shell PATH',\n };\n if (host.local)\n return {\n bin: bundledPm2Bin(),\n source: 'bundled',\n node: process.version,\n pm2Version: null,\n reason: 'pm2 bundled with mcproc',\n };\n const why =\n i < 0\n ? 'no pm2 on PATH'\n : !pm2Version\n ? 'pm2 on PATH does not run (`pm2 -v` printed nothing)'\n : `Node ${node ?? 'missing'} is older than 18`;\n throw new McprocError('PM2_NOT_FOUND', `${transport.describe()}: ${why}`, {\n hint: PM2_NOT_FOUND_HINT,\n });\n}\n","import path from 'node:path';\nimport { McprocError } from './errors.js';\nimport {\n loadManifest,\n scopeManifest,\n type Host,\n type Manifest,\n} from './manifest.js';\nimport { Pm2Client, resolvePm2Bin, type Pm2Resolution } from './pm2.js';\nimport { createTransport } from '../transport/index.js';\nimport type { Spawner, Transport } from '../transport/types.js';\nimport { checkHere, type HereCheck } from './urlcheck.js';\n\nexport const MAX_PM2_HOME = 90;\n\nexport function resolveProjectDir(\n explicit?: string,\n roots: string[] = [],\n env: NodeJS.ProcessEnv = process.env\n): string {\n const pick =\n explicit ||\n env.MCPROC_PROJECT ||\n env.CLAUDE_PROJECT_DIR ||\n roots[0] ||\n process.cwd();\n return path.resolve(pick);\n}\n\nexport interface Prepared {\n manifest: Manifest;\n host: Host;\n}\nexport interface Context extends Prepared {\n transport: Transport;\n pm2: Pm2Client;\n resolution: Pm2Resolution;\n /** checks a url from this machine when url_check asks for it; tests pass a fake */\n hereCheck: HereCheck;\n}\n\nexport function pickHost(m: Manifest, name = 'local'): Host {\n const h = Object.hasOwn(m.hosts, name) ? m.hosts[name] : undefined;\n if (!h)\n throw new McprocError(\n 'UNKNOWN_HOST',\n `Unknown host \"${name}\" in ${m.path}`,\n { hint: `Known hosts: ${Object.keys(m.hosts).join(', ')}` }\n );\n if (h.pm2_home && h.pm2_home.length > MAX_PM2_HOME) {\n throw new McprocError(\n 'PM2_HOME_TOO_LONG',\n `hosts.${name}.pm2_home is ${h.pm2_home.length} characters; unix socket paths are capped at 108 bytes and pm2 puts its sockets inside PM2_HOME`,\n { hint: `Use a path of at most ${MAX_PM2_HOME} characters.` }\n );\n }\n return h;\n}\n\nexport function assertWritable(host: Host): void {\n if (host.readonly)\n throw new McprocError(\n 'READONLY_HOST',\n `Host \"${host.name}\" is readonly: no start/stop/restart/delete/flush/init there`,\n {\n hint: 'Read-only tools (ls, describe, logs, ports, doctor) still work.',\n }\n );\n}\n\nexport function assertApp(m: Manifest, name: string): void {\n if (!Object.hasOwn(m.apps, name))\n throw new McprocError('UNKNOWN_APP', `Unknown app \"${name}\" in ${m.path}`, {\n hint: `Known apps: ${Object.keys(m.apps).join(', ')}`,\n });\n}\n\nexport function prepare(opts: {\n project?: string;\n host?: string;\n roots?: string[];\n}): Prepared {\n const manifest = loadManifest(resolveProjectDir(opts.project, opts.roots));\n return { manifest, host: pickHost(manifest, opts.host) };\n}\n\nconst cache = new Map<string, Pm2Resolution>();\nexport function clearResolutionCache(): void {\n cache.clear();\n}\n\n/**\n * A context for one host. Its manifest is the host's view (scopeManifest): the apps bound to it plus the unbound ones\n * when it is the fallback — by default the host itself, i.e. what `--host <it>` means; a whole-project command reaching\n * a host it does not name passes `fallback` (local), so that host sees only its bound apps. `hereCheck` is the check of\n * a url from this machine; every context gets the real one unless a caller (a test) passes another.\n */\nexport async function connect(\n prep: Prepared,\n opts: {\n spawner?: Spawner;\n fresh?: boolean;\n fallback?: string;\n hereCheck?: HereCheck;\n } = {}\n): Promise<Context> {\n const transport = createTransport(prep.host, opts.spawner);\n const key = `${prep.manifest.path}|${prep.host.name}`;\n let resolution = opts.fresh ? undefined : cache.get(key);\n if (!resolution) {\n resolution = await resolvePm2Bin(prep.host, transport);\n cache.set(key, resolution);\n }\n const pm2 = new Pm2Client(\n transport,\n prep.host,\n resolution.bin,\n prep.host.pm2_home\n );\n return {\n manifest: scopeManifest(\n prep.manifest,\n prep.host.name,\n opts.fallback ?? prep.host.name\n ),\n host: prep.host,\n transport,\n pm2,\n resolution,\n hereCheck: opts.hereCheck ?? checkHere,\n };\n}\n\nexport function createContext(opts: {\n project?: string;\n host?: string;\n roots?: string[];\n spawner?: Spawner;\n fresh?: boolean;\n}): Promise<Context> {\n return connect(prepare(opts), { spawner: opts.spawner, fresh: opts.fresh });\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport { z } from 'zod';\nimport { McprocError } from './errors.js';\nimport { VERSION, VERSION_PATTERN, compareVersions } from '../version.js';\nimport { repeatsARepeat } from './incidents/detect.js';\nimport { NAME_RE } from './names.js';\nimport { loadOverride, type Override } from './override.js';\nimport { parsePercent, parseSizeMib } from './sizes.js';\nimport {\n renderTemplate,\n resolveVars,\n TemplateError,\n type VarValue,\n} from './template.js';\n\nexport { NAME_RE };\nexport const MANIFEST_REL = path.join('.mcproc', 'mcproc.yaml');\nexport const PROTECTED_PM2_KEYS = [\n 'name',\n 'namespace',\n 'cwd',\n 'script',\n 'args',\n 'interpreter',\n 'time',\n 'log_date_format',\n] as const;\nexport const DEFAULT_SHELL = '/bin/bash -lc';\n\nconst name = z.string().regex(NAME_RE, 'must match ^[a-z0-9][a-z0-9._-]*$');\nconst envValue = z.union([z.string(), z.number(), z.boolean()]);\nconst portNo = z.number().int().min(1).max(65535);\nconst VAR_NAME_RE = /^[a-z][a-z0-9_]*$/;\nconst varName = z.string().regex(VAR_NAME_RE, 'must match ^[a-z][a-z0-9_]*$');\nconst varValue = z.union([z.string(), z.number(), z.boolean()]);\nconst sizeString = z.string().min(1);\n\nexport type AppKind = 'build' | 'server' | 'worker' | 'task';\nexport type DepCondition = 'started' | 'ready' | 'completed';\n/** One dependency: which app, what state of it the dependent waits for, and how long. */\nexport interface Dep {\n app: string;\n condition: DepCondition;\n timeoutMs: number;\n}\nexport const DEP_TIMEOUT_DEFAULT_S = 60;\nexport const DEP_TIMEOUT_MAX_S = 600;\n\n/** A bare name means `started`; the object form names the condition and how long to wait for it. */\nconst depSchema = z.union([\n z.string().min(1),\n z\n .object({\n app: z.string().min(1),\n condition: z.enum(['started', 'ready', 'completed']).default('started'),\n timeout: z\n .number()\n .int()\n .min(1)\n .max(DEP_TIMEOUT_MAX_S)\n .default(DEP_TIMEOUT_DEFAULT_S),\n })\n .strict(),\n]);\n\nconst errorsSchema = z.union([\n z.literal(false),\n z\n .object({\n match: z.array(z.string().min(1)).default([]),\n ignore: z.array(z.string().min(1)).default([]),\n context: z\n .tuple([\n z.number().int().min(0).max(50),\n z.number().int().min(0).max(50),\n ])\n .default([3, 5]),\n stderr: z.boolean().default(false),\n defaults: z.boolean().default(true),\n })\n .strict(),\n]);\n\nconst reloadsSchema = z.union([\n z.literal(false),\n z\n .object({\n match: z.array(z.string().min(1)).default([]),\n ignore: z.array(z.string().min(1)).default([]),\n defaults: z.boolean().default(true),\n })\n .strict(),\n]);\n\nconst appSchema = z\n .object({\n description: z.string().min(1),\n kind: z.enum(['build', 'server', 'worker', 'task']).default('server'),\n run: z.string().min(1),\n cwd: z.string().min(1).default('.'),\n env: z.record(envValue).default({}),\n memory: sizeString.optional(),\n containers: z.array(z.string().min(1)).default([]),\n port: portNo.optional(),\n ports: z.array(portNo).optional(),\n url: z\n .string()\n .regex(\n /^https?:\\/\\/\\S+$/,\n 'url must start with http:// or https:// (it is opened in a browser and checked with one HTTP request)'\n )\n .optional(),\n url_check: z.enum(['auto', 'host', 'here']).optional(),\n watch: z.union([z.boolean(), z.array(z.string())]).optional(),\n watch_delay: z.number().int().min(0).optional(),\n ignore_watch: z.array(z.string()).optional(),\n depends_on: z.array(depSchema).default([]),\n autorestart: z.boolean().optional(),\n pm2: z.record(z.unknown()).default({}),\n host: name.optional(),\n errors: errorsSchema.optional(),\n reloads: reloadsSchema.optional(),\n })\n .strict();\n\nconst hostSchema = z\n .object({\n ssh: z.string().min(1).optional(),\n ssh_args: z.array(z.string()).default([]),\n docker: z\n .object({\n container: z.string().min(1),\n user: z.string().min(1).optional(),\n })\n .strict()\n .optional(),\n cwd: z.string().min(1).optional(),\n readonly: z.boolean().default(false),\n shell: z.string().min(1).default(DEFAULT_SHELL),\n pm2: z.string().min(1).optional(),\n pm2_home: z.string().min(1).optional(),\n runtime: z.string().min(1).optional(),\n env: z.record(envValue).default({}),\n })\n .strict();\n\nconst resourcesSchema = z\n .object({\n reserve: z.string().min(1).optional(),\n margin: z.string().min(1).optional(),\n settle: z.number().int().min(0).max(600).optional(),\n })\n .strict();\nconst worktreeSchema = z\n .object({\n dir: z.string().min(1).nullable().optional(),\n copy: z.array(z.string().min(1)).default([]),\n link: z.array(z.string().min(1)).default([]),\n install: z\n .union([z.string().min(1), z.literal(false)])\n .nullable()\n .optional(),\n slots: z.number().int().min(1).max(99).default(9),\n })\n .strict();\nconst execSchema = z.object({ env: z.record(varValue).default({}) }).strict();\n\n/** A key left empty in YAML (`apps:` with only comments below it) parses as null: treat it as an empty map. */\nconst orEmpty = <T extends z.ZodTypeAny>(schema: T) =>\n z.preprocess((v) => (v === null || v === undefined ? {} : v), schema);\n\nconst WRITTEN_BY =\n 'must be the version of the mcproc that wrote this manifest, like 0.13.0';\n\nexport const manifestSchema = z\n .object({\n version: z.literal(1),\n mcproc: z\n .string({ invalid_type_error: WRITTEN_BY })\n .regex(VERSION_PATTERN, WRITTEN_BY)\n .optional(),\n project: name.optional(),\n vars: orEmpty(z.record(varName, varValue)),\n resources: orEmpty(resourcesSchema),\n worktree: orEmpty(worktreeSchema),\n exec: orEmpty(execSchema),\n apps: orEmpty(z.record(name, appSchema)),\n profiles: orEmpty(z.record(name, z.array(z.string()))),\n hosts: orEmpty(z.record(name, hostSchema)),\n })\n .strict();\n\n/** What counts as an error in an app's logs (the `incidents` tool); null when the app turned detection off. */\nexport interface ErrorSettings {\n match: string[];\n ignore: string[];\n context: [number, number];\n stderr: boolean;\n defaults: boolean;\n}\n/** What counts as an in-process reload in an app's logs (a watcher's restart or rebuild that pm2 does not see). */\nexport interface ReloadSettings {\n match: string[];\n ignore: string[];\n defaults: boolean;\n}\n/** Where an app's url is requested from: its host, then this machine when the host gets no answer (auto); only one side otherwise. */\nexport type UrlCheckMode = 'auto' | 'host' | 'here';\n/** One resolved var and where its value came from, as describe shows it. */\nexport interface VarInfo {\n name: string;\n value: VarValue;\n source: 'built-in' | 'manifest' | 'override';\n}\n/** What a stand must leave to the rest of the host, the safety margin on an estimate, and the watcher's settle time. */\nexport interface Resources {\n reserve: { kind: 'mib'; mib: number } | { kind: 'percent'; ratio: number };\n margin: number;\n settle: number;\n}\n/** What a worktree of this repository gets beyond the git tree. */\nexport interface WorktreeSettings {\n /** where worktrees go; null = `<main checkout>.worktrees` next to the repository */\n dir: string | null;\n copy: string[];\n link: string[];\n /** the install command; null = detected from the lockfile; false = none */\n install: string | false | null;\n slots: number;\n}\nexport interface ExecSettings {\n env: Record<string, string>;\n}\nexport const RESERVE_DEFAULT_MIB = 2048;\nexport const MARGIN_DEFAULT = 0.1;\nexport const SETTLE_DEFAULT_S = 20;\n\nexport interface App {\n name: string;\n description: string;\n kind: AppKind;\n run: string;\n cwd: string;\n env: Record<string, string>;\n /** the memory the app is expected to use, in MiB; null when undeclared */\n memory_mib: number | null;\n /** docker containers the app owns, removed with it */\n containers: string[];\n ports: number[];\n url: string | null;\n /** where the url is requested from: auto (its host, then this machine when the host gets no answer), host, or here */\n url_check: UrlCheckMode;\n watch?: boolean | string[];\n watch_delay?: number;\n ignore_watch?: string[];\n depends_on: Dep[];\n autorestart: boolean;\n pm2: Record<string, unknown>;\n /** the host this app always runs on; null = wherever the command points (--host, default local) */\n host: string | null;\n errors: ErrorSettings | null;\n /** null when the app turned reload detection off */\n reloads: ReloadSettings | null;\n}\nexport interface Host {\n name: string;\n local: boolean;\n ssh?: string;\n ssh_args: string[];\n docker?: { container: string; user?: string };\n cwd: string;\n readonly: boolean;\n shell: { bin: string; flags: string[] };\n pm2?: string;\n pm2_home?: string;\n runtime?: string;\n env: Record<string, string>;\n}\nexport interface Manifest {\n root: string;\n path: string;\n /** the version of the mcproc that wrote the manifest (init records it); null when it names none */\n mcproc: string | null;\n project: string;\n /** the manifest's own slug (declared, else from the main checkout's directory name), before any override: the registry of worktree slots is keyed by it */\n base_project: string;\n vars: VarInfo[];\n /** the override file that set project or vars; null when the checkout has none */\n override: string | null;\n /** the main checkout of this repository: the override's `repo` for a worktree, else this root */\n repo: string;\n /** the value of a numeric `slot` var; null when the manifest declares none */\n slot: number | null;\n resources: Resources;\n worktree: WorktreeSettings;\n exec: ExecSettings;\n apps: Record<string, App>;\n profiles: Record<string, string[]>;\n hosts: Record<string, Host>;\n}\n\nexport function findManifestPath(\n startDir: string\n): { root: string; path: string } | null {\n let dir = path.resolve(startDir);\n for (;;) {\n const p = path.join(dir, MANIFEST_REL);\n if (fs.existsSync(p)) return { root: dir, path: p };\n const parent = path.dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n}\n\nexport function defaultProject(root: string): string {\n const s = path\n .basename(root)\n .toLowerCase()\n .replace(/[^a-z0-9._-]+/g, '-')\n .replace(/^[^a-z0-9]+/, '')\n .replace(/-+$/, '');\n return s || 'project';\n}\n\nfunction stringifyEnv(\n env: Record<string, string | number | boolean>\n): Record<string, string> {\n return Object.fromEntries(\n Object.entries(env).map(([k, v]) => [k, String(v)])\n );\n}\n\nexport function parseShell(s: string): { bin: string; flags: string[] } {\n const parts = s.trim().split(/\\s+/);\n return { bin: parts[0], flags: parts.slice(1) };\n}\n\nfunction findCycle(apps: Record<string, App>): string[] | null {\n const state = new Map<string, 0 | 1 | 2>();\n const stack: string[] = [];\n const visit = (n: string): string[] | null => {\n const st = state.get(n) ?? 0;\n if (st === 1) return [...stack.slice(stack.indexOf(n)), n];\n if (st === 2) return null;\n state.set(n, 1);\n stack.push(n);\n for (const d of apps[n]?.depends_on ?? []) {\n const c = visit(d.app);\n if (c) return c;\n }\n stack.pop();\n state.set(n, 2);\n return null;\n };\n for (const n of Object.keys(apps)) {\n const c = visit(n);\n if (c) return c;\n }\n return null;\n}\n\n/**\n * A union entry that fails gives zod one `invalid_union` issue on the entry whose real reasons sit in its branches:\n * flatten them so the message names the field (`apps.w.depends_on.0.timeout`), not just the entry.\n */\nfunction flattenIssues(issues: z.ZodIssue[]): z.ZodIssue[] {\n return issues.flatMap((i) =>\n i.code === 'invalid_union'\n ? flattenIssues(i.unionErrors.flatMap((e) => e.issues))\n : [i]\n );\n}\n\n/** A name the manifest itself declares (never one every JavaScript object has, like `constructor`). */\nconst own = (o: object, k: string): boolean => Object.hasOwn(o, k);\n\n/**\n * An app's own log patterns (`errors` and `reloads` lists): each must compile, and none may repeat a group that ends in\n * a repeat, which backtracks for minutes on a line that almost matches. `field` names the list in the message.\n */\nfunction checkPatterns(\n problems: string[],\n field: string,\n patterns: string[]\n): void {\n for (const p of patterns) {\n try {\n new RegExp(p);\n } catch (e) {\n problems.push(\n `${field}: invalid pattern \"${p}\": ${(e as Error).message}`\n );\n continue;\n }\n if (repeatsARepeat(p))\n problems.push(\n `${field}: pattern \"${p}\" repeats a group that ends in a repeat (like (a+)+), which can run for minutes on a log line that almost matches; rewrite it without the nested repeat`\n );\n }\n}\n\n/** The error a template raised, as the manifest reports it: the field path first, the code by the kind of failure. */\nfunction templateError(field: string, e: unknown): McprocError {\n const t = e instanceof TemplateError ? e : null;\n const code =\n t?.kind === 'unknown'\n ? 'UNKNOWN_VAR'\n : t?.kind === 'cycle'\n ? 'VAR_CYCLE'\n : 'BAD_TEMPLATE';\n // a failure inside one var's template is reported under that var: vars.<name>\n const where = t?.varName ? `${field}.${t.varName}` : field;\n const msg = t?.varName\n ? t.message.slice(t.varName.length + 2)\n : (e as Error).message;\n return new McprocError(code, `${where}: ${msg}`, {\n hint:\n code === 'UNKNOWN_VAR'\n ? 'Declare the var under vars: in the manifest; the override may only set declared vars.'\n : code === 'VAR_CYCLE'\n ? 'Break the cycle between the named vars: one of them must not depend on the others.'\n : \"Templates are {{ expr }} over var names with integer + - * / % and parentheses; write \\\\{{ for a literal {{ (a docker --format '{{.Names}}' in a run line needs it).\",\n });\n}\n\n/** Keys whose string values are never templates: structure, not configuration. */\nconst NO_TEMPLATE_KEYS = new Set([\n 'version',\n 'mcproc',\n 'project',\n 'profiles',\n 'vars',\n]);\n\n/**\n * Every string leaf of the raw manifest rendered with the resolved vars, except the structural keys; `port`/`ports`\n * that rendered to digits become numbers so the schema can check them. Errors name the field path.\n */\nfunction interpolateRaw(raw: unknown, vars: Record<string, VarValue>): unknown {\n const walk = (v: unknown, p: string[]): unknown => {\n if (typeof v === 'string') {\n try {\n const r = renderTemplate(v, vars);\n const portLike =\n p[0] === 'apps' &&\n ((p.length === 3 && p[2] === 'port') ||\n (p.length === 4 && p[2] === 'ports'));\n if (portLike) {\n // a port: a number as rendered, or a string of digits; anything else cannot be a port\n if (typeof r === 'number') return r;\n if (typeof r === 'string' && /^\\d+$/.test(r)) return Number(r);\n throw new TemplateError(\n `must render to an integer, got ${JSON.stringify(r)}`,\n 'type'\n );\n }\n // every other field is a string in the schema: a whole-template number or boolean is written out\n return typeof r === 'string' ? r : String(r);\n } catch (e) {\n throw templateError(p.join('.') || '(root)', e);\n }\n }\n if (Array.isArray(v)) return v.map((x, i) => walk(x, [...p, String(i)]));\n if (v && typeof v === 'object') {\n const out: Record<string, unknown> = {};\n for (const [k, x] of Object.entries(v as Record<string, unknown>))\n out[k] =\n p.length === 0 && NO_TEMPLATE_KEYS.has(k) ? x : walk(x, [...p, k]);\n return out;\n }\n return v;\n };\n return walk(raw, []);\n}\n\n/** Parses manifest text: renders its `{{ }}` templates with the vars (the override's values win), then checks the result against the schema. */\nexport function parseManifest(\n text: string,\n root: string,\n manifestPath: string,\n override: Override | null = null\n): Manifest {\n let raw: unknown;\n try {\n raw = parseYaml(text);\n } catch (e) {\n throw new McprocError(\n 'MANIFEST_INVALID',\n `YAML parse error in ${manifestPath}: ${(e as Error).message}`\n );\n }\n const top = (raw && typeof raw === 'object' ? raw : {}) as Record<\n string,\n unknown\n >;\n try {\n return checkManifest(raw, top, root, manifestPath, override);\n } catch (e) {\n throw upgradeHint(e, top.mcproc);\n }\n}\n\n/** An error from a manifest that a newer mcproc wrote says so: what it trips on may be newer than this build. */\nfunction upgradeHint(e: unknown, writtenBy: unknown): unknown {\n if (\n !(e instanceof McprocError) ||\n typeof writtenBy !== 'string' ||\n !VERSION_PATTERN.test(writtenBy) ||\n compareVersions(writtenBy, VERSION) <= 0\n )\n return e;\n const hint = `This manifest was written by mcproc ${writtenBy}, this is ${VERSION}: it may use what this build does not know yet. Upgrade mcproc.`;\n return new McprocError(e.code, e.message, {\n hint: e.hint ? `${hint} ${e.hint}` : hint,\n details: e.details,\n });\n}\n\n/** Everything parseManifest checks once the YAML has parsed: templates, the schema, the cross-field rules. */\nfunction checkManifest(\n raw: unknown,\n top: Record<string, unknown>,\n root: string,\n manifestPath: string,\n override: Override | null\n): Manifest {\n // project and vars come first: everything else is rendered with them\n if (typeof top.project === 'string' && /\\{\\{/.test(top.project))\n throw new McprocError('BAD_TEMPLATE', 'project: must not be a template', {\n hint: 'Set the project slug in the override file instead.',\n });\n // every checkout of a repository shares one base slug: a worktree takes the default from its main checkout's path\n const base_project =\n typeof top.project === 'string'\n ? top.project\n : defaultProject(override?.repo ?? root);\n const project = override?.project ?? base_project;\n const declaredRes = z.record(varName, varValue).safeParse(top.vars ?? {});\n if (!declaredRes.success)\n throw new McprocError(\n 'MANIFEST_INVALID',\n `Invalid manifest ${manifestPath}:\\n vars: ${declaredRes.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; ')}`\n );\n let resolved: Record<string, VarValue>;\n try {\n resolved = resolveVars(\n declaredRes.data,\n override?.vars ?? {},\n {\n project,\n root,\n },\n override?.path\n );\n } catch (e) {\n throw templateError('vars', e);\n }\n const vars: VarInfo[] = Object.entries(resolved).map(([name, value]) => ({\n name,\n value,\n source:\n name === 'project' || name === 'root'\n ? 'built-in'\n : override && Object.hasOwn(override.vars, name)\n ? 'override'\n : 'manifest',\n }));\n const res = manifestSchema.safeParse(interpolateRaw(raw, resolved));\n if (!res.success) {\n const issues = flattenIssues(res.error.issues).map(\n (i) => `${i.path.join('.') || '(root)'}: ${i.message}`\n );\n throw new McprocError(\n 'MANIFEST_INVALID',\n `Invalid manifest ${manifestPath}:\\n ${issues.join('\\n ')}`,\n { details: issues }\n );\n }\n const m = res.data;\n const problems: string[] = [];\n if (Object.keys(m.apps).length === 0)\n problems.push('apps: at least one app is required');\n\n const apps: Record<string, App> = {};\n for (const [n, a] of Object.entries(m.apps)) {\n if (a.port !== undefined && a.ports !== undefined)\n problems.push(`apps.${n}: use either port or ports, not both`);\n const deps: Dep[] = a.depends_on.map((d) =>\n typeof d === 'string'\n ? {\n app: d,\n condition: 'started',\n timeoutMs: DEP_TIMEOUT_DEFAULT_S * 1000,\n }\n : { app: d.app, condition: d.condition, timeoutMs: d.timeout * 1000 }\n );\n for (const d of deps) {\n if (!own(m.apps, d.app)) {\n problems.push(`apps.${n}.depends_on: unknown app \"${d.app}\"`);\n continue;\n }\n const dep = m.apps[d.app];\n if (d.condition === 'completed' && dep.kind !== 'task')\n problems.push(\n `apps.${n}.depends_on: \"${d.app}\" must be kind: task for condition completed (it is ${dep.kind})`\n );\n if (\n d.condition === 'ready' &&\n dep.port === undefined &&\n (dep.ports ?? []).length === 0 &&\n dep.url === undefined\n )\n problems.push(\n `apps.${n}.depends_on: \"${d.app}\" declares no port or url, so ready cannot be observed`\n );\n }\n if (a.url_check !== undefined && a.url === undefined)\n problems.push(\n `apps.${n}.url_check: there is no url to check; declare url or drop url_check`\n );\n if (a.kind === 'task' && a.autorestart === true)\n problems.push(\n `apps.${n}.autorestart: a task runs once; drop autorestart or use kind: worker`\n );\n // stop, delete, logs and ports act on one pm2 process per app: settings that start several would leave the rest running\n const instances = (a.pm2 as Record<string, unknown>).instances;\n if (instances !== undefined && instances !== 1)\n problems.push(\n `apps.${n}.pm2.instances: mcproc runs one process per app (stop and delete act on one); remove it or set 1`\n );\n const mode = (a.pm2 as Record<string, unknown>).exec_mode;\n if (mode !== undefined && mode !== 'fork' && mode !== 'fork_mode')\n problems.push(\n `apps.${n}.pm2.exec_mode: only fork mode (one process per app); cluster mode is not supported`\n );\n for (const k of PROTECTED_PM2_KEYS)\n if (k in a.pm2)\n problems.push(\n `apps.${n}.pm2.${k}: managed by mcproc, cannot be overridden`\n );\n const errors: ErrorSettings | null =\n a.errors === false\n ? null\n : {\n match: a.errors?.match ?? [],\n ignore: a.errors?.ignore ?? [],\n context: a.errors?.context ?? [3, 5],\n stderr: a.errors?.stderr ?? false,\n defaults: a.errors?.defaults ?? true,\n };\n const reloads: ReloadSettings | null =\n a.reloads === false\n ? null\n : {\n match: a.reloads?.match ?? [],\n ignore: a.reloads?.ignore ?? [],\n defaults: a.reloads?.defaults ?? true,\n };\n for (const [field, s] of [\n ['errors', errors],\n ['reloads', reloads],\n ] as const)\n for (const k of ['match', 'ignore'] as const)\n checkPatterns(problems, `apps.${n}.${field}.${k}`, s?.[k] ?? []);\n let memory_mib: number | null = null;\n if (a.memory !== undefined)\n try {\n memory_mib = parseSizeMib(a.memory);\n } catch (e) {\n problems.push(`apps.${n}.memory: ${(e as Error).message}`);\n }\n apps[n] = {\n name: n,\n description: a.description,\n kind: a.kind,\n run: a.run,\n cwd: a.cwd,\n env: stringifyEnv(a.env),\n memory_mib,\n containers: a.containers,\n ports: a.ports ?? (a.port !== undefined ? [a.port] : []),\n url: a.url ?? null,\n url_check: a.url_check ?? 'auto',\n watch: a.watch,\n watch_delay: a.watch_delay ?? (a.watch ? 1000 : undefined),\n ignore_watch: a.ignore_watch,\n depends_on: deps,\n autorestart: a.autorestart ?? a.kind !== 'task',\n pm2: a.pm2,\n host: a.host ?? null,\n errors,\n reloads,\n };\n }\n const cycle = findCycle(apps);\n if (cycle) problems.push(`apps: depends_on cycle: ${cycle.join(' -> ')}`);\n\n if (own(m.apps, 'all'))\n problems.push('apps.all: reserved, the built-in profile of every app');\n if (own(m.profiles, 'all'))\n problems.push('profiles.all: reserved, the built-in profile of every app');\n for (const p of Object.keys(m.profiles))\n if (own(m.apps, p))\n problems.push(\n `profiles.${p}: an app has this name, so a target \"${p}\" would mean both; rename one`\n );\n for (const [p, list] of Object.entries(m.profiles))\n for (const a of list)\n if (!own(m.apps, a)) problems.push(`profiles.${p}: unknown app \"${a}\"`);\n\n const hosts: Record<string, Host> = {};\n for (const [h, hv] of Object.entries(m.hosts)) {\n const local = h === 'local';\n if (local && (hv.ssh || hv.docker || hv.cwd))\n problems.push(\n 'hosts.local: ssh, docker and cwd are not allowed on the local host'\n );\n if (!local && !hv.ssh && !hv.docker)\n problems.push(`hosts.${h}: needs ssh or docker (or both)`);\n if (!local && !hv.cwd)\n problems.push(\n `hosts.${h}: cwd (the project root on that host) is required`\n );\n if (hv.ssh?.startsWith('-'))\n problems.push(`hosts.${h}.ssh: must not start with \"-\"`);\n for (const a of hv.ssh_args)\n if (/[\\n\\r]/.test(a))\n problems.push(`hosts.${h}.ssh_args: newlines are not allowed`);\n for (const k of ['cwd', 'runtime', 'pm2_home'] as const) {\n const v = hv[k];\n if (v !== undefined && !v.startsWith('/'))\n problems.push(\n `hosts.${h}.${k}: must be an absolute path on that host (\"~\" and relative paths are not expanded)`\n );\n }\n hosts[h] = {\n name: h,\n local,\n ssh: hv.ssh,\n ssh_args: hv.ssh_args,\n docker: hv.docker,\n cwd: local ? root : (hv.cwd ?? root),\n readonly: hv.readonly,\n shell: parseShell(hv.shell),\n pm2: hv.pm2,\n pm2_home: hv.pm2_home,\n runtime: hv.runtime,\n env: stringifyEnv(hv.env),\n };\n }\n if (!hosts.local)\n hosts.local = {\n name: 'local',\n local: true,\n ssh_args: [],\n cwd: root,\n readonly: false,\n shell: parseShell(DEFAULT_SHELL),\n env: {},\n };\n for (const a of Object.values(apps)) {\n if (a.host !== null && !own(hosts, a.host))\n problems.push(\n `apps.${a.name}.host: unknown host \"${a.host}\" (declared: ${Object.keys(hosts).join(', ')})`\n );\n }\n\n let reserve: Resources['reserve'] = {\n kind: 'mib',\n mib: RESERVE_DEFAULT_MIB,\n };\n let margin = MARGIN_DEFAULT;\n if (m.resources.reserve !== undefined)\n try {\n reserve = m.resources.reserve.trim().endsWith('%')\n ? { kind: 'percent', ratio: parsePercent(m.resources.reserve) }\n : { kind: 'mib', mib: parseSizeMib(m.resources.reserve) };\n } catch (e) {\n problems.push(`resources.reserve: ${(e as Error).message}`);\n }\n if (m.resources.margin !== undefined)\n try {\n margin = parsePercent(m.resources.margin);\n } catch (e) {\n problems.push(`resources.margin: ${(e as Error).message}`);\n }\n const resources: Resources = {\n reserve,\n margin,\n settle: m.resources.settle ?? SETTLE_DEFAULT_S,\n };\n const worktree: WorktreeSettings = {\n dir: m.worktree.dir ?? null,\n copy: m.worktree.copy,\n link: m.worktree.link,\n install: m.worktree.install ?? null,\n slots: m.worktree.slots,\n };\n const exec: ExecSettings = { env: stringifyEnv(m.exec.env) };\n const slotVar = resolved.slot;\n const slot = typeof slotVar === 'number' ? slotVar : null;\n\n if (problems.length)\n throw new McprocError(\n 'MANIFEST_INVALID',\n `Invalid manifest ${manifestPath}:\\n ${problems.join('\\n ')}`,\n { details: problems }\n );\n return {\n root,\n path: manifestPath,\n mcproc: m.mcproc ?? null,\n project,\n base_project,\n vars,\n override: override?.path ?? null,\n repo: override?.repo ?? root,\n slot,\n apps,\n profiles: m.profiles,\n hosts,\n resources,\n worktree,\n exec,\n };\n}\n\n/**\n * The part of the manifest that runs on one host: apps bound to it, plus the unbound apps when it is the fallback host\n * (the host the command names, local when it names none). Dependencies and profile members that run elsewhere are\n * dropped, so everything that works on one manifest (ecosystem, ports, targets) works on this view unchanged.\n */\nexport function scopeManifest(\n m: Manifest,\n host: string,\n fallback: string\n): Manifest {\n const apps = Object.fromEntries(\n Object.values(m.apps)\n .filter((a) => (a.host ?? fallback) === host)\n .map((a) => [a.name, a])\n );\n for (const [n, a] of Object.entries(apps)) {\n const deps = a.depends_on.filter((d) => d.app in apps);\n if (deps.length !== a.depends_on.length)\n apps[n] = { ...a, depends_on: deps };\n }\n const profiles = Object.fromEntries(\n Object.entries(m.profiles).map(([p, list]) => [\n p,\n list.filter((a) => a in apps),\n ])\n );\n return { ...m, apps, profiles };\n}\n\nexport function loadManifest(startDir: string): Manifest {\n const found = findManifestPath(startDir);\n if (!found) {\n throw new McprocError(\n 'MANIFEST_NOT_FOUND',\n `No ${MANIFEST_REL} found in ${path.resolve(startDir)} or its parents`,\n {\n hint: \"Run init (MCP tool or `mcproc init`) to create a draft from the project's scripts, fill in a description per app, then verify with ls.\",\n }\n );\n }\n return parseManifest(\n fs.readFileSync(found.path, 'utf8'),\n found.root,\n found.path,\n loadOverride(found.root)\n );\n}\n","import vm from 'node:vm';\nimport type { ErrorSettings } from '../manifest.js';\nimport { McprocError } from '../errors.js';\n\nexport type Stream = 'out' | 'err';\nexport type IncidentKind = 'error' | 'crashed' | 'restarted' | 'reloaded';\n/**\n * One error occurrence with its context, a process event, or an app's in-process reloads of one poll; `count` > 1 when\n * the same error repeated within one poll (for `reloaded`, how many reloads).\n */\nexport interface Incident {\n app: string;\n host: string;\n kind: IncidentKind;\n stream: Stream;\n time: string | null;\n first_time: string | null;\n count: number;\n line: string;\n before: string[];\n after: string[];\n fingerprint: string;\n}\n/** The built-in markers in force, and the app's own patterns as written (they run under a time budget, see ownHits). */\nexport interface Rules {\n starts: RegExp[];\n match: string[];\n ignore: string[];\n context: [number, number];\n stderr: boolean;\n budgetMs: number;\n}\n/** The lines of one stream read in one poll; the first `contextOnly` precede the new part and are context, never a start. */\nexport interface StreamLines {\n stream: Stream;\n lines: string[];\n contextOnly: number;\n}\n\n/** The usual ways programs report an error (matched against the text after pm2's stamp). Lowercase \"error\" alone is not one. */\nexport const BUILTIN_MARKERS: RegExp[] = [\n /\\blevel=(?:error|fatal|crit(?:ical)?)\\b/i,\n /\"level\"\\s*:\\s*(?:\"(?:error|fatal)\"|(?:50|60)\\b)/i,\n /(?:^|[\\s[(])(?:ERROR|FATAL|CRITICAL)(?:[\\s\\]):]|$)/,\n /\\b(?:[A-Z][A-Za-z0-9]*)?(?:Error|Exception)\\b(?::|\\s+at\\b|$)/,\n /^Traceback \\(most recent call last\\)/,\n /^panic: /,\n /^thread '.*' panicked at/,\n /\\bUnhandled(?:PromiseRejection|Rejection)?\\b|\\buncaughtException\\b/,\n /\\bE(?:CONNREFUSED|ADDRINUSE|ACCES|NOENT|PIPE|CONNRESET|TIMEDOUT)\\b/,\n];\n/** Lines that continue a stack trace: folded into the incident without using up its after-context. */\nconst STACK: RegExp[] = [\n /^\\s+at\\s/,\n /^\\s+File \"/,\n /^\\s{2,}\\S/,\n /^Caused by:/,\n /^\\s*\\.\\.\\. \\d+ more/,\n /^\\s*\\^+\\s*$/,\n /^goroutine \\d+/,\n];\nconst PM2_STAMP = /^(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{3})?): /; // seconds, or milliseconds\nexport const MAX_FOLD = 30;\nexport const MAX_AFTER = 60;\nexport const MAX_LINE = 2000;\n\n/** How long an app's own patterns may take on one file's lines before the poll of that app stops with an error naming them. */\nexport const MATCH_BUDGET_MS = 2000;\n\nexport function compileRules(\n s: ErrorSettings,\n context?: [number, number],\n budgetMs = MATCH_BUDGET_MS\n): Rules {\n return {\n starts: s.defaults ? BUILTIN_MARKERS : [],\n match: s.match,\n ignore: s.ignore,\n context: context ?? s.context,\n stderr: s.stderr,\n budgetMs,\n };\n}\n\n// An app's own patterns run in a separate context with a time limit, which interrupts a pattern that backtracks without end.\nconst OWN = new vm.Script(\n 'const m = match.map((p) => new RegExp(p)); const g = ignore.map((p) => new RegExp(p)); out = texts.map((t) => (g.some((re) => re.test(t)) ? 2 : m.some((re) => re.test(t)) ? 1 : 0));'\n);\n\n/**\n * Runs a caller's own patterns over texts in a separate context with a time limit, which interrupts a pattern that\n * backtracks without end. Per text: 2 = an ignore pattern matched, 1 = a match pattern matched, 0 = neither; null when\n * there is nothing to run. On the limit it throws what `onTimeout` builds, so each caller names its own patterns.\n */\nexport function runOwnPatterns(\n texts: string[],\n match: string[],\n ignore: string[],\n budgetMs: number,\n onTimeout: () => Error\n): number[] | null {\n if (texts.length === 0 || (match.length === 0 && ignore.length === 0))\n return null;\n const ctx = vm.createContext({ texts, match, ignore, out: null });\n try {\n OWN.runInContext(ctx, { timeout: budgetMs });\n } catch (e) {\n if ((e as { code?: string }).code !== 'ERR_SCRIPT_EXECUTION_TIMEOUT')\n throw e;\n throw onTimeout();\n }\n return Array.from(ctx.out as number[]);\n}\n\n/** Per line: 2 when one of the app's `ignore` patterns matches, 1 when one of its `match` patterns does, 0 otherwise. */\nfunction ownHits(texts: string[], rules: Rules, app: string): number[] | null {\n return runOwnPatterns(\n texts,\n rules.match,\n rules.ignore,\n rules.budgetMs,\n () =>\n new McprocError(\n 'TIMEOUT',\n `the errors patterns of ${app} ran over ${rules.budgetMs} ms on its log: one of them backtracks without end on these lines`,\n {\n hint: `Simplify apps.${app}.errors.match/ignore (a repeat inside a repeat, or alternatives that match the same text); this app's incidents wait until then.`,\n }\n )\n );\n}\n\nexport const stampOf = (line: string): string | null =>\n PM2_STAMP.exec(line)?.[1] ?? null;\n/** The line without pm2's leading time stamp (the rest of it is what patterns are matched against). */\nexport const bodyOf = (line: string): string => line.replace(PM2_STAMP, '');\n/** A line as an answer reports it: at most MAX_LINE characters, so one huge line cannot swell the answer. */\nexport const cut = (s: string): string =>\n s.length > MAX_LINE ? `${s.slice(0, MAX_LINE - 1)}…` : s;\n/** A context line or a stack frame: at most CONTEXT_LINE characters, as it only frames the incident's own line. */\nexport const CONTEXT_LINE = 300;\nexport const cutContext = (s: string): string =>\n s.length > CONTEXT_LINE ? `${s.slice(0, CONTEXT_LINE - 1)}…` : s;\n/** What patterns are matched against: the line without its stamp, as far as the output shows it (a huge line stays cheap). */\nexport const searched = (line: string): string =>\n bodyOf(line).slice(0, MAX_LINE);\n\n/**\n * A group repeated without bound whose content can end in an unbounded repeat — `(a+)+`, `(\\w+\\s*)*`, `(a+b?)+`, `(.*)+` —\n * backtracks exponentially on a line that almost matches. Such a pattern is refused when the manifest is loaded, before a\n * poll has to stop it (the time budget of ownHits is the bound for what this check cannot see, like `(a|a)*`).\n * `(\\d+\\.)+` passes: its repeat ends in a literal.\n */\nexport function repeatsARepeat(p: string): boolean {\n const stack = [{ ends: false, any: false }]; // per open group: does the current alternative end in an unbounded repeat; did any earlier one\n // a quantifier at j: its length, whether it repeats without bound, whether it may match nothing (then what came before can still end the text)\n const quant = (\n j: number\n ): { len: number; unbounded: boolean; nullable: boolean } => {\n const lazy = p[j + 1] === '?' ? 2 : 1;\n if (p[j] === '*') return { len: lazy, unbounded: true, nullable: true };\n if (p[j] === '+') return { len: lazy, unbounded: true, nullable: false };\n if (p[j] === '?') return { len: lazy, unbounded: false, nullable: true };\n const m = /^\\{(\\d+)(,(\\d*))?\\}\\??/.exec(p.slice(j));\n return m\n ? {\n len: m[0].length,\n unbounded: m[2] !== undefined && m[3] === '',\n nullable: Number(m[1]) === 0,\n }\n : { len: 0, unbounded: false, nullable: false };\n };\n let i = 0;\n while (i < p.length) {\n const top = stack[stack.length - 1];\n const c = p[i];\n if (c === '(') {\n stack.push({ ends: false, any: false });\n if (p[i + 1] !== '?') i += 1;\n else if (p[i + 2] === '<' && p[i + 3] !== '=' && p[i + 3] !== '!')\n i = p.indexOf('>', i) + 1 || p.length; // (?<name>\n else i += p[i + 2] === '<' ? 4 : 3; // (?: (?= (?! (?<= (?<!\n continue;\n }\n if (c === ')') {\n const g = stack.length > 1 ? stack.pop()! : { ends: false, any: false };\n const q = quant(i + 1);\n const inner = g.any || g.ends;\n if (q.unbounded && inner) return true;\n const parent = stack[stack.length - 1];\n parent.ends = q.nullable\n ? parent.ends || q.unbounded || inner\n : q.unbounded || inner;\n i += 1 + q.len;\n continue;\n }\n if (c === '|') {\n top.any ||= top.ends;\n top.ends = false;\n i++;\n continue;\n }\n if (c === '^' || c === '$') {\n i++;\n continue;\n } // zero width: what came before still ends the text\n let len = 1;\n if (c === '\\\\') len = 2;\n else if (c === '[') {\n let j = i + 1;\n while (j < p.length && p[j] !== ']') j += p[j] === '\\\\' ? 2 : 1;\n len = j + 1 - i;\n }\n const q = quant(i + len);\n top.ends = q.nullable ? top.ends || q.unbounded : q.unbounded;\n i += len + q.len;\n }\n return false;\n}\n\nfunction timeAt(lines: string[], i: number): string | null {\n for (let k = i; k >= 0; k--) {\n const t = stampOf(lines[k]);\n if (t) return t;\n }\n return null;\n}\n\n/** What makes two occurrences the same error: the text without the stamp, with numbers, ids, hex, paths and quoted strings masked. */\nexport function fingerprint(line: string): string {\n return bodyOf(line)\n .replace(/\"[^\"]*\"|'[^']*'/g, '\"…\"')\n .replace(\n /\\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\b/gi,\n '<id>'\n )\n .replace(/(?:\\/[\\w.@-]+)+/g, '<path>')\n .replace(/\\b0x[0-9a-f]+\\b|\\b[0-9a-f]{8,}\\b/gi, '<hex>')\n .replace(/\\d+/g, '<n>')\n .trim();\n}\n\nexport function detect(\n src: StreamLines,\n rules: Rules,\n who: { app: string; host: string }\n): Incident[] {\n const { lines, contextOnly, stream } = src;\n const [nBefore, nAfter] = rules.context;\n const texts = lines.map(searched);\n const first = Math.max(0, contextOnly);\n const own = ownHits(texts.slice(first), rules, who.app); // only lines that may start an incident: context before the new part is never searched\n\n const isStack = (k: number): boolean => STACK.some((re) => re.test(texts[k]));\n const isStart = (k: number): boolean => {\n if (own?.[k - first] === 2) return false;\n return (\n (rules.stderr && stream === 'err') ||\n own?.[k - first] === 1 ||\n rules.starts.some((re) => re.test(texts[k]))\n );\n };\n const out: Incident[] = [];\n let i = first;\n while (i < lines.length) {\n if (!isStart(i)) {\n i++;\n continue;\n }\n const start = i;\n const after: string[] = [];\n let j = i + 1;\n let tail = 0; // after-context lines since the last start or frame\n let folded = 0; // frames folded since the last start\n let dropped = 0; // frames beyond MAX_FOLD\n const flush = () => {\n if (dropped) {\n after.push(`… ${dropped} more`);\n dropped = 0;\n }\n };\n while (j < lines.length && after.length < MAX_AFTER) {\n const l = lines[j];\n if (isStack(j)) {\n if (folded < MAX_FOLD) {\n after.push(cutContext(l));\n folded++;\n } else dropped++;\n tail = 0;\n j++;\n continue;\n }\n if (tail >= nAfter) break; // past the after-context: the next error starts its own incident\n if (isStart(j)) {\n flush();\n after.push(cutContext(l));\n folded = 0;\n tail = 0;\n j++;\n continue;\n } // inside it: one incident\n flush();\n after.push(cutContext(l));\n tail++;\n j++;\n }\n flush();\n const time = timeAt(lines, start);\n out.push({\n ...who,\n kind: 'error',\n stream,\n time,\n first_time: time,\n count: 1,\n line: cut(lines[start]),\n before: lines.slice(Math.max(0, start - nBefore), start).map(cutContext),\n after,\n fingerprint: fingerprint(cut(lines[start])), // bounded like the line itself\n });\n i = j;\n }\n return out;\n}\n\n/**\n * The same error of one app (same kind and fingerprint) collapses into its last occurrence, counted, with the first time\n * kept. Last and first go by time (stdout and stderr are read one after the other); unstamped incidents count as oldest.\n */\nexport function collapse(incidents: Incident[]): Incident[] {\n const by = new Map<string, Incident>();\n for (const inc of [...incidents].sort((a, b) =>\n (a.time ?? '').localeCompare(b.time ?? '')\n )) {\n const key = [inc.host, inc.app, inc.kind, inc.fingerprint].join('\\u0000');\n const prev = by.get(key);\n if (!prev) {\n by.set(key, inc);\n continue;\n }\n by.delete(key); // re-inserted: the order follows the last occurrence\n by.set(key, {\n ...inc,\n count: prev.count + inc.count,\n first_time: prev.first_time ?? inc.first_time,\n });\n }\n return [...by.values()];\n}\n","/** What a project, app, profile or host name may look like. */\nexport const NAME_RE = /^[a-z0-9][a-z0-9._-]*$/;\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { parse as parseYaml, stringify as toYaml } from 'yaml';\nimport { z } from 'zod';\nimport { McprocError } from './errors.js';\nimport { NAME_RE } from './names.js';\nimport type { VarValue } from './template.js';\n\nexport const OVERRIDE_REL = path.join('.mcproc', 'mcproc.local.yaml');\n\n/**\n * The per-checkout override: a project slug and var values, nothing else that the manifest decides; a main checkout's\n * may also name machine-local copy and link extras for the worktrees made from it, so they never enter the repository.\n */\nexport interface Override {\n path: string;\n project?: string;\n /** the main checkout of the repository, recorded by worktree add so the slot registry can be found from a worktree */\n repo?: string;\n vars: Record<string, VarValue>;\n /** extra `worktree.copy` and `worktree.link` entries for new worktrees, beside the manifest's */\n worktree?: { copy: string[]; link: string[] };\n}\n\nconst overrideSchema = z\n .object({\n project: z\n .string()\n .regex(NAME_RE, 'must match ^[a-z0-9][a-z0-9._-]*$')\n .optional(),\n repo: z.string().min(1).optional(),\n // a key left empty in YAML parses as null: treat it as no vars\n vars: z.preprocess(\n (v) => (v === null || v === undefined ? {} : v),\n z.record(z.union([z.string(), z.number(), z.boolean()]))\n ),\n // an empty `worktree:` key is no extras\n worktree: z.preprocess(\n (v) => (v === null ? undefined : v),\n z\n .object({\n copy: z.array(z.string().min(1)).default([]),\n link: z.array(z.string().min(1)).default([]),\n })\n .strict()\n .optional()\n ),\n })\n .strict();\n\n/** Parses the text of an override file; refuses unknown keys and a project slug that is not a valid name. */\nexport function parseOverride(text: string, overridePath: string): Override {\n let raw: unknown;\n try {\n raw = parseYaml(text) ?? {};\n } catch (e) {\n throw new McprocError(\n 'MANIFEST_INVALID',\n `YAML parse error in ${overridePath}: ${(e as Error).message}`\n );\n }\n const res = overrideSchema.safeParse(raw);\n if (!res.success)\n throw new McprocError(\n 'MANIFEST_INVALID',\n `Invalid override ${overridePath}:\\n ${res.error.issues.map((i) => `${i.path.join('.') || '(root)'}: ${i.message}`).join('\\n ')}`,\n {\n hint: 'The override may set only project, repo, vars and worktree (copy, link).',\n }\n );\n return {\n path: overridePath,\n project: res.data.project,\n ...(res.data.repo !== undefined ? { repo: res.data.repo } : {}),\n vars: res.data.vars,\n ...(res.data.worktree !== undefined ? { worktree: res.data.worktree } : {}),\n };\n}\n\n/** The override next to the manifest of `root`, or null when the checkout has none. */\nexport function loadOverride(root: string): Override | null {\n const p = path.join(root, OVERRIDE_REL);\n if (!fs.existsSync(p)) return null;\n return parseOverride(fs.readFileSync(p, 'utf8'), p);\n}\n\n/** Writes the override of a checkout (worktree add), replacing any earlier one; returns its path. */\nexport function writeOverride(\n root: string,\n o: { project: string; repo?: string; vars?: Record<string, VarValue> }\n): string {\n const p = path.join(root, OVERRIDE_REL);\n const body: Record<string, unknown> = { project: o.project };\n if (o.repo) body.repo = o.repo;\n if (o.vars && Object.keys(o.vars).length) body.vars = o.vars;\n fs.mkdirSync(path.dirname(p), { recursive: true });\n fs.writeFileSync(\n p,\n `# Written by mcproc worktree add: this checkout's project slug and vars.\\n${toYaml(body)}`\n );\n return p;\n}\n","/** A size as the manifest writes it (`512M`, `1.5G`, `100K`, a bare number of MiB), in MiB, rounded up; a decimal without a unit is refused so `1.5` cannot mean 1.5 MiB by accident. */\nexport function parseSizeMib(s: string): number {\n const m = /^\\s*(\\d+(?:\\.\\d+)?)\\s*([kmgtKMGT])?(?:i?[bB])?\\s*$/.exec(s);\n if (!m || (m[1].includes('.') && !m[2]))\n throw new Error(\n `not a size: \"${s}\" (use <n>K, <n>M, <n>G or a whole number of MiB)`\n );\n const n = Number(m[1]);\n const unit = (m[2] ?? 'M').toUpperCase();\n const mib =\n unit === 'K'\n ? n / 1024\n : unit === 'G'\n ? n * 1024\n : unit === 'T'\n ? n * 1024 * 1024\n : n;\n return Math.max(0, Math.ceil(mib));\n}\n\n/** A percent as the manifest writes it (`10%`, `12.5 %`), as a ratio in [0, 1]. */\nexport function parsePercent(s: string): number {\n const m = /^\\s*(\\d+(?:\\.\\d+)?)\\s*%\\s*$/.exec(s);\n if (!m) throw new Error(`not a percent: \"${s}\" (use <n>%)`);\n const n = Number(m[1]);\n if (n > 100) throw new Error(`not a percent: \"${s}\" is above 100%`);\n return n / 100;\n}\n\n/** MiB for a human: `512M` under a GiB, `1.5G` from there, one decimal. */\nexport function fmtMib(mib: number): string {\n if (mib < 1024) return `${Math.round(mib)}M`;\n return `${(mib / 1024).toFixed(1)}G`;\n}\n","export type VarValue = string | number | boolean;\n\n/** A template that cannot be rendered; the manifest wraps it into BAD_TEMPLATE / VAR_CYCLE / UNKNOWN_VAR with the field path. */\nexport class TemplateError extends Error {\n constructor(\n message: string,\n readonly kind: 'syntax' | 'unknown' | 'cycle' | 'type' = 'syntax',\n /** the var whose template failed, when the failure came from rendering one var */\n readonly varName?: string\n ) {\n super(message);\n this.name = 'TemplateError';\n }\n}\n\ntype Tok =\n | { t: 'num'; v: number }\n | { t: 'name'; v: string }\n | { t: 'op'; v: '+' | '-' | '*' | '/' | '%' | '(' | ')' }\n | { t: 'end' };\n\nfunction tokenize(expr: string): Tok[] {\n const out: Tok[] = [];\n let i = 0;\n while (i < expr.length) {\n const c = expr[i];\n if (/\\s/.test(c)) {\n i++;\n continue;\n }\n if (/[0-9]/.test(c)) {\n let j = i;\n while (j < expr.length && /[0-9]/.test(expr[j])) j++;\n out.push({ t: 'num', v: Number(expr.slice(i, j)) });\n i = j;\n continue;\n }\n if (/[a-z_]/i.test(c)) {\n let j = i;\n while (j < expr.length && /[a-z0-9_]/i.test(expr[j])) j++;\n out.push({ t: 'name', v: expr.slice(i, j) });\n i = j;\n continue;\n }\n if ('+-*/%()'.includes(c)) {\n out.push({ t: 'op', v: c as Extract<Tok, { t: 'op' }>['v'] });\n i++;\n continue;\n }\n throw new TemplateError(`unexpected \"${c}\" in \"${expr}\"`);\n }\n out.push({ t: 'end' });\n return out;\n}\n\n/** Integer arithmetic over var names; a bare name is its value whatever the type, anything else needs numbers. */\nexport function evaluate(\n expr: string,\n vars: Record<string, VarValue>\n): VarValue {\n const toks = tokenize(expr);\n let k = 0;\n const peek = () => toks[k];\n const next = () => toks[k++];\n const num = (v: VarValue, what: string): number => {\n if (typeof v !== 'number')\n throw new TemplateError(\n `${what} is not a number (${JSON.stringify(v)}) in \"${expr}\"`,\n 'type'\n );\n return v;\n };\n const lookup = (name: string): VarValue => {\n if (!Object.hasOwn(vars, name))\n throw new TemplateError(`unknown var \"${name}\" in \"${expr}\"`, 'unknown');\n return vars[name];\n };\n const factor = (): VarValue => {\n const t = next();\n if (t.t === 'num') return t.v;\n if (t.t === 'name') return lookup(t.v);\n if (t.t === 'op' && t.v === '-') return -num(factor(), 'operand');\n if (t.t === 'op' && t.v === '(') {\n const v = sum();\n const close = next();\n if (close.t !== 'op' || close.v !== ')')\n throw new TemplateError(`missing \")\" in \"${expr}\"`);\n return v;\n }\n throw new TemplateError(`unexpected end or token in \"${expr}\"`);\n };\n const term = (): VarValue => {\n let v = factor();\n for (;;) {\n const t = peek();\n if (t.t !== 'op' || !'*/%'.includes(t.v)) return v;\n next();\n const a = num(v, 'operand');\n const b = num(factor(), 'operand');\n if (t.v === '*') v = a * b;\n else {\n if (b === 0) throw new TemplateError(`division by zero in \"${expr}\"`);\n v = t.v === '/' ? Math.trunc(a / b) : a % b;\n }\n }\n };\n const sum = (): VarValue => {\n let v = term();\n for (;;) {\n const t = peek();\n if (t.t !== 'op' || !'+-'.includes(t.v)) return v;\n next();\n const a = num(v, 'operand');\n const b = num(term(), 'operand');\n v = t.v === '+' ? a + b : a - b;\n }\n };\n const v = sum();\n if (peek().t !== 'end')\n throw new TemplateError(`unexpected trailing input in \"${expr}\"`);\n return v;\n}\n\nconst OPEN = /(\\\\)?\\{\\{/g;\n\n/** Whether a string holds a template (an escaped `\\{{` is not one). */\nexport function hasTemplate(s: string): boolean {\n for (const m of s.matchAll(OPEN)) if (!m[1]) return true;\n return false;\n}\n\n/**\n * The string with every `{{ expr }}` rendered; a template that is the whole string returns the value itself (so a\n * number stays a number); `\\{{` becomes a literal `{{`.\n */\nexport function renderTemplate(\n s: string,\n vars: Record<string, VarValue>\n): VarValue {\n const whole = /^\\s*\\{\\{([^}]*)\\}\\}\\s*$/.exec(s);\n if (whole && !s.includes('\\\\{{')) return evaluate(whole[1], vars);\n let out = '';\n let i = 0;\n while (i < s.length) {\n if (s.startsWith('\\\\{{', i)) {\n out += '{{';\n i += 3;\n continue;\n }\n if (s.startsWith('{{', i)) {\n const end = s.indexOf('}}', i + 2);\n if (end < 0) throw new TemplateError(`unclosed template in \"${s}\"`);\n out += String(evaluate(s.slice(i + 2, end), vars));\n i = end + 2;\n continue;\n }\n out += s[i++];\n }\n return out;\n}\n\n/** The names a template value depends on (its bare identifiers; an escaped `\\{{` is text), for ordering the resolution. */\nfunction namesIn(v: VarValue): string[] {\n if (typeof v !== 'string') return [];\n const out = new Set<string>();\n for (const m of v.matchAll(/(?<!\\\\)\\{\\{([^}]*)\\}\\}/g))\n for (const n of m[1].matchAll(/[a-z_][a-z0-9_]*/gi)) out.add(n[0]);\n return [...out];\n}\n\n/**\n * Declared defaults, overridden per checkout, over the built-ins (`project`, `root`): each var rendered once its\n * dependencies are, so a port can be `{{ 8000 + slot * 100 }}` with `slot` set by the override.\n */\nexport function resolveVars(\n declared: Record<string, VarValue>,\n overrides: Record<string, VarValue>,\n builtins: Record<string, VarValue>,\n overridePath?: string\n): Record<string, VarValue> {\n for (const n of Object.keys(declared))\n if (Object.hasOwn(builtins, n))\n throw new TemplateError(\n `\"${n}\" is a built-in var and cannot be declared`\n );\n for (const n of Object.keys(overrides))\n if (!Object.hasOwn(declared, n))\n throw new TemplateError(\n `undeclared var \"${n}\" in the override${overridePath ? ` ${overridePath}` : ''} (declared: ${Object.keys(declared).join(', ') || 'none'})`,\n 'unknown'\n );\n const raw: Record<string, VarValue> = { ...declared, ...overrides };\n const done: Record<string, VarValue> = { ...builtins };\n const visiting: string[] = [];\n const visit = (n: string): void => {\n if (Object.hasOwn(done, n)) return;\n if (visiting.includes(n))\n throw new TemplateError(\n `cycle: ${[...visiting.slice(visiting.indexOf(n)), n].join(' -> ')}`,\n 'cycle'\n );\n visiting.push(n);\n for (const d of namesIn(raw[n])) if (Object.hasOwn(raw, d)) visit(d);\n visiting.pop();\n const v = raw[n];\n if (typeof v !== 'string') {\n done[n] = v;\n return;\n }\n try {\n done[n] = renderTemplate(v, done);\n } catch (e) {\n if (e instanceof TemplateError)\n throw new TemplateError(`${n}: ${e.message}`, e.kind, n);\n throw e;\n }\n };\n for (const n of Object.keys(raw)) visit(n);\n return done;\n}\n","import http from 'node:http';\nimport https from 'node:https';\nimport { isIP } from 'node:net';\nimport type { UrlCheckMode } from './manifest.js';\nimport { urlName } from '../shell/snippets.js';\n\n/** Why nothing answered a url: the short word `ls` shows after `✗ down`. */\nexport type UrlFail =\n | 'refused'\n | 'not resolved'\n | 'timeout'\n | 'tls'\n | 'reset'\n | 'no answer'\n | 'no curl or wget';\n/** One request's outcome: an HTTP answer (its status; null when the tool cannot tell which error it was), or why there was none. */\nexport type Attempt =\n | { answered: true; code: number | null }\n | { answered: false; fail: UrlFail };\n/**\n * The host's facts about one url, as its probe line gives them: the HTTP code (0 = nothing answered, null = neither\n * curl nor wget there), the tool's exit token (curl's status, or `w<status>[:<stderr>]` for wget), the first address\n * the url's name resolves to there. null for a field the line did not carry.\n */\nexport interface HostUrl {\n code: number | null;\n exit: string | null;\n addr: string | null;\n}\n/** The host as it describes itself in the probe's environment section. */\nexport interface HostEnv {\n container: 'docker' | 'podman' | 'lxc' | 'none';\n hostname: string | null;\n /** the addresses the host's own name resolves to, plus 127.0.0.1 and ::1 */\n self: string[];\n}\n/** One app's url as decided: the answer, where it came from, and why it is down or was taken from this machine. */\nexport interface UrlResult {\n status: 'ok' | 'error' | 'down' | 'unchecked';\n code: number | null;\n from: 'host' | 'here' | null;\n reason: string | null;\n}\n/**\n * The check made on the machine mcproc runs on; a dependency, so tests never open sockets they do not mean to. It never\n * rejects: a failure is an Attempt without an answer (settleUrls still reads a rejection as no answer).\n */\nexport type HereCheck = (url: string) => Promise<Attempt>;\n/** What the decision needs of an app. */\nexport interface UrlApp {\n name: string;\n url: string;\n url_check: UrlCheckMode;\n}\nexport interface UrlInput {\n host: string;\n /** the host is this machine: its probe's check is the only one */\n local: boolean;\n mode: UrlCheckMode;\n url: string;\n /** the probe's line for the url; absent when the host did not request it */\n onHost?: HostUrl;\n /** the check from this machine; absent when none was made */\n here?: Attempt;\n env: HostEnv | null;\n}\n\nexport const HERE_CONNECT_MS = 1000;\nexport const HERE_TOTAL_MS = 2000;\n\n/**\n * One GET from this machine, as the host's curl makes it: connected within 1 s, answered within 2 s, any certificate\n * accepted (it asks \"does it answer\", not \"can I trust it\"), redirects not followed (a 3xx is an answer). node:http\n * rather than fetch: fetch cannot turn certificate checks off for one request without the undici package. A fresh\n * socket per check (no agent), so the connect timer measures this connection. Never rejects: a url that does not\n * parse, or one the request refuses at once (another protocol), resolves as no answer.\n */\nexport function checkHere(\n url: string,\n opts: { connectMs?: number; totalMs?: number } = {}\n): Promise<Attempt> {\n return new Promise((resolve) => {\n let settled = false;\n let total: NodeJS.Timeout | undefined;\n let connect: NodeJS.Timeout | undefined;\n const settle = (a: Attempt) => {\n if (settled) return;\n settled = true;\n clearTimeout(total);\n clearTimeout(connect);\n resolve(a);\n };\n try {\n const u = new URL(url);\n const tls = u.protocol === 'https:';\n const onAnswer = (res: http.IncomingMessage) => {\n settle({ answered: true, code: res.statusCode ?? null });\n res.resume();\n req.destroy(); // the status is all it asks; the body is not waited for\n };\n const base = {\n method: 'GET',\n agent: false,\n headers: { 'user-agent': 'mcproc' },\n };\n const req = tls\n ? https.request(u, { ...base, rejectUnauthorized: false }, onAnswer)\n : http.request(u, base, onAnswer);\n // a timer settles the check itself, then drops the request: the bound holds whether or not an error follows\n const timeout = () => {\n settle({ answered: false, fail: 'timeout' });\n req.destroy();\n };\n total = setTimeout(timeout, opts.totalMs ?? HERE_TOTAL_MS);\n req.on('socket', (s) => {\n if (settled) return;\n connect = setTimeout(timeout, opts.connectMs ?? HERE_CONNECT_MS);\n // TLS counts as connecting, as for curl's --connect-timeout\n s.once(tls ? 'secureConnect' : 'connect', () => clearTimeout(connect));\n });\n req.on('error', (e) => settle({ answered: false, fail: hereFail(e) }));\n req.end();\n } catch (e) {\n // the URL parser or the request itself threw before anything was sent\n settle({ answered: false, fail: hereFail(e) });\n }\n });\n}\n\n/** What a failed request from here means, in the words the host's checks use. */\nexport function hereFail(e: unknown): UrlFail {\n const err = e as { code?: unknown; message?: unknown } | null | undefined;\n const code = String(err?.code ?? '');\n const msg = String(err?.message ?? '');\n if (code === 'ETIMEDOUT') return 'timeout';\n if (['ENOTFOUND', 'EAI_AGAIN', 'EAI_NONAME', 'EAI_FAIL'].includes(code))\n return 'not resolved';\n if (code === 'ECONNREFUSED') return 'refused';\n if (\n code === 'EPROTO' ||\n code.startsWith('ERR_SSL') ||\n code.startsWith('ERR_TLS') ||\n /\\bSSL\\b|\\bTLS\\b|certificate/i.test(msg)\n )\n return 'tls';\n if (code === 'ECONNRESET' || code === 'EPIPE') return 'reset';\n return 'no answer';\n}\n\n/** curl's exit statuses that say why nothing answered (its `-w %{http_code}` is 000 for every one of them). */\nconst CURL_FAILS: Record<string, UrlFail> = {\n '6': 'not resolved',\n '7': 'refused',\n '28': 'timeout',\n '35': 'tls',\n '51': 'tls',\n '58': 'tls',\n '60': 'tls',\n '52': 'reset',\n '56': 'reset',\n};\n\n/**\n * wget prints 000 for every failure; its token `w<status>[:<stderr>]` says more. BusyBox wget (alpine) exits 1 for\n * everything and says why on stderr, even under -q (\"Connection refused\", \"bad address\", \"download timed out\",\n * \"server returned error: HTTP/1.1 404 Not Found\"); GNU wget is silent under -q and its status says it: 4 network,\n * 5 TLS, 6 authentication and 8 an error answer (both HTTP answers whose code it does not print).\n */\nfunction wgetAttempt(x: string): Attempt {\n const m = /^w(\\d+)(?::(.*))?$/s.exec(x);\n const status = m ? Number(m[1]) : -1;\n const msg = m?.[2] ?? '';\n const no = (fail: UrlFail): Attempt => ({ answered: false, fail });\n const answer = /HTTP\\/[\\d.]+ (\\d{3})\\b/.exec(msg);\n if (answer) return { answered: true, code: Number(answer[1]) };\n // cut as a whole by `timeout`: 124 from coreutils, 143 (SIGTERM) from BusyBox's, which execs wget in place\n if (status === 124 || status === 143) return no('timeout');\n // refused and resolve failures before tls: a resolve failure quotes the name, which may itself contain ssl or tls\n if (/refused/i.test(msg)) return no('refused');\n if (/bad address|resolve|not known|name resolution/i.test(msg))\n return no('not resolved');\n if (/ssl|tls|certificate/i.test(msg)) return no('tls'); // a failed handshake ends in a reset too: TLS first\n if (/timed out/i.test(msg)) return no('timeout');\n if (/reset|error getting response|closed/i.test(msg)) return no('reset');\n if (status === 5) return no('tls');\n if (status === 6 || status === 8) return { answered: true, code: null };\n return no('no answer');\n}\n\n/** What the host's check found, from its probe line. */\nexport function hostAttempt(h: HostUrl): Attempt {\n if (h.code === null) return { answered: false, fail: 'no curl or wget' };\n if (h.code > 0) return { answered: true, code: h.code };\n const x = h.exit ?? '';\n if (x.startsWith('w')) return wgetAttempt(x);\n return { answered: false, fail: CURL_FAILS[x] ?? 'no answer' };\n}\n\n/**\n * The url's name resolved on its host to the host itself (a hostname line in /etc/hosts, a loopback address, one of\n * its own addresses): the name means another machine where the url is opened. Never for localhost or an IP literal:\n * those name the host on purpose.\n */\nexport function isItself(\n name: string | null,\n addr: string | null,\n env: HostEnv | null\n): boolean {\n if (\n !name ||\n !addr ||\n isIP(name) !== 0 ||\n name === 'localhost' ||\n name.endsWith('.localhost')\n )\n return false;\n return (\n addr.startsWith('127.') ||\n addr === '::1' ||\n (env?.self.includes(addr) ?? false)\n );\n}\n\n/**\n * Why the host got no answer, as url_reason says it. A name that resolves there to the host itself is the reason only\n * when the url answered from here (`answeredHere`): a name that means another machine where the url is opened, the\n * dev-container case. Otherwise the host's own failure stays the reason and the address follows as a note: a host\n * whose own name legitimately resolves to itself, its app simply down, must not point at naming.\n */\nfunction hostReason(\n i: UrlInput,\n h: HostUrl,\n fail: UrlFail,\n answeredHere: boolean\n): string {\n const name = urlName(i.url);\n if (fail === 'not resolved' && name)\n return `on ${i.host} ${name} does not resolve`;\n const own = `on ${i.host}: ${fail}`;\n if (i.local || fail === 'no curl or wget' || !isItself(name, h.addr, i.env))\n return own;\n const itself = `${name} resolves to ${h.addr}, the host itself`;\n return answeredHere ? `on ${i.host} ${itself}` : `${own} (${itself})`;\n}\n\n/** The address note a host's failure carries when its name resolves to the host itself (see hostReason). */\nconst ITSELF_NOTE = / \\([^()]*, the host itself\\)/g;\n/** A reason without that note, for a line that already says where the name resolves. */\nexport const withoutItselfNote = (reason: string): string =>\n reason.replace(ITSELF_NOTE, '');\n\nconst UNCHECKED: UrlResult = {\n status: 'unchecked',\n code: null,\n from: null,\n reason: null,\n};\nconst answered = (\n code: number | null,\n from: 'host' | 'here',\n reason: string | null\n): UrlResult => ({\n status: code !== null && code < 400 ? 'ok' : 'error',\n code,\n from,\n reason,\n});\nconst down = (from: 'host' | 'here', reason: string): UrlResult => ({\n status: 'down',\n code: null,\n from,\n reason,\n});\n\n/** Whether a url is also checked from here: never for a host that is this machine; always for here; for auto only when the host got no answer. */\nexport function needsHere(\n local: boolean,\n mode: UrlCheckMode,\n onHost: HostUrl | undefined\n): boolean {\n if (local || mode === 'host') return false;\n if (mode === 'here') return true;\n return onHost !== undefined && !hostAttempt(onHost).answered;\n}\n\n/**\n * Where an app's url answers (the rules of url_check). auto: an HTTP answer on the host wins; with none, the answer\n * from here, the reason saying why the host could not; with neither, down from here with both reasons. host: only the\n * host's line (no curl or wget there leaves it unchecked, with that reason). here: only the check from here. A host that\n * is this machine makes one check, its probe's, whatever url_check says.\n */\nexport function decideUrl(i: UrlInput): UrlResult {\n const here = i.here;\n if (!i.local && i.mode === 'here') {\n if (!here) return UNCHECKED;\n return here.answered\n ? answered(here.code, 'here', 'url_check: here')\n : down('here', `here: ${here.fail}`);\n }\n const onHost = i.onHost;\n if (!onHost) return UNCHECKED;\n const a = hostAttempt(onHost);\n if (a.answered) return answered(a.code, 'host', null);\n const why = (answeredHere: boolean) =>\n hostReason(i, onHost, a.fail, answeredHere);\n if (i.local || i.mode === 'host' || !here)\n return a.fail === 'no curl or wget'\n ? { ...UNCHECKED, reason: why(false) }\n : down('host', why(false));\n if (here.answered) return answered(here.code, 'here', why(true));\n return down('here', `${why(false)}; here: ${here.fail}`);\n}\n\n/**\n * Every asked app's url decided on one host. The checks from here the rules need run in parallel, one per distinct\n * url, after the probe: a url the host answered costs nothing more. Keyed by app name.\n */\nexport async function settleUrls(\n apps: UrlApp[],\n where: { host: string; local: boolean },\n probe: { urls: Map<string, HostUrl>; env: HostEnv | null },\n here: HereCheck\n): Promise<Record<string, UrlResult>> {\n const want = [\n ...new Set(\n apps\n .filter((a) =>\n needsHere(where.local, a.url_check, probe.urls.get(a.url))\n )\n .map((a) => a.url)\n ),\n ];\n // a check that breaks its contract and rejects (or throws) is no answer for its url, not a failed snapshot\n const ask = async (u: string): Promise<Attempt> => {\n try {\n return await here(u);\n } catch {\n return { answered: false, fail: 'no answer' };\n }\n };\n const answers = new Map(\n await Promise.all(want.map(async (u) => [u, await ask(u)] as const))\n );\n return Object.fromEntries(\n apps.map((a) => [\n a.name,\n decideUrl({\n host: where.host,\n local: where.local,\n mode: a.url_check,\n url: a.url,\n onHost: probe.urls.get(a.url),\n here: answers.get(a.url),\n env: probe.env,\n }),\n ])\n );\n}\n\n/**\n * The short word of a reason, for `✗ down (…)`: that of the last place tried (this machine, after the host), never the\n * address note. `itself` only for the reason of a url that answered from here.\n */\nexport function reasonWord(reason: string): string {\n const last = withoutItselfNote(reason.split('; ').at(-1) ?? reason);\n if (last.endsWith(', the host itself')) return 'itself';\n if (last.endsWith(' does not resolve')) return 'not resolved';\n const i = last.lastIndexOf(': ');\n return i < 0 ? last : last.slice(i + 2);\n}\n","import { isIP } from 'node:net';\nimport { shq } from '../transport/quote.js';\nimport { DEFAULT_TIMEOUT_MS } from '../transport/index.js';\n\n/** The host name of a url, as a host resolves it (IPv6 brackets removed); null when the url does not parse. */\nexport function urlName(url: string): string | null {\n try {\n return new URL(url).hostname.replace(/^\\[|\\]$/g, '') || null;\n } catch {\n return null;\n }\n}\n\nexport const MARK = {\n JLIST: '__MCPROC_JLIST__',\n JLIST_RC: '__MCPROC_JLIST_RC__',\n CLOCK: '__MCPROC_CLOCK__',\n PS: '__MCPROC_PS__',\n TCP: '__MCPROC_TCP__',\n UDP: '__MCPROC_UDP__',\n FD: '__MCPROC_FD__',\n PROC: '__MCPROC_PROC__',\n STAT: '__MCPROC_STAT__',\n STAT2: '__MCPROC_STAT2__',\n RSS: '__MCPROC_RSS__',\n ARGS: '__MCPROC_ARGS__',\n DOCKER: '__MCPROC_DOCKER__',\n ENV: '__MCPROC_ENV__',\n MEM: '__MCPROC_MEM__',\n DOCKERMEM: '__MCPROC_DOCKERMEM__',\n URL: '__MCPROC_URL__',\n} as const;\n\n/* /proc/<pid>/stat: \"pid (comm) state ppid …\"; comm may contain spaces, so cut after the last \")\". */\nconst PS_FALLBACK = `for p in /proc/[0-9]*; do s=$(cat \"$p/stat\" 2>/dev/null) || continue; r=\\${s##*) }; set -- $r; echo \"\\${p#/proc/} $2\"; done`;\n/* \"<pid> <inode>\" for every socket fd; only needed when ss is missing. */\nconst FD_SCAN = `for p in /proc/[0-9]*; do for f in \"$p\"/fd/*; do l=$(readlink \"$f\" 2>/dev/null) || continue; case $l in socket:*) i=\\${l#socket:[}; echo \"\\${p#/proc/} \\${i%]}\";; esac; done; done`;\n/* The /proc scans read stdin fed by `cat`, never a file list: mawk and busybox awk abort the whole pass at the first file that\n vanished between the glob and the open (a process exiting mid-pass), and only gawk carries on; cat just skips it. */\n/* \"pid ppid utime+stime\" per process in ONE awk pass; the comm field may contain spaces, so split after the last \") \". */\nexport const STAT_AWK = `awk '{ i=index($0,\") \"); split(substr($0,i+2),f,\" \"); print $1, f[2], f[12]+f[13] }'`;\n/* \"pid VmRSS_kB\" per process (Pid: precedes VmRSS: in /proc/<pid>/status); kernel threads have no VmRSS and drop out. */\nexport const RSS_AWK = `awk '/^Pid:/{ p=$2 } /^VmRSS:/{ print p, $2 }'`;\n/**\n * `cmd` cut after `secs` seconds where the host has `timeout`, and run as it is where it has not: a wedged docker daemon\n * or a dead resolver must not stall the whole probe until the transport timeout.\n */\nexport const bounded = (secs: number, cmd: string): string =>\n `if command -v timeout >/dev/null 2>&1; then timeout ${secs} ${cmd}; else ${cmd}; fi`;\n\n/** Seconds each of the environment section's two lookups (its own name, `hostname -i`) may take on the host. */\nconst ENV_LOOKUP_S = 2;\n/** Seconds a url's name lookup may take on the host. */\nconst URL_LOOKUP_S = 2;\n/** Seconds curl may take for a url (-m). */\nconst URL_CURL_S = 2;\n/** Seconds wget may take for a url, as a whole: its -T bounds each phase, not a body that streams on or its own resolver. */\nconst URL_WGET_S = 3;\n/** The most one url check adds to a round trip: its lookup, then curl or wget, whichever may take longer. */\nconst URL_CHECK_MS = (URL_LOOKUP_S + Math.max(URL_CURL_S, URL_WGET_S)) * 1000;\n/** The most the environment section adds to a round trip: its two lookups. */\nconst ENV_MS = 2 * ENV_LOOKUP_S * 1000;\n/** No round trip that checks urls waits longer than this, however many urls it checks. */\nconst URL_BUDGET_CAP_MS = 120_000;\n\n/**\n * The time budget of a round trip that checks `urls` urls on the host: `base`, plus the bounds of the environment\n * section (asked with any url, or always with `env`) and of each url, so a host whose resolver drops packets still\n * answers; never more than URL_BUDGET_CAP_MS. These bounds hold where the host has `timeout`.\n */\nexport function urlBudgetMs(\n base: number,\n urls: number,\n env = urls > 0\n): number {\n return Math.min(\n base + (env ? ENV_MS : 0) + URL_CHECK_MS * urls,\n URL_BUDGET_CAP_MS\n );\n}\n\n/** The probe's time budget: the transport's default, grown by the urls it checks. */\nexport const probeTimeoutMs = (urls: number): number =>\n urlBudgetMs(DEFAULT_TIMEOUT_MS, urls);\n\n/**\n * The host about itself, next to its url checks: whether it is a container, its hostname, and the addresses its own\n * name resolves to (127.0.0.1 and ::1 always), so a url whose name resolves to one of them reads \"the host itself\".\n */\nexport const ENV_SNIPPET = [\n `echo ${MARK.ENV}`,\n `c=none; if [ -f /.dockerenv ]; then c=docker; elif [ -f /run/.containerenv ]; then c=podman; elif grep -qa 'container=lxc' /proc/1/environ 2>/dev/null || grep -q '/lxc' /proc/1/cgroup 2>/dev/null; then c=lxc; elif grep -q '/docker' /proc/1/cgroup 2>/dev/null; then c=docker; fi; echo \"container $c\"`,\n `h=$(hostname 2>/dev/null || cat /proc/sys/kernel/hostname 2>/dev/null); echo \"hostname $h\"`,\n `echo \"self $(${bounded(ENV_LOOKUP_S, 'getent hosts \"$h\" 2>/dev/null')} | awk '{print $1}' | tr '\\\\n' ' ')$(${bounded(ENV_LOOKUP_S, 'hostname -i 2>/dev/null')}) 127.0.0.1 ::1\"`,\n].join('\\n');\n\n/** The host's memory: the two /proc/meminfo lines the lease needs (MemTotal, MemAvailable); empty where there is no /proc. */\nexport const MEM_SNIPPET = [\n `echo ${MARK.MEM}`,\n `awk '/^(MemTotal|MemAvailable):/' /proc/meminfo 2>/dev/null`,\n].join('\\n');\n\n/**\n * The memory of the declared containers that are running: one `docker stats --no-stream` over those names (a name\n * that is not running fails the whole call, so `docker ps` filters first). Measured at about 2 s per call, so it\n * is asked only where the caller passes names; empty when there are none.\n */\nexport function dockerMemSnippet(names: string[]): string {\n if (names.length === 0) return '';\n return [\n `echo ${MARK.DOCKERMEM}`,\n `if command -v docker >/dev/null 2>&1; then R=$(${bounded(3, \"docker ps --format '{{.Names}}' 2>/dev/null\")}); L=\"\"; for n in ${names.map(shq).join(' ')}; do if printf '%s\\\\n' \"$R\" | grep -qxF -- \"$n\"; then L=\"$L $n\"; fi; done; if [ -n \"$L\" ]; then ${bounded(5, \"docker stats --no-stream --format '{{.Name}}\\\\t{{.MemUsage}}' $L 2>/dev/null\")}; fi; fi`,\n ].join('\\n');\n}\n\n/**\n * \"<url>\\t<code>\\t<exit>\\t<addr>\": curl's HTTP status (000 when nothing answered) and its exit status; or wget's 200/000\n * and `w<status>:<its stderr on one line>` (BusyBox wget exits 1 for every failure and says why only there); \"-\" and an\n * empty exit when the host has neither. addr: the first address the url's name resolves to there (an IP literal is\n * itself), empty when it does not resolve or getent is missing. A liveness check, not a trust check: self-signed dev\n * certificates (-k / --no-check-certificate) must not read as down. wget makes one try (-t 1): GNU wget otherwise retries\n * a timed-out request up to 20 times; BusyBox wget accepts -t and makes one try anyway. It is also cut as a whole after\n * URL_WGET_S, which exits 124 (coreutils timeout) or 143 (BusyBox's, by SIGTERM).\n */\nexport function urlCheck(url: string): string {\n const q = shq(url);\n const name = urlName(url);\n const addr =\n name === null\n ? \"''\"\n : isIP(name) !== 0\n ? shq(name)\n : `\"$(${bounded(URL_LOOKUP_S, `getent hosts ${shq(name)} 2>/dev/null`)} | awk 'NR==1{print $1}')\"`;\n return [\n `printf '%s\\\\t' ${q}`,\n `if command -v curl >/dev/null 2>&1; then curl -s -k -o /dev/null --connect-timeout 1 -m ${URL_CURL_S} -w '%{http_code}' ${q} 2>/dev/null; printf '\\\\t%s' \"$?\"`,\n `elif command -v wget >/dev/null 2>&1; then e=$(${bounded(URL_WGET_S, `wget -q --no-check-certificate -t 1 -T 2 -O /dev/null ${q} 2>&1`)}); r=$?; if [ \"$r\" = 0 ]; then printf '200\\\\tw0'; else printf '000\\\\tw%s:%s' \"$r\" \"$(printf '%s' \"$e\" | tr '\\\\t\\\\n\\\\r' ' ' | cut -c1-200)\"; fi`,\n `else printf '%s\\\\t' -; fi`,\n `printf '\\\\t%s\\\\n' ${addr}`,\n ].join('; ');\n}\n\n/**\n * The url part of a host's answer, which parseUrlProbe reads back: the host's environment (when `env`; by default only\n * with a url to check, where it explains why one does not answer there), the URL marker, one check per url.\n */\nexport function urlSection(urls: string[], env = urls.length > 0): string[] {\n return [\n ...(env ? [ENV_SNIPPET] : []),\n `echo ${MARK.URL}`,\n ...urls.map(urlCheck),\n ];\n}\n\n/** One round trip: pm2 state, the host's UTC offset, process tree, listeners, CPU ticks, RSS, command lines, docker-published ports, the host's\n * memory (/proc/meminfo), the memory of the declared `containers` that run (docker stats, only when names are given), and one HTTP\n * request per declared url, with the host's environment (container, hostname, own addresses) when there is one. `metrics: false` is the light form\n * for polling: pm2 state, offset, tree, listeners and urls only, no /proc stat, RSS, args or docker passes. */\nexport function probeScript(\n pm2Bin: string,\n opts: {\n cpuSample?: boolean;\n urls?: string[];\n metrics?: boolean;\n containers?: string[];\n } = {}\n): string {\n return [\n `echo ${MARK.JLIST}`,\n `${pm2Bin} jlist 2>/dev/null; echo \"${MARK.JLIST_RC} $?\"`,\n // pm2 keeps start times as epoch ms and stamps log lines in the host's wall time: the offset turns one into the other\n `echo ${MARK.CLOCK}`,\n `date '+%z' 2>/dev/null`,\n `echo ${MARK.PS}`,\n `if command -v ps >/dev/null 2>&1; then ps -eo pid,ppid 2>/dev/null || ps -o pid,ppid 2>/dev/null; else ${PS_FALLBACK}; fi`,\n // F=1 once /proc is used for either protocol: an ss that is missing or fails (old iproute2) must not read as \"no listeners\"\n `F=0`,\n `echo ${MARK.TCP}`,\n `if command -v ss >/dev/null 2>&1 && T=$(ss -ltnp 2>/dev/null); then printf '%s\\\\n' \"$T\"; else F=1; echo ${MARK.PROC}; cat /proc/net/tcp /proc/net/tcp6 2>/dev/null; fi`,\n `echo ${MARK.UDP}`,\n `if [ \"$F\" = 0 ] && U=$(ss -lunp 2>/dev/null); then printf '%s\\\\n' \"$U\"; else F=1; echo ${MARK.PROC}; cat /proc/net/udp /proc/net/udp6 2>/dev/null; fi`,\n `echo ${MARK.FD}`,\n `if [ \"$F\" = 1 ]; then ${FD_SCAN}; fi`,\n ...(opts.metrics === false\n ? []\n : [\n `echo ${MARK.STAT}`,\n `echo \"CLK $(getconf CLK_TCK 2>/dev/null || echo 100)\"`,\n `cat /proc/[0-9]*/stat 2>/dev/null | ${STAT_AWK}`,\n ...(opts.cpuSample\n ? [\n `sleep 0.5 2>/dev/null || sleep 1`,\n `echo ${MARK.STAT2}`,\n `echo \"CLK $(getconf CLK_TCK 2>/dev/null || echo 100)\"`,\n `cat /proc/[0-9]*/stat 2>/dev/null | ${STAT_AWK}`,\n ]\n : []),\n `echo ${MARK.RSS}`,\n `cat /proc/[0-9]*/status 2>/dev/null | ${RSS_AWK}`,\n `echo ${MARK.ARGS}`,\n `ps -eo pid=,args= 2>/dev/null || ps -o pid,args 2>/dev/null`,\n `echo ${MARK.DOCKER}`,\n `if command -v docker >/dev/null 2>&1; then ${bounded(3, \"docker ps --format '{{.Names}}\\\\t{{.Ports}}' 2>/dev/null\")}; fi`,\n MEM_SNIPPET,\n ...(opts.containers?.length\n ? [dockerMemSnippet(opts.containers)]\n : []),\n ]),\n ...urlSection(opts.urls ?? []),\n ].join('\\n');\n}\n\n/**\n * Shell for the hex of the 16 bytes before byte position `end` (a shell expression) of the already quoted file `f`.\n * Comparing them with what they were tells a grown file from a replaced or truncated one that grew back past the\n * old position (pm2-logrotate, a flush outside mcproc): size alone cannot.\n */\nexport const hex16 = (f: string, end: string): string =>\n `$([ ${end} -gt 0 ] && tail -c +$((${end}>16?${end}-15:1)) ${f} 2>/dev/null | head -c $((${end}>16?16:${end})) | od -An -tx1 | tr -d ' \\\\n')`;\n","import { execFileSync } from 'node:child_process';\nimport { createHash } from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { McprocError } from '../core/errors.js';\n\nexport interface Pm2Bundle {\n version: string;\n sha256: string;\n data: Buffer;\n path: string;\n}\nexport type Runner = (cmd: string, args: string[], cwd: string) => void;\n\nconst sha256 = (b: Buffer) => createHash('sha256').update(b).digest('hex');\nconst readJson = (p: string) =>\n // biome-ignore lint/suspicious/noExplicitAny: package.json files are untyped data, probed field by field\n JSON.parse(fs.readFileSync(p, 'utf8')) as Record<string, any>;\n\n/** Walks up to the directory whose package.json is mcproc's (works from src/ under tsx and from dist/ when installed). */\nexport function findPackageRoot(\n from: string = path.dirname(fileURLToPath(import.meta.url))\n): string {\n let dir = path.resolve(from);\n for (;;) {\n const p = path.join(dir, 'package.json');\n if (fs.existsSync(p)) {\n try {\n if (readJson(p).name === 'mcproc') return dir;\n } catch {\n /* not ours */\n }\n }\n const parent = path.dirname(dir);\n if (parent === dir)\n throw new McprocError(\n 'BUNDLE_INVALID',\n `cannot locate the mcproc package root above ${from}`\n );\n dir = parent;\n }\n}\n\nexport function lockfileHash(root: string): string {\n return sha256(\n fs.readFileSync(path.join(root, 'runtime', 'package-lock.json'))\n );\n}\n\nexport function defaultPm2CacheDir(\n env: NodeJS.ProcessEnv = process.env\n): string {\n return path.join(\n env.XDG_CACHE_HOME || path.join(os.homedir(), '.cache'),\n 'mcproc',\n 'pm2'\n );\n}\n\nconst defaultRunner: Runner = (cmd, args, cwd) => {\n execFileSync(cmd, args, { cwd, stdio: ['ignore', 'ignore', 'inherit'] });\n};\n\nfunction tarFlags(): string[] {\n try {\n return /GNU tar/.test(execFileSync('tar', ['--version']).toString())\n ? [\n '--sort=name',\n '--mtime=@0',\n '--owner=0',\n '--group=0',\n '--numeric-owner',\n '--mode=u+rwX,go+rX,go-w',\n ]\n : [];\n } catch {\n return [];\n }\n}\n\n/**\n * The pm2 tree `unpack` ships to hosts, assembled on THIS machine with npm ci from the lockfile mcproc ships\n * (never embedded in the package) and cached once per pm2 version + lockfile.\n */\nexport async function ensurePm2Bundle(\n opts: { root?: string; cacheDir?: string; run?: Runner; force?: boolean } = {}\n): Promise<Pm2Bundle> {\n const root = opts.root ?? findPackageRoot();\n const cacheDir = opts.cacheDir ?? defaultPm2CacheDir();\n const run = opts.run ?? defaultRunner;\n const pin: string =\n readJson(path.join(root, 'package.json')).dependencies?.pm2 ?? '';\n if (!/^\\d+\\.\\d+\\.\\d+$/.test(pin))\n throw new McprocError(\n 'BUNDLE_INVALID',\n `pm2 must be pinned to an exact version in mcproc's package.json, got \"${pin}\"`\n );\n const runtimePin: string =\n readJson(path.join(root, 'runtime', 'package.json')).dependencies?.pm2 ??\n '';\n if (runtimePin !== pin)\n throw new McprocError(\n 'BUNDLE_INVALID',\n `runtime/package.json pins pm2 ${runtimePin}, package.json pins ${pin}`\n );\n const lockSha = lockfileHash(root);\n const target = path.join(cacheDir, `pm2-${pin}-${lockSha.slice(0, 12)}.tgz`);\n const sidecar = `${target}.json`;\n if (!opts.force && fs.existsSync(target) && fs.existsSync(sidecar)) {\n const meta = readJson(sidecar);\n const data = fs.readFileSync(target);\n if (\n meta.pm2 === pin &&\n meta.lock_sha256 === lockSha &&\n sha256(data) === meta.sha256\n )\n return { version: pin, sha256: meta.sha256, data, path: target };\n }\n const stage = fs.mkdtempSync(path.join(os.tmpdir(), 'mcproc-pm2-'));\n try {\n for (const f of ['package.json', 'package-lock.json'])\n fs.copyFileSync(path.join(root, 'runtime', f), path.join(stage, f));\n try {\n run(\n 'npm',\n ['ci', '--omit=dev', '--ignore-scripts', '--no-audit', '--no-fund'],\n stage\n );\n } catch (e) {\n throw new McprocError(\n 'DOWNLOAD_FAILED',\n `npm ci for pm2 ${pin} failed on this machine: ${(e as Error).message}`,\n {\n hint: 'unpack assembles pm2 here once with npm (network to the npm registry needed the first time); afterwards the cached archive is used.',\n }\n );\n }\n const got = readJson(\n path.join(stage, 'node_modules', 'pm2', 'package.json')\n ).version;\n if (got !== pin)\n throw new McprocError(\n 'BUNDLE_INVALID',\n `npm installed pm2 ${got}, expected ${pin}`\n );\n fs.rmSync(path.join(stage, 'node_modules', '.package-lock.json'), {\n force: true,\n });\n const tgz = execFileSync(\n 'tar',\n [...tarFlags(), '-czf', '-', 'node_modules'],\n { cwd: stage, maxBuffer: 1 << 30 }\n );\n fs.mkdirSync(cacheDir, { recursive: true });\n fs.writeFileSync(`${target}.part`, tgz);\n fs.renameSync(`${target}.part`, target);\n const meta = {\n pm2: pin,\n sha256: sha256(tgz),\n bytes: tgz.length,\n lock_sha256: lockSha,\n built_at: new Date().toISOString(),\n };\n fs.writeFileSync(sidecar, `${JSON.stringify(meta, null, 2)}\\n`);\n return { version: pin, sha256: meta.sha256, data: tgz, path: target };\n } finally {\n fs.rmSync(stage, { recursive: true, force: true });\n }\n}\n","import { McprocError } from '../core/errors.js';\n\nexport type NodePlatform =\n | 'linux-x64'\n | 'linux-arm64'\n | 'linux-x64-musl'\n | 'darwin-x64'\n | 'darwin-arm64';\nexport const NODE_DIST_BASE = 'https://nodejs.org/dist';\n\n/** `uname -sm` plus the musl probe → a platform nodejs.org publishes a tarball for, or null. */\nexport function parsePlatform(\n unameSm: string,\n musl: boolean\n): NodePlatform | null {\n const [sys, machine] = unameSm.trim().split(/\\s+/);\n const arch =\n machine === 'x86_64' || machine === 'amd64'\n ? 'x64'\n : machine === 'aarch64' || machine === 'arm64'\n ? 'arm64'\n : null;\n if (!arch) return null;\n if (sys === 'Linux') {\n if (musl) return arch === 'x64' ? 'linux-x64-musl' : null; // nodejs.org publishes musl builds for x64 only\n return arch === 'x64' ? 'linux-x64' : 'linux-arm64';\n }\n if (sys === 'Darwin') return arch === 'x64' ? 'darwin-x64' : 'darwin-arm64';\n return null;\n}\n\nexport function nodeDistFile(version: string, platform: NodePlatform): string {\n return `node-${version}-${platform}.tar.gz`;\n}\n\nexport function nodeDistUrl(version: string, file: string): string {\n return `${NODE_DIST_BASE}/${version}/${file}`;\n}\n\nexport function parseShasums(text: string): Map<string, string> {\n const m = new Map<string, string>();\n for (const line of text.split('\\n')) {\n const r = /^([0-9a-f]+)\\s+\\*?(\\S+)$/i.exec(line.trim());\n if (r) m.set(r[2], r[1].toLowerCase());\n }\n return m;\n}\n\nexport function normalizeVersion(v: string): string {\n const s = v.trim();\n if (!/^v?\\d+\\.\\d+\\.\\d+$/.test(s))\n throw new McprocError('BAD_ARGUMENT', `not a Node version: \"${v}\"`, {\n hint: 'Use an exact version such as 24.21.0.',\n });\n return s.startsWith('v') ? s : `v${s}`;\n}\n\nexport function compareVersions(a: string, b: string): number {\n const pa = a.replace(/^v/, '').split('.').map(Number);\n const pb = b.replace(/^v/, '').split('.').map(Number);\n for (let i = 0; i < 3; i++) if (pa[i] !== pb[i]) return pa[i] - pb[i];\n return 0;\n}\n","import { McprocError } from '../core/errors.js';\nimport { nodeMajor } from '../core/pm2.js';\nimport { parsePlatform, type NodePlatform } from './platform.js';\nimport type { HostFacts } from './probe.js';\n\nexport type WithNode = 'auto' | 'always' | 'never';\nexport interface UnpackOptions {\n dir?: string;\n withNode?: WithNode;\n nodeVersion?: string;\n force?: boolean;\n}\n\n/**\n * Whether unpack brings an official Node build. `auto` brings one when the host has none >= 18, when a version is asked\n * for, or when the runtime already carries one (its wrapper runs that Node, so it stays managed and can be upgraded).\n */\nexport function needsNode(\n f: HostFacts,\n o: UnpackOptions\n): { need: boolean; platform: NodePlatform | null } {\n const mode = o.withNode ?? 'auto';\n const hostOk = nodeMajor(f.node) >= 18;\n if (o.nodeVersion !== undefined && mode === 'never') {\n throw new McprocError(\n 'BAD_ARGUMENT',\n `node_version ${o.nodeVersion} asks for a Node build, but with_node is never`,\n { hint: 'Drop node_version, or use with_node: auto (or always).' }\n );\n }\n if (o.nodeVersion !== undefined && nodeMajor(o.nodeVersion) < 18) {\n throw new McprocError(\n 'BAD_ARGUMENT',\n `node_version ${o.nodeVersion} is older than 18, which pm2 needs`,\n {\n hint: 'Ask for Node 18 or newer, or leave node_version out for the current LTS.',\n }\n );\n }\n const carried = o.nodeVersion !== undefined || Boolean(f.lock?.node);\n if (mode === 'never' || (mode === 'auto' && hostOk && !carried)) {\n if (!hostOk) {\n throw new McprocError(\n 'NODE_NOT_FOUND',\n `the host has ${f.node ? `Node ${f.node}` : 'no Node'} in its login shell and with_node is never; pm2 needs Node 18 or newer`,\n {\n hint: 'Use with_node: auto (or always) to bring an official Node build along.',\n }\n );\n }\n return { need: false, platform: null };\n }\n const platform = parsePlatform(f.unameSm, f.musl);\n if (!platform) {\n throw new McprocError(\n 'NODE_NOT_FOUND',\n `nodejs.org publishes no Node build for \"${f.unameSm}\"${f.musl ? ' with musl' : ''}`,\n {\n hint: 'Install Node 18 or newer on that host and run unpack with with_node: never.',\n }\n );\n }\n // the official Linux builds are dynamically linked against libstdc++ and libgcc; without them the binary cannot even start (darwin builds use the system libc++)\n if (platform.startsWith('linux-') && !f.cxx) {\n throw new McprocError(\n 'NODE_NOT_FOUND',\n `the host has no libstdc++, which the official Node build for ${platform} is linked against`,\n {\n hint: f.musl\n ? 'On the host: apk add libstdc++ (then run unpack again), or install Node >= 18 there and use with_node: never.'\n : 'On the host: install libstdc++6 (apt) / libstdc++ (dnf, apk), or install Node >= 18 there and use with_node: never.',\n }\n );\n }\n return { need: true, platform };\n}\n\nexport function plannedWrites(\n f: HostFacts,\n o: UnpackOptions,\n pm2Version: string,\n nodeVersion: string | null\n): { writePm2: boolean; writeNode: boolean } {\n const force = o.force === true;\n return {\n writePm2: force || f.lock?.pm2 !== pm2Version,\n writeNode: nodeVersion !== null && (force || f.lock?.node !== nodeVersion),\n };\n}\n","import { McprocError } from '../core/errors.js';\nimport { shq } from '../transport/quote.js';\nimport type { NodePlatform } from './platform.js';\n\nexport const COPY_HEADER = '# copied by mcproc unpack';\n\nexport interface RuntimeLock {\n mcproc: string;\n pm2: string;\n pm2_sha256: string;\n node: string | null;\n node_sha256: string | null;\n platform: NodePlatform | null;\n written_at: string;\n by: string;\n}\n\nfunction assertVersion(v: string): void {\n if (!/^\\d+\\.\\d+\\.\\d+$/.test(v))\n throw new McprocError(\n 'BUNDLE_INVALID',\n `bad pm2 version in the runtime bundle: \"${v}\"`\n );\n}\n\n/** POSIX sh wrapper: bundled node when present, else the node on PATH; arguments and PM2_HOME pass through. */\nexport function renderWrapper(runtimeDir: string, pm2Version: string): string {\n assertVersion(pm2Version);\n return [\n '#!/bin/sh',\n `${WRAPPER_MARK}: runs the unpacked pm2 with the bundled node when present, else the node on PATH`,\n `RT=${shq(runtimeDir)}`,\n 'if [ -x \"$RT/bin/node\" ]; then NODE=\"$RT/bin/node\"; else NODE=node; fi',\n `exec \"$NODE\" \"$RT/pm2/${pm2Version}/node_modules/pm2/bin/pm2\" \"$@\"`,\n '',\n ].join('\\n');\n}\n\n/** The marker line of the wrapper: a bin/pm2 carrying it is mcproc's even before its lock is written. */\nexport const WRAPPER_MARK = '# written by mcproc unpack';\n\n/**\n * The new runtime before anything in use is switched to it: its pm2 tree (`pm2Tree`, a staged copy, else the version's\n * place) answers with the Node it will run under — a new build (`nodeBin`), else the one in use, else the host's. Like\n * verifyScript, it never starts a daemon.\n */\nexport function stagedVerifyScript(\n runtimeDir: string,\n pm2Version: string,\n staged: { pm2Tree?: string; nodeBin?: string | null } = {}\n): string {\n assertVersion(pm2Version);\n const pkg = staged.pm2Tree\n ? `${shq(staged.pm2Tree)}/node_modules/pm2/package.json`\n : `\"$RT/pm2/${pm2Version}/node_modules/pm2/package.json\"`;\n return [\n `RT=${shq(runtimeDir)}`,\n staged.nodeBin\n ? `NODE=${shq(staged.nodeBin)}`\n : 'if [ -x \"$RT/bin/node\" ]; then NODE=\"$RT/bin/node\"; else NODE=node; fi',\n `\"$NODE\" -p 'require(process.argv[1]).version' ${pkg}`,\n ].join('; ');\n}\n\n/** Prints the unpacked pm2 version with the node the wrapper would use. Unlike `pm2 -v`, it never starts a daemon. */\nexport function verifyScript(runtimeDir: string, pm2Version: string): string {\n assertVersion(pm2Version);\n return [\n `RT=${shq(runtimeDir)}`,\n '[ -x \"$RT/bin/pm2\" ] || { echo \"missing $RT/bin/pm2\" >&2; exit 1; }',\n 'if [ -x \"$RT/bin/node\" ]; then NODE=\"$RT/bin/node\"; else NODE=node; fi',\n `\"$NODE\" -p 'require(process.argv[1]).version' \"$RT/pm2/${pm2Version}/node_modules/pm2/package.json\"`,\n ].join('; ');\n}\n\nexport function renderLock(lock: RuntimeLock): string {\n return `${JSON.stringify(lock, null, 2)}\\n`;\n}\n\nexport function manifestCopy(original: string, from: string, at: Date): string {\n return `${COPY_HEADER} from ${from} on ${at.toISOString()}; edit the original there, the next unpack replaces this copy\\n${original}`;\n}\n","import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { createHash } from 'node:crypto';\nimport { McprocError, isMcprocError } from '../core/errors.js';\nimport {\n NODE_DIST_BASE,\n compareVersions,\n nodeDistFile,\n nodeDistUrl,\n normalizeVersion,\n parseShasums,\n type NodePlatform,\n} from './platform.js';\n\nexport type Fetcher = (url: string) => Promise<{\n ok: boolean;\n status: number;\n text(): Promise<string>;\n arrayBuffer(): Promise<ArrayBuffer>;\n}>;\n/** Every request is bounded: a stalled connection must fail as DOWNLOAD_FAILED, not hang the tool call. */\nexport const defaultFetcher: Fetcher = (url) =>\n fetch(url, {\n signal: AbortSignal.timeout(url.endsWith('.tar.gz') ? 600_000 : 30_000),\n });\n\nexport interface NodeTarball {\n version: string;\n platform: NodePlatform;\n file: string;\n path: string;\n sha256: string;\n bytes: number;\n}\n\nexport function defaultCacheDir(env: NodeJS.ProcessEnv = process.env): string {\n return path.join(\n env.XDG_CACHE_HOME || path.join(os.homedir(), '.cache'),\n 'mcproc',\n 'node'\n );\n}\n\nconst sha256 = (b: Buffer) => createHash('sha256').update(b).digest('hex');\nconst HINT =\n 'The machine running mcproc must reach nodejs.org once per Node version; afterwards the verified tarball is served from its cache.';\n\nasync function getText(fetcher: Fetcher, url: string): Promise<string> {\n try {\n const r = await fetcher(url);\n if (!r.ok) throw new Error(`HTTP ${r.status}`);\n return await r.text();\n } catch (e) {\n throw new McprocError(\n 'DOWNLOAD_FAILED',\n `cannot download ${url}: ${(e as Error).message}`,\n { hint: HINT }\n );\n }\n}\n\nasync function getBytes(fetcher: Fetcher, url: string): Promise<Buffer> {\n try {\n const r = await fetcher(url);\n if (!r.ok) throw new Error(`HTTP ${r.status}`);\n return Buffer.from(await r.arrayBuffer());\n } catch (e) {\n throw new McprocError(\n 'DOWNLOAD_FAILED',\n `cannot download ${url}: ${(e as Error).message}`,\n { hint: HINT }\n );\n }\n}\n\n/** Versions cached for a platform whose checksum sidecar exists (i.e. were verified when downloaded), newest first. */\nfunction cachedVersions(cacheDir: string, platform: NodePlatform): string[] {\n let names: string[] = [];\n try {\n names = fs.readdirSync(cacheDir);\n } catch {\n return [];\n }\n const re = new RegExp(`^node-(v\\\\d+\\\\.\\\\d+\\\\.\\\\d+)-${platform}\\\\.tar\\\\.gz$`);\n return names\n .map((n) => re.exec(n)?.[1])\n .filter(\n (v): v is string =>\n !!v && names.includes(`node-${v}-${platform}.tar.gz.sha256`)\n )\n .sort(compareVersions)\n .reverse();\n}\n\nexport async function resolveNodeVersion(\n requested: string | undefined,\n platform: NodePlatform,\n opts: { fetcher?: Fetcher; cacheDir?: string } = {}\n): Promise<string> {\n if (requested) return normalizeVersion(requested);\n const fetcher = opts.fetcher ?? defaultFetcher;\n const cacheDir = opts.cacheDir ?? defaultCacheDir();\n try {\n const index = JSON.parse(\n await getText(fetcher, `${NODE_DIST_BASE}/index.json`)\n ) as { version: string; lts: string | false }[];\n const lts = index.find((v) => v.lts); // index.json lists the newest release first\n if (!lts)\n throw new McprocError(\n 'DOWNLOAD_FAILED',\n 'nodejs.org index.json lists no LTS release',\n { hint: HINT }\n );\n return lts.version;\n } catch (e) {\n const cached = cachedVersions(cacheDir, platform);\n if (cached.length) return cached[0];\n throw isMcprocError(e)\n ? e\n : new McprocError('DOWNLOAD_FAILED', (e as Error).message, {\n hint: HINT,\n });\n }\n}\n\nexport async function fetchNodeTarball(\n version: string,\n platform: NodePlatform,\n opts: { fetcher?: Fetcher; cacheDir?: string } = {}\n): Promise<NodeTarball> {\n const fetcher = opts.fetcher ?? defaultFetcher;\n const cacheDir = opts.cacheDir ?? defaultCacheDir();\n const file = nodeDistFile(version, platform);\n const target = path.join(cacheDir, file);\n const sidecar = `${target}.sha256`;\n if (fs.existsSync(target) && fs.existsSync(sidecar)) {\n const want = fs.readFileSync(sidecar, 'utf8').trim();\n const data = fs.readFileSync(target);\n if (sha256(data) === want)\n return {\n version,\n platform,\n file,\n path: target,\n sha256: want,\n bytes: data.length,\n };\n }\n const want = parseShasums(\n await getText(fetcher, nodeDistUrl(version, 'SHASUMS256.txt'))\n ).get(file);\n if (!want)\n throw new McprocError(\n 'DOWNLOAD_FAILED',\n `nodejs.org has no ${file} for ${version}`,\n {\n hint: 'Pick another node_version, or with_node: never when the host already has Node >= 18.',\n }\n );\n const data = await getBytes(fetcher, nodeDistUrl(version, file));\n const got = sha256(data);\n if (got !== want)\n throw new McprocError(\n 'DOWNLOAD_FAILED',\n `checksum mismatch for ${file}: SHASUMS256 says ${want}, downloaded ${got}`,\n { hint: HINT }\n );\n fs.mkdirSync(cacheDir, { recursive: true });\n fs.writeFileSync(`${target}.part`, data);\n fs.renameSync(`${target}.part`, target);\n fs.writeFileSync(sidecar, `${want}\\n`);\n return {\n version,\n platform,\n file,\n path: target,\n sha256: want,\n bytes: data.length,\n };\n}\n","import { shq } from '../transport/quote.js';\nimport { COPY_HEADER, WRAPPER_MARK, type RuntimeLock } from './files.js';\n\nexport const UNPACK_MARK = '__MCPROC_UNPACK__';\nexport const LOCK_MARK = '__MCPROC_LOCK__';\n\nexport interface HostFacts {\n unameSm: string;\n musl: boolean;\n node: string | null;\n tar: boolean;\n /** libstdc++ present: every nodejs.org Linux build (glibc and musl alike) is linked against it; a bare alpine lacks it. */\n cxx: boolean;\n /** `<rt>/bin/pm2` or `<rt>/bin/node` exists without a valid mcproc lock.json: files mcproc did not write (a dir such as /usr/local). */\n foreignBin: boolean;\n daemonUp: boolean;\n manifest: 'absent' | 'mcproc-copy' | 'hand-written';\n lock: RuntimeLock | null;\n}\n\n/** One round trip in plain POSIX sh (busybox and dash run it; bash is not required). */\nexport function unpackProbeScript(\n runtimeDir: string,\n manifestPath: string\n): string {\n return [\n `echo ${UNPACK_MARK}`,\n 'uname -sm',\n 'if [ -e /etc/alpine-release ] || (ldd --version 2>&1 | grep -qi musl); then echo MUSL; fi',\n 'if v=$(node -v 2>/dev/null); then echo \"NODE $v\"; else echo NODE_NONE; fi',\n 'if command -v tar >/dev/null 2>&1; then echo TAR_OK; else echo TAR_NONE; fi',\n // one path at a time: `ls a b` fails when ANY is missing, and musl hosts have no ldconfig\n 'C=0; for l in /usr/lib/libstdc++.so.6 /lib/libstdc++.so.6 /usr/lib64/libstdc++.so.6 /usr/lib/*-linux-gnu/libstdc++.so.6; do [ -e \"$l\" ] && C=1; done; if [ \"$C\" = 1 ] || ldconfig -p 2>/dev/null | grep -q \\'libstdc++\\\\.so\\\\.6\\'; then echo CXX_OK; else echo CXX_NONE; fi',\n `if [ -e ${shq(`${runtimeDir}/bin/pm2`)} ] || [ -e ${shq(`${runtimeDir}/bin/node`)} ] || [ -L ${shq(`${runtimeDir}/bin/node`)} ]; then echo BIN_PRESENT; fi`,\n `if grep -q ${shq(WRAPPER_MARK)} ${shq(`${runtimeDir}/bin/pm2`)} 2>/dev/null; then echo BIN_OURS; fi`, // an unpack cut off before its lock\n // a live daemon, not just a socket file left behind by a dead one\n // biome-ignore lint/suspicious/noTemplateCurlyInString: shell parameter expansion, for the host's sh\n 'H=\"${PM2_HOME:-$HOME/.pm2}\"; if [ -f \"$H/pm2.pid\" ] && kill -0 \"$(cat \"$H/pm2.pid\")\" 2>/dev/null; then echo DAEMON_UP; fi',\n `if [ -f ${shq(manifestPath)} ]; then printf 'MANIFEST %s\\\\n' \"$(head -n 1 ${shq(manifestPath)})\"; else echo MANIFEST_NONE; fi`,\n `echo ${LOCK_MARK}`,\n `cat ${shq(`${runtimeDir}/lock.json`)} 2>/dev/null || true`,\n ].join('\\n');\n}\n\n/** A lock.json mcproc wrote (its own fields), else null: an empty or foreign file proves nothing about bin/. */\nfunction mcprocLock(v: unknown): RuntimeLock | null {\n const o = v as Partial<RuntimeLock> | null;\n return o &&\n typeof o === 'object' &&\n typeof o.mcproc === 'string' &&\n typeof o.pm2 === 'string' &&\n typeof o.pm2_sha256 === 'string'\n ? (o as RuntimeLock)\n : null;\n}\n\nexport function parseUnpackProbe(stdout: string): HostFacts {\n const start = stdout.indexOf(UNPACK_MARK);\n const lockAt = stdout.indexOf(LOCK_MARK);\n const head = stdout\n .slice(\n start < 0 ? 0 : start + UNPACK_MARK.length,\n lockAt < 0 ? undefined : lockAt\n )\n .split('\\n')\n .map((l) => l.trim())\n .filter(Boolean);\n const lockText =\n lockAt < 0 ? '' : stdout.slice(lockAt + LOCK_MARK.length).trim();\n let lock: RuntimeLock | null = null;\n if (lockText) {\n try {\n lock = mcprocLock(JSON.parse(lockText));\n } catch {\n lock = null;\n }\n }\n const nodeLine = head.find((l) => l.startsWith('NODE '));\n const mf = head.find((l) => l.startsWith('MANIFEST'));\n const manifest: HostFacts['manifest'] =\n !mf || mf === 'MANIFEST_NONE'\n ? 'absent'\n : mf.slice('MANIFEST'.length).trim().startsWith(COPY_HEADER)\n ? 'mcproc-copy'\n : 'hand-written';\n // bin/ is ours with a lock mcproc wrote, or with the wrapper it writes (switched before the node link, so an unpack cut off in between still has it)\n return {\n unameSm: head[0] ?? '',\n musl: head.includes('MUSL'),\n node: nodeLine ? nodeLine.slice(5).trim() : null,\n tar: head.includes('TAR_OK'),\n cxx: head.includes('CXX_OK'),\n foreignBin:\n head.includes('BIN_PRESENT') &&\n lock === null &&\n !head.includes('BIN_OURS'),\n daemonUp: head.includes('DAEMON_UP'),\n manifest,\n lock,\n };\n}\n","import fs from 'node:fs';\nimport { McprocError } from '../errors.js';\nimport type { Manifest } from '../manifest.js';\nimport { readHostMemory, type HostMemory } from '../memory.js';\nimport type { Pm2Process } from '../pm2.js';\nimport type { Context } from '../resolve.js';\nimport { stateDir } from '../state.js';\nimport { WATCHER_NAME, WATCHER_NS } from './ensure.js';\nimport { LeaseStore, type Lease } from './store.js';\n\n/** The host's queue as `leases` shows it: the state directory, the memory reading, the watcher and every lease. */\nexport interface LeasesView {\n state_dir: string;\n /** the host's memory; null without a local context or where there is no reading */\n memory: HostMemory | null;\n /** the watcher's pm2 process; null without a local context */\n watcher: { online: boolean; pid: number | null } | null;\n /** oldest first, each with its 1-based position among the pending ones (0 when not pending) */\n leases: (Lease & { position: number })[];\n}\n\n/**\n * The host's queue as `leases` shows it: every lease with its position, the memory reading and the watcher's state when\n * a context is given. A read never fails on the extras: the prune is skipped when the lease lock cannot be taken, and\n * the memory or the watcher is null when meminfo or pm2's list does not answer.\n */\nexport async function leasesView(\n dir = stateDir(),\n ctx?: Context\n): Promise<LeasesView> {\n const store = new LeaseStore(dir);\n // a host that never queued anything keeps no state directory: the read does not make one\n if (fs.existsSync(store.dir))\n await store\n .withLock(() => store.prune())\n .catch(() => {\n /* the lock is busy: the ended leases are pruned by a later read or the watcher */\n });\n const leases = store\n .list()\n .map((l) => ({ ...l, position: store.positionOf(l.id) }));\n let memory: HostMemory | null = null;\n let watcher: LeasesView['watcher'] = null;\n if (ctx?.host.local) {\n memory = await readHostMemory(ctx.transport, ctx.host).catch(() => null);\n watcher = await ctx.pm2.jlist().then(watcherIn, () => null);\n }\n return { state_dir: dir, memory, watcher, leases };\n}\n\n/** The watcher's state in a pm2 list: online or not, and its pid (null when it has none). */\nexport function watcherIn(procs: Pm2Process[]): {\n online: boolean;\n pid: number | null;\n} {\n const w = procs.find(\n (p) => p.name === WATCHER_NAME && p.namespace === WATCHER_NS\n );\n return {\n online: Boolean(w && w.status === 'online'),\n pid: w && w.pid > 0 ? w.pid : null,\n };\n}\n\n/** A lease that covers apps not running yet, as ls and wait show it: queued (its position) or starting. */\nexport interface LeaseView {\n id: string;\n state: 'pending' | 'starting';\n /** 1-based place in the queue, the starting leases counted ahead; 0 for a starting lease */\n position: number;\n waiting_for: string | null;\n apps: string[];\n}\n\n/**\n * The pending and starting leases of one checkout, with their queue positions: what ls and wait show for apps that are\n * not running yet; none when the lease directory cannot be read (its permissions, a file in its place).\n */\nexport function leasesCovering(\n dir: string,\n m: Pick<Manifest, 'root' | 'project'>\n): LeaseView[] {\n const store = new LeaseStore(dir);\n try {\n return store\n .list()\n .filter(\n (l): l is Lease & { state: 'pending' | 'starting' } =>\n (l.state === 'pending' || l.state === 'starting') &&\n l.root === m.root &&\n l.project === m.project\n )\n .map((l) => ({\n id: l.id,\n state: l.state,\n position: store.positionOf(l.id),\n waiting_for: l.waiting_for,\n apps: l.apps,\n }));\n } catch {\n // the queue's bookkeeping must not fail ls, monit or wait: the apps are shown as pm2 has them\n return [];\n }\n}\n\n/**\n * Cancels a pending lease, or a starting exec lease (it has no child to end: its owner's wait ends on the cancel); a\n * starting start or an ended lease is refused (LEASE_NOT_PENDING).\n */\nexport function cancelLease(id: string, dir = stateDir()): Promise<Lease> {\n const store = new LeaseStore(dir);\n return store.withLock(() => {\n const l = store.get(id);\n // the store lets a starting lease be cancelled (a stop does that, ending its child); a request may only end a\n // starting exec, which has no child\n if (\n l &&\n l.state !== 'pending' &&\n !(l.state === 'starting' && l.kind === 'exec')\n )\n throw new McprocError(\n 'LEASE_NOT_PENDING',\n `lease ${id} is ${l.state}, only a pending lease or a starting exec can be cancelled`,\n {\n hint:\n l.kind !== 'exec'\n ? 'Stop its target to end a starting or running start.'\n : l.state === 'running'\n ? 'A running exec frees its lease when its command exits: wait for it to end.'\n : 'The exec has ended: there is nothing left to cancel.',\n }\n );\n return store.transition(id, 'cancelled', {\n error: 'cancelled by request',\n });\n });\n}\n","import type { Host } from './manifest.js';\nimport { MARK, MEM_SNIPPET } from '../shell/snippets.js';\nimport { ensureOk } from '../transport/index.js';\nimport type { Transport } from '../transport/types.js';\n\n/** What the host has and what it can still give, in MiB, from /proc/meminfo. */\nexport interface HostMemory {\n total_mib: number;\n available_mib: number;\n}\n\nconst KB = 1024;\n\n/** The MemTotal and MemAvailable lines of /proc/meminfo (kB) as MiB; null when either is missing. */\nexport function parseMeminfo(text: string): HostMemory | null {\n let total: number | null = null;\n let available: number | null = null;\n for (const raw of text.split('\\n')) {\n const m = /^(MemTotal|MemAvailable):\\s+(\\d+)\\s*kB/.exec(raw.trim());\n if (!m) continue;\n const mib = Math.floor(Number(m[2]) / KB);\n if (m[1] === 'MemTotal') total = mib;\n else available = mib;\n }\n return total !== null && available !== null\n ? { total_mib: total, available_mib: available }\n : null;\n}\n\nconst UNIT_MIB: Record<string, number> = {\n B: 1 / (KB * KB),\n KB: 1 / KB,\n KIB: 1 / KB,\n MB: 1,\n MIB: 1,\n GB: KB,\n GIB: KB,\n TB: KB * KB,\n TIB: KB * KB,\n};\n\n/** `docker stats --no-stream --format '{{.Name}}\\t{{.MemUsage}}'` lines (\"name\\t27.06MiB / 31.09GiB\") as MiB per container, rounded up. */\nexport function parseDockerStats(text: string): Map<string, number> {\n const out = new Map<string, number>();\n for (const raw of text.split('\\n')) {\n const [name, usage] = raw.split('\\t');\n const m = /^\\s*([\\d.]+)\\s*([KMGT]?i?B)/i.exec(usage ?? '');\n if (!name || !m) continue;\n const factor = UNIT_MIB[m[2].toUpperCase()];\n if (factor === undefined) continue;\n out.set(name.trim(), Math.ceil(Number(m[1]) * factor));\n }\n return out;\n}\n\n/** One small round trip for the host's memory alone, for the watcher between probes; null where there is no /proc/meminfo. */\nexport async function readHostMemory(\n transport: Transport,\n host: Host\n): Promise<HostMemory | null> {\n const res = ensureOk(await transport.exec(MEM_SNIPPET), host, 'meminfo');\n const i = res.stdout.indexOf(MARK.MEM);\n return i < 0 ? null : parseMeminfo(res.stdout.slice(i + MARK.MEM.length));\n}\n","import os from 'node:os';\nimport path from 'node:path';\n\n/** The host state directory: MCPROC_STATE_DIR, else $XDG_STATE_HOME/mcproc, else ~/.local/state/mcproc. Leases and the slot registry live there, per host, never per project. */\nexport function stateDir(env: NodeJS.ProcessEnv = process.env): string {\n if (env.MCPROC_STATE_DIR) return path.resolve(env.MCPROC_STATE_DIR);\n return path.join(\n env.XDG_STATE_HOME || path.join(os.homedir(), '.local', 'state'),\n 'mcproc'\n );\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { LOG_STAMP } from '../ecosystem.js';\nimport { McprocError } from '../errors.js';\nimport type { Context } from '../resolve.js';\nimport { stateDir } from '../state.js';\nimport { LeaseStore } from './store.js';\n\n/** The pm2 process name of the host's lease watcher. */\nexport const WATCHER_NAME = 'mcproc-watcher';\n/** The pm2 namespace the lease watcher runs in, apart from every project's. */\nexport const WATCHER_NS = 'mcproc';\n/** The note an idle watcher leaves in the state directory as it exits: `{ \"exiting_at\": \"<ISO>\" }`. */\nexport const WATCHER_NOTE = 'watcher.json';\n/** An exit note younger than this means the online watcher is on its way out. */\nconst EXIT_FRESH_MS = 5000;\n/** How long a start waits for a leaving watcher to be gone before it trusts it after all. */\nconst EXIT_WAIT_MS = 3000;\nconst EXIT_POLL_MS = 250;\n\n/** When the watcher last noted its idle exit in `dir`, in epoch ms; null without a readable note. */\nfunction exitingAt(dir: string): number | null {\n try {\n const v = JSON.parse(\n fs.readFileSync(path.join(dir, WATCHER_NOTE), 'utf8')\n ) as { exiting_at?: unknown };\n const at =\n typeof v.exiting_at === 'string' ? Date.parse(v.exiting_at) : Number.NaN;\n return Number.isFinite(at) ? at : null;\n } catch {\n return null;\n }\n}\n\n/** The CLI file the watcher's node runs: MCPROC_CLI_ENTRY, else the running CLI's own entry when it is the built bundle. */\nexport function watcherEntry(\n env: NodeJS.ProcessEnv = process.env,\n argv: string[] = process.argv\n): string {\n if (env.MCPROC_CLI_ENTRY) return path.resolve(env.MCPROC_CLI_ENTRY);\n const own = argv[1] ?? '';\n if (own.endsWith('cli.js')) return path.resolve(own);\n throw new McprocError(\n 'NOT_STARTED',\n `cannot launch the lease watcher: this mcproc runs from ${own || 'an unknown entry'}, not from a built cli.js`,\n {\n hint: 'Set MCPROC_CLI_ENTRY to the dist/cli.js the watcher should run (a dev checkout: build it to the side).',\n }\n );\n}\n\n/**\n * The watcher as one pm2 process per daemon: online already, or started from an ecosystem file in the state directory.\n * An online watcher without a fresh exit note is trusted at once; one whose note is fresh is leaving after an idle exit\n * and is waited for (up to EXIT_WAIT_MS) before the lease lock is taken, so the lock is never held through that wait.\n * Then, under the lock, pm2 is asked again: an online watcher is trusted unless it is the leaving one (its note still in\n * place), else a fresh one is started, so two starts that queue at once launch one watcher (a second launch would\n * restart the first, and its tree).\n */\nexport async function ensureWatcher(\n ctx: Context,\n dir = stateDir()\n): Promise<'online' | 'started'> {\n let leaving: number | null = null;\n if (await watcherOnline(ctx)) {\n // no fresh note: it stays, since it cannot leave while a lease is pending (see the watcher's leaveIdle)\n const at = exitingAt(dir);\n if (at === null || Date.now() - at >= EXIT_FRESH_MS) return 'online';\n leaving = at;\n const until = Date.now() + EXIT_WAIT_MS;\n while (Date.now() < until) {\n await new Promise((r) => setTimeout(r, EXIT_POLL_MS));\n if (!(await watcherOnline(ctx))) break;\n }\n }\n return new LeaseStore(dir).withLock(() => lookAndLaunch(ctx, dir, leaving));\n}\n\n/** Whether the watcher's pm2 process is online on the context's daemon. */\nasync function watcherOnline(ctx: Context): Promise<boolean> {\n return (await ctx.pm2.jlist()).some(\n (p) =>\n p.name === WATCHER_NAME &&\n p.namespace === WATCHER_NS &&\n p.status === 'online'\n );\n}\n\n/**\n * ensureWatcher's look and launch, under the lease lock: an online watcher is left alone, else a fresh one is started.\n * `leaving` is the exit note a start waited on: while that note is still in place (no launch took it meanwhile), the\n * online watcher is the one on its way out and a fresh one is started over it, which is safe since it passed leaveIdle\n * and so runs no start.\n */\nasync function lookAndLaunch(\n ctx: Context,\n dir: string,\n leaving: number | null\n): Promise<'online' | 'started'> {\n if (\n (await watcherOnline(ctx)) &&\n (leaving === null || exitingAt(dir) !== leaving)\n )\n return 'online';\n const entry = watcherEntry();\n const file = path.join(dir, 'watcher.ecosystem.json');\n fs.mkdirSync(dir, { recursive: true });\n // a fresh watcher: the note of the one before it no longer applies\n fs.rmSync(path.join(dir, WATCHER_NOTE), { force: true });\n fs.writeFileSync(\n file,\n JSON.stringify(\n {\n apps: [\n {\n name: WATCHER_NAME,\n namespace: WATCHER_NS,\n cwd: dir,\n script: process.execPath,\n args: [entry, 'watch-leases'],\n interpreter: 'none',\n // the watcher reads this state directory, drives this daemon and spawns its children from this same\n // bundle, whatever the shell pm2 inherits\n env: {\n MCPROC_STATE_DIR: dir,\n ...(process.env.MCPROC_CLI_ENTRY\n ? { MCPROC_CLI_ENTRY: entry }\n : {}),\n ...(ctx.pm2.env() ?? {}),\n },\n autorestart: false,\n treekill: true,\n log_date_format: LOG_STAMP,\n },\n ],\n },\n null,\n 2\n )\n );\n await ctx.pm2.startOrRestart(file, WATCHER_NAME);\n return 'started';\n}\n","import path from 'node:path';\nimport type { App, Host, Manifest } from './manifest.js';\nimport { pm2Name } from './pm2.js';\n\n/** The stamp pm2 writes before every log line; mcproc's log readers accept it and the older second-only form. */\nexport const LOG_STAMP = 'YYYY-MM-DDTHH:mm:ss.SSS';\n\n/**\n * In front of a one-shot app's command. pm2 records exit_code 0 for a process killed by a signal, so a plain\n * `pm2 stop` would read as a successful run; the shell runs the trap after its foreground child exits and leaves\n * 130 (SIGINT) or 143 (SIGTERM) instead, which the status word reads as \"stopped\". Natural exits pass through.\n */\nexport const STOP_TRAP = \"trap 'exit 130' INT; trap 'exit 143' TERM; \";\n\nexport interface Pm2AppConfig {\n name: string;\n namespace: string;\n cwd: string;\n script: string;\n args: string[];\n interpreter: 'none';\n env: Record<string, string>;\n autorestart: boolean;\n treekill: true;\n /** pm2's stamp before every log line, to the millisecond (pm2 would overwrite it with seconds if `time` were set) */\n log_date_format: string;\n watch?: boolean | string[];\n watch_delay?: number;\n ignore_watch?: string[];\n [k: string]: unknown;\n}\n\nexport function appCwd(host: Host, app: App): string {\n return path.posix.resolve(host.cwd, app.cwd);\n}\n\nexport function generatedDir(host: Host): string {\n return path.posix.join(host.cwd, '.mcproc', '.generated');\n}\n\nexport function ecosystemPath(host: Host): string {\n return path.posix.join(generatedDir(host), 'ecosystem.json');\n}\n\nexport function buildEcosystem(\n m: Manifest,\n host: Host\n): { apps: Pm2AppConfig[] } {\n const apps = Object.values(m.apps).map((app): Pm2AppConfig => {\n const base: Pm2AppConfig = {\n name: pm2Name(m.project, app.name),\n namespace: m.project,\n cwd: appCwd(host, app),\n script: host.shell.bin,\n args: [\n ...host.shell.flags,\n app.autorestart ? app.run : STOP_TRAP + app.run,\n ],\n interpreter: 'none',\n env: { ...app.env, ...host.env },\n autorestart: app.autorestart,\n treekill: true,\n log_date_format: LOG_STAMP,\n };\n if (app.watch !== undefined) {\n base.watch = app.watch;\n base.watch_delay = app.watch_delay;\n }\n if (app.ignore_watch) base.ignore_watch = app.ignore_watch;\n return { ...base, ...app.pm2 } as Pm2AppConfig; // protected keys were rejected at validation\n });\n return { apps };\n}\n","import crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { McprocError } from '../errors.js';\n\n/** Where a lease stands: queued (pending), handed to a watcher (starting), up (running), or ended (freed, cancelled, failed). */\nexport type LeaseState =\n | 'pending'\n | 'starting'\n | 'running'\n | 'freed'\n | 'cancelled'\n | 'failed';\n/** Whether a lease claims memory for a start of apps or for a one-off exec. */\nexport type LeaseKind = 'start' | 'exec';\n/** Where one app's share of an estimate came from: `declared`, `measured from slot N`, or `none`. */\nexport interface LeaseSource {\n mib: number;\n source: string;\n}\n/** One claim on the host's memory: a start of apps, or a one-off exec; its estimate and where it stands in the queue. */\nexport interface Lease {\n id: string;\n seq: number;\n state: LeaseState;\n kind: LeaseKind;\n project: string;\n root: string;\n slot: number | null;\n repo: string | null;\n target: string;\n /** the `--host` the caller gave the start, else null: the watcher's child starts the target again on the same hosts */\n host: string | null;\n apps: string[];\n reload: boolean;\n estimate_mib: number;\n need_mib: number;\n margin: number;\n reserve_mib: number;\n sources: Record<string, LeaseSource>;\n note: string | null;\n requester_pid: number;\n /** the process running the start: the watcher's child while starting, the admitted caller while a start admitted at once runs */\n child_pid: number | null;\n queued_at: string;\n admitted_at: string | null;\n running_at: string | null;\n ended_at: string | null;\n waiting_for: string | null;\n error: string | null;\n exit_code: number | null;\n}\n/** The fields a caller supplies to create a lease; the store fills in the id, sequence and times. */\nexport type NewLease = Omit<\n Lease,\n | 'id'\n | 'seq'\n | 'state'\n | 'child_pid'\n | 'queued_at'\n | 'admitted_at'\n | 'running_at'\n | 'ended_at'\n | 'waiting_for'\n | 'error'\n | 'exit_code'\n>;\n\n/** The lease state machine: for each state, the states it may move to. */\nexport const ALLOWED: Record<LeaseState, readonly LeaseState[]> = {\n pending: ['starting', 'running', 'cancelled'],\n starting: ['running', 'failed', 'cancelled'],\n running: ['freed'],\n freed: [],\n cancelled: [],\n failed: [],\n};\nconst ENDED = new Set<LeaseState>(['freed', 'cancelled', 'failed']);\n/** Age after which a lock whose holder is dead may be broken, in milliseconds. */\nexport const LOCK_STALE_MS = 30_000;\nconst LOCK_WAIT_MS = 10_000;\nconst PRUNE_AFTER_MS = 24 * 3600 * 1000;\n\n/** Whether a process with that pid exists, as `kill -0` tells it (a process of another user, EPERM, exists too). */\nexport function pidAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (e) {\n return (e as NodeJS.ErrnoException).code === 'EPERM';\n }\n}\n\n/** How long a lease's live starter is trusted after its start began, in milliseconds: ten minutes. */\nexport const STARTER_TRUST_MS = 600_000;\n\n/**\n * Whether the process running a lease's start is still there (see `child_pid`) and the start began (`running_at`, else\n * `admitted_at`) less than STARTER_TRUST_MS before `now`: a start that runs may not have its apps up yet, and a start\n * admitted at once inside a long-lived process (the MCP server) whose clear failed pins its lease no longer than that.\n */\nexport function starterAlive(\n l: Pick<Lease, 'child_pid' | 'running_at' | 'admitted_at'>,\n now = Date.now()\n): boolean {\n if (typeof l.child_pid !== 'number') return false;\n const began = l.running_at ?? l.admitted_at;\n if (began === null || !(now - Date.parse(began) < STARTER_TRUST_MS))\n return false;\n return pidAlive(l.child_pid);\n}\n\n/** The tokens of the locks this process holds right now: a lock naming this pid with another token is a leftover. */\nconst LIVE_TOKENS = new Set<string>();\n/** What a crashed holder or breaker leaves: token files, and guard directories moved aside (`.lock.break.<token>.stale`). */\nconst STRAY = /^\\.lock\\..+\\.(tmp|stale)$/;\n/** What a stale-lock break can come to: the lock taken by the breaker, a retry at once, or a wait before the next try. */\ntype BreakResult = 'taken' | 'retry' | 'wait';\n\ninterface Held {\n pid: number;\n at: number;\n token: string;\n}\n/** Parses the content of a lock file, or null when it is empty, half-written or of another shape. */\nfunction parseHeld(raw: string): Held | null {\n try {\n const v = JSON.parse(raw) as Partial<Held>;\n return typeof v.pid === 'number' &&\n typeof v.at === 'number' &&\n typeof v.token === 'string'\n ? (v as Held)\n : null;\n } catch {\n return null;\n }\n}\n/** Reads a lock file's holder, or null when the file is missing or unreadable as a holder. */\nfunction readHeld(file: string): Held | null {\n try {\n return parseHeld(fs.readFileSync(file, 'utf8'));\n } catch {\n return null;\n }\n}\n\n/**\n * The host's leases as files under `<state>/leases`: one JSON per lease named by sequence and id, a `.seq` counter,\n * and a `.lock` around every change, hard-linked atomically from a token file its holder wrote first. Reads need no\n * lock: a write is a rename, so a reader sees a whole file or none. Every mutator (`create`, `transition`, `patch`,\n * `prune`) is called under `withLock`, which is not reentrant: a mutator never takes the lock itself.\n */\nexport class LeaseStore {\n readonly dir: string;\n private readonly now: () => number;\n private readonly pid: number;\n private readonly beforeUnlink: (() => void) | undefined;\n /**\n * Opens the lease directory under the given state directory, with optional clock and pid overrides for tests;\n * `beforeUnlink` (tests only) runs while a breaker holds the break guard, before the re-read that decides the unlink.\n */\n constructor(\n stateDir: string,\n deps: { now?: () => number; pid?: number; beforeUnlink?: () => void } = {}\n ) {\n this.dir = path.join(stateDir, 'leases');\n this.now = deps.now ?? (() => Date.now());\n this.pid = deps.pid ?? process.pid;\n this.beforeUnlink = deps.beforeUnlink;\n }\n private file(l: Pick<Lease, 'seq' | 'id'>): string {\n return path.join(\n this.dir,\n `${String(l.seq).padStart(6, '0')}-${l.id}.json`\n );\n }\n private stamp(): string {\n return new Date(this.now()).toISOString();\n }\n private write(l: Lease): Lease {\n fs.mkdirSync(this.dir, { recursive: true });\n const f = this.file(l);\n const tmp = `${f}.${this.pid}.tmp`;\n fs.writeFileSync(tmp, JSON.stringify(l, null, 2));\n fs.renameSync(tmp, f);\n return l;\n }\n /**\n * Runs `fn` holding the lock (not reentrant). A lock is stale when it is older than LOCK_STALE_MS and its holder is\n * dead, when it was taken before this boot, when it names this process with a token this process does not hold, or,\n * unparseable, when its file's mtime is older than LOCK_STALE_MS; a stale lock is broken under the break guard (see\n * breakIfStale), never by moving it aside, so the lock path is never left free while a live holder has it.\n */\n async withLock<T>(fn: () => Promise<T> | T): Promise<T> {\n fs.mkdirSync(this.dir, { recursive: true });\n const lock = path.join(this.dir, '.lock');\n const token = `${this.pid}-${crypto.randomBytes(6).toString('hex')}`;\n const tmp = path.join(this.dir, `.lock.${token}.tmp`);\n const writeToken = () => {\n fs.mkdirSync(this.dir, { recursive: true });\n fs.writeFileSync(\n tmp,\n JSON.stringify({ pid: this.pid, at: this.now(), token })\n );\n };\n writeToken();\n const start = Date.now();\n let swept = false;\n try {\n for (;;) {\n if (this.tryLink(tmp, lock, writeToken)) break;\n if (!swept) {\n this.sweepStrays();\n swept = true;\n }\n const r = this.breakIfStale(lock, token, () =>\n this.tryLink(tmp, lock, writeToken)\n );\n if (r === 'taken') break;\n if (r === 'retry') continue;\n if (Date.now() - start > LOCK_WAIT_MS)\n throw new McprocError(\n 'TIMEOUT',\n `the lease lock ${lock} is held by pid ${readHeld(lock)?.pid ?? '?'} for more than ${LOCK_WAIT_MS / 1000} s`,\n { hint: 'If that process is gone, remove the file.' }\n );\n await new Promise((r) => setTimeout(r, 50));\n }\n } finally {\n fs.rmSync(tmp, { force: true });\n }\n LIVE_TOKENS.add(token);\n try {\n return await fn();\n } finally {\n // the token leaves the live set before the release: a release that throws must not leave it live\n try {\n LIVE_TOKENS.delete(token);\n } finally {\n this.release(lock, token);\n }\n }\n }\n /** Whether a parsed lock is a leftover: from before this boot, this process's own but not held, or old with a dead holder. */\n private heldStale(held: Held): boolean {\n // pids are reused after a reboot and the state directory outlives it: a lock from before the boot is nobody's\n if (held.at < this.now() - os.uptime() * 1000) return true;\n // this process knows every lock it holds: one naming it with another token is a leftover (a release that threw)\n if (held.pid === process.pid && !LIVE_TOKENS.has(held.token)) return true;\n return this.now() - held.at > LOCK_STALE_MS && !pidAlive(held.pid);\n }\n /**\n * Removes the `.lock.*.tmp` files and the `.lock.*.stale` entries (guard directories moved aside) a crashed holder or\n * breaker left, once older than LOCK_STALE_MS by mtime.\n */\n private sweepStrays(): void {\n let names: string[];\n try {\n names = fs.readdirSync(this.dir);\n } catch {\n return;\n }\n for (const n of names) {\n if (!STRAY.test(n)) continue;\n const f = path.join(this.dir, n);\n if (this.mtimeAgeMs(f) > LOCK_STALE_MS)\n fs.rmSync(f, { recursive: true, force: true });\n }\n }\n /**\n * Takes the lock by hard-linking the prepared file, which is atomic: the lock never exists empty; false when it is\n * held. A token file that is gone (a sweep took it while this process stalled for longer than LOCK_STALE_MS) is\n * written again by `rewrite` and the link is tried once more.\n */\n private tryLink(tmp: string, lock: string, rewrite: () => void): boolean {\n for (let attempt = 0; ; attempt++) {\n try {\n fs.linkSync(tmp, lock);\n return true;\n } catch (e) {\n const code = (e as NodeJS.ErrnoException).code;\n if (code === 'EEXIST') return false;\n if (code === 'ENOENT' && attempt === 0 && !fs.existsSync(tmp)) {\n rewrite();\n continue;\n }\n throw e;\n }\n }\n }\n /** Whether the lock as read now is the one judged stale: the same token, or for an unparseable one, still unparseable and old. */\n private stillStale(lock: string, judged: Held | null): boolean {\n let raw: string;\n try {\n raw = fs.readFileSync(lock, 'utf8');\n } catch (e) {\n if ((e as NodeJS.ErrnoException).code === 'ENOENT') return false;\n throw e;\n }\n const now = parseHeld(raw);\n return judged\n ? now?.token === judged.token\n : now === null && this.mtimeAgeMs(lock) > LOCK_STALE_MS;\n }\n /**\n * Whether the break guard was left by a breaker that died with it: its holder is older than LOCK_STALE_MS and dead,\n * or, with no readable holder, the directory's mtime is older than LOCK_STALE_MS.\n */\n private guardStale(guard: string): boolean {\n const held = readHeld(path.join(guard, 'holder'));\n if (held)\n return this.now() - held.at > LOCK_STALE_MS && !pidAlive(held.pid);\n return this.mtimeAgeMs(guard) > LOCK_STALE_MS;\n }\n /**\n * Breaks the lock when its holder is judged stale. The breaker first takes the guard `<lock>.break`, a directory made\n * with mkdir (atomic, one winner), its holder written inside; with the guard busy it waits, unless the guard is\n * itself stale: then it is moved aside (one winner) and removed. Under the guard the lock is read again, and only\n * the very lock judged stale is unlinked, the breaker's own token file linked in its place at once (`take`; a lock\n * linked in between by a plain acquirer wins). The guard is removed in every case. Residual, a double-hold window:\n * when a breaker dies holding the guard, two breakers that judge that guard stale within microseconds of each other\n * can each move a guard aside (the second one the first's fresh guard), both break under their own guard and both\n * hold the lock. It needs a crashed guard holder plus two breakers inside microseconds.\n */\n private breakIfStale(\n lock: string,\n token: string,\n take: () => boolean\n ): BreakResult {\n let raw: string;\n try {\n raw = fs.readFileSync(lock, 'utf8');\n } catch (e) {\n if ((e as NodeJS.ErrnoException).code === 'ENOENT') return 'retry';\n throw e;\n }\n const held = parseHeld(raw);\n const stale = held\n ? this.heldStale(held)\n : this.mtimeAgeMs(lock) > LOCK_STALE_MS;\n if (!stale) return 'wait';\n const guard = `${lock}.break`;\n try {\n fs.mkdirSync(guard);\n } catch (e) {\n if ((e as NodeJS.ErrnoException).code !== 'EEXIST') throw e;\n if (!this.guardStale(guard)) return 'wait';\n const moved = `${guard}.${token}.stale`;\n try {\n fs.renameSync(guard, moved);\n } catch (err) {\n // someone else moved it first\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return 'retry';\n throw err;\n }\n fs.rmSync(moved, { recursive: true, force: true });\n return 'retry';\n }\n try {\n fs.writeFileSync(\n path.join(guard, 'holder'),\n JSON.stringify({ pid: this.pid, at: this.now(), token })\n );\n this.beforeUnlink?.();\n // a lock that changed since it was judged belongs to a fresh holder: it is left alone\n if (!this.stillStale(lock, held)) return 'retry';\n try {\n fs.unlinkSync(lock);\n } catch (e) {\n if ((e as NodeJS.ErrnoException).code !== 'ENOENT') throw e;\n }\n // EEXIST: a plain acquirer linked first and holds the lock; the loop waits for it\n return take() ? 'taken' : 'retry';\n } finally {\n fs.rmSync(guard, { recursive: true, force: true });\n }\n }\n /** Age of a lock file by its modification time on the file system's clock; 0 when it is gone. */\n private mtimeAgeMs(lock: string): number {\n try {\n return Date.now() - fs.statSync(lock).mtimeMs;\n } catch {\n return 0;\n }\n }\n /** Unlinks the lock only when it still carries this holder's token; a lock it does not own is never removed. */\n private release(lock: string, token: string): void {\n if (readHeld(lock)?.token === token) fs.rmSync(lock, { force: true });\n }\n /** Every readable lease, in sequence order; a half-written file is skipped. */\n list(): Lease[] {\n if (!fs.existsSync(this.dir)) return [];\n return fs\n .readdirSync(this.dir)\n .filter((f) => f.endsWith('.json'))\n .sort()\n .flatMap((f) => {\n try {\n return [\n JSON.parse(\n fs.readFileSync(path.join(this.dir, f), 'utf8')\n ) as Lease,\n ];\n } catch {\n return []; // half-written by a crashed writer: skipped\n }\n });\n }\n /** The lease with this id, or null when there is none. */\n get(id: string): Lease | null {\n return this.list().find((l) => l.id === id) ?? null;\n }\n private nextSeq(): number {\n const f = path.join(this.dir, '.seq');\n const onDisk = Math.max(\n 0,\n ...fs\n .readdirSync(this.dir)\n .filter((name) => name.endsWith('.json'))\n .map((name) => Number(name.split('-')[0]))\n .filter(Number.isFinite)\n );\n const parsed = fs.existsSync(f) ? Number(fs.readFileSync(f, 'utf8')) : 0;\n const n = Math.max(Number.isFinite(parsed) ? parsed : 0, onDisk);\n const tmp = `${f}.${this.pid}.tmp`;\n fs.writeFileSync(tmp, String(n + 1));\n fs.renameSync(tmp, f);\n return n + 1;\n }\n /** A new lease, pending (queued) or running (admitted at once), with `child_pid` the process running its start; call it under the lock. */\n async create(\n input: NewLease,\n state: 'pending' | 'running',\n opts: { child_pid?: number | null } = {}\n ): Promise<Lease> {\n fs.mkdirSync(this.dir, { recursive: true });\n const at = this.stamp();\n const l: Lease = {\n ...input,\n id: `l_${crypto\n .randomBytes(8)\n .toString('base64url')\n .replace(/[^a-z0-9]/gi, '')\n .toLowerCase()\n .padEnd(10, '0')\n .slice(0, 10)}`,\n seq: this.nextSeq(),\n state,\n child_pid: opts.child_pid ?? null,\n queued_at: at,\n admitted_at: state === 'running' ? at : null,\n running_at: state === 'running' ? at : null,\n ended_at: null,\n waiting_for: null,\n error: null,\n exit_code: null,\n };\n return this.write(l);\n }\n /** Moves a lease along ALLOWED, stamping the time it reached the new state; `patch` sets other fields with it. */\n async transition(\n id: string,\n to: LeaseState,\n patch: Partial<Lease> = {}\n ): Promise<Lease> {\n const l = this.get(id);\n if (!l) throw new McprocError('BAD_ARGUMENT', `no lease ${id}`);\n if (!ALLOWED[l.state].includes(to))\n throw new McprocError(\n to === 'cancelled' ? 'LEASE_NOT_PENDING' : 'BAD_ARGUMENT',\n `lease ${id} is ${l.state}, cannot become ${to}`,\n {\n hint:\n to === 'cancelled'\n ? 'Only a pending or starting lease can be cancelled; stop the target to free a running one.'\n : undefined,\n }\n );\n const at = this.stamp();\n const next: Lease = { ...l, ...patch, state: to };\n if (to === 'starting') next.admitted_at = at;\n if (to === 'running') {\n next.admitted_at ??= at;\n next.running_at = at;\n }\n if (ENDED.has(to)) next.ended_at = at;\n if (to !== 'pending') next.waiting_for = null;\n return this.write(next);\n }\n /**\n * Rewrites fields of a lease without a state change: the watcher's `waiting_for`, a child pid, a refreshed estimate.\n * With `expect`, a lease that is no longer in that state is refused (BAD_ARGUMENT) and left as it was.\n */\n async patch(\n id: string,\n fields: Partial<Lease>,\n opts: { expect?: LeaseState } = {}\n ): Promise<Lease> {\n const l = this.get(id);\n if (!l) throw new McprocError('BAD_ARGUMENT', `no lease ${id}`);\n if (opts.expect && l.state !== opts.expect)\n throw new McprocError(\n 'BAD_ARGUMENT',\n `lease ${id} is ${l.state}, expected ${opts.expect}`\n );\n return this.write({\n ...l,\n ...fields,\n id: l.id,\n seq: l.seq,\n state: l.state,\n });\n }\n /** The queue: pending leases oldest first. */\n pending(): Lease[] {\n return this.list().filter((l) => l.state === 'pending');\n }\n /** The pending lease at the front of the queue, or null when the queue is empty. */\n head(): Lease | null {\n return this.pending()[0] ?? null;\n }\n /** 1-based place in the queue, the starting leases counted ahead of every pending one; 0 when the lease is not pending. */\n positionOf(id: string): number {\n const all = this.list();\n const i = all\n .filter((l) => l.state === 'pending')\n .findIndex((l) => l.id === id);\n if (i < 0) return 0;\n return all.filter((l) => l.state === 'starting').length + i + 1;\n }\n /** Removes ended leases older than `maxAgeMs` (a day); returns how many. */\n prune(maxAgeMs = PRUNE_AFTER_MS): number {\n let n = 0;\n for (const l of this.list()) {\n if (!ENDED.has(l.state) || !l.ended_at) continue;\n if (this.now() - Date.parse(l.ended_at) > maxAgeMs) {\n fs.rmSync(this.file(l), { force: true });\n n++;\n }\n }\n return n;\n }\n}\n","import { spawn } from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { createTransport } from '../../transport/index.js';\nimport { describeError, isMcprocError } from '../errors.js';\nimport { Fleet } from '../fleet.js';\nimport {\n DEFAULT_SHELL,\n type Host,\n loadManifest,\n type Manifest,\n parseShell,\n type Resources,\n SETTLE_DEFAULT_S,\n} from '../manifest.js';\nimport type { HostMemory } from '../memory.js';\nimport { readHostMemory } from '../memory.js';\nimport { findProcess, isRunning, type Pm2Process } from '../pm2.js';\nimport { connect, pickHost, prepare } from '../resolve.js';\nimport { abortableSleep } from '../wait.js';\nimport {\n admit,\n estimateApps,\n needOf,\n rampingMib,\n reserveMib,\n} from './admission.js';\nimport { WATCHER_NOTE } from './ensure.js';\nimport {\n listCheckout,\n measureSiblings,\n ownsManifest,\n registryOf,\n} from './siblings.js';\nimport {\n type Lease,\n type LeaseSource,\n type LeaseState,\n LeaseStore,\n pidAlive,\n starterAlive,\n} from './store.js';\n\n/** What the watcher reads and runs: the lease store, the host's memory, each lease's estimate, start and pm2 state, and its clock. */\nexport interface WatcherDeps {\n store: LeaseStore;\n memory(): Promise<HostMemory | null>;\n /** the head's estimate taken again, live: a sibling may have grown or gone since it was queued (an exec keeps its own); see watchLeases for when */\n estimate(l: Lease): Promise<{\n estimate_mib: number;\n need_mib: number;\n reserve_mib: number;\n sources: Record<string, LeaseSource>;\n }>;\n /** runs the admitted start and resolves when it has ended; the child itself writes running or failed */\n runStart(l: Lease): Promise<void>;\n onlineApps(l: Lease): Promise<Set<string>>;\n /** what a start of the lease's target would launch on this host now (see appsToLaunch): what its estimate must cover */\n targetApps(l: Lease): Promise<string[]>;\n settleMs(l: Lease): number;\n sleep(ms: number, signal?: AbortSignal): Promise<void>;\n now(): number;\n log(line: string): void;\n /** wakes the loop on a change of the queue; returns the unsubscribe */\n watch?(cb: () => void): () => void;\n /** whether the lease's checkout is gone (its root has no manifest of its own any more); absent, none is */\n gone?(l: Lease): boolean;\n}\n\n/**\n * Under the lock, moves a lease only while it is still in `from` (and, with `also`, while that still holds of it): a\n * change that landed meanwhile (a cancel, a stop, a starter recorded) is not written over.\n */\nasync function moveIf(\n store: LeaseStore,\n id: string,\n from: LeaseState,\n to: LeaseState,\n patch: Partial<Lease> = {},\n also: (cur: Lease) => boolean = () => true\n): Promise<Lease | null> {\n return store.withLock(async () => {\n const cur = store.get(id);\n return cur?.state === from && also(cur)\n ? store.transition(id, to, patch)\n : null;\n });\n}\n\n/** How long an exec lease may stay starting before the watcher fails it, in milliseconds: its owner polls every second. */\nconst EXEC_TURN_GRACE_MS = 60_000;\n\n/**\n * A running lease whose apps all left pm2 or stopped holds nothing, nor one whose checkout is gone (both spared while\n * their starter lives, for at most STARTER_TRUST_MS, see starterAlive); a starting one whose recorded child is gone is\n * over at once, one that never recorded a child after `stuckMs`. An exec lease belongs to its requester: once that\n * process is gone, a running one is freed and a starting one failed at once; a starting one its live owner has not\n * taken within EXEC_TURN_GRACE_MS (its wait ended without the cancel landing) is failed too, so it cannot hold the queue.\n */\nasync function reconcile(deps: WatcherDeps, stuckMs: number): Promise<void> {\n const { store } = deps;\n for (const l of store.list()) {\n try {\n if (l.kind === 'exec') {\n // nothing else ends it: its process died without its own cleanup (a kill, a closed terminal)\n if (\n (l.state === 'running' || l.state === 'starting') &&\n !pidAlive(l.requester_pid)\n )\n await moveIf(\n store,\n l.id,\n l.state,\n l.state === 'running' ? 'freed' : 'failed',\n { error: 'requester gone' }\n );\n else if (\n l.state === 'starting' &&\n l.admitted_at &&\n deps.now() - Date.parse(l.admitted_at) > EXEC_TURN_GRACE_MS\n )\n await moveIf(store, l.id, 'starting', 'failed', {\n error: 'the exec did not take its turn',\n });\n continue;\n }\n if (\n l.state === 'running' &&\n l.kind === 'start' &&\n !starterAlive(l, deps.now())\n ) {\n let gone = deps.gone?.(l) ?? false;\n let online = new Set<string>();\n if (!gone)\n try {\n online = await deps.onlineApps(l);\n } catch (e) {\n if (!isMcprocError(e) || e.code !== 'MANIFEST_NOT_FOUND') throw e;\n gone = true;\n }\n if (gone || !l.apps.some((a) => online.has(a)))\n await moveIf(\n store,\n l.id,\n 'running',\n 'freed',\n { error: gone ? 'checkout gone' : 'no app online any more' },\n (cur) => !starterAlive(cur, deps.now())\n );\n }\n if (l.state !== 'starting') continue;\n if (l.kind === 'start' && l.child_pid !== null) {\n if (!pidAlive(l.child_pid))\n await moveIf(\n store,\n l.id,\n 'starting',\n 'failed',\n { error: \"the start's child is gone\", child_pid: null },\n (cur) => cur.child_pid === l.child_pid\n );\n continue;\n }\n if (l.admitted_at && deps.now() - Date.parse(l.admitted_at) > stuckMs)\n await moveIf(\n store,\n l.id,\n 'starting',\n 'failed',\n { error: `the start did not answer within ${stuckMs / 1000} s` },\n (cur) => cur.child_pid === null\n );\n } catch (e) {\n deps.log(`error: ${l.id}: ${describeError(e)}`);\n }\n }\n}\n\n/** How long the waiting head's full estimate (its siblings measured) holds while the memory reading says it cannot fit yet. */\nconst ESTIMATE_EVERY_MS = 30_000;\n\n/** Records why the head still waits, under the lock and only while it is still pending: a cancel that landed meanwhile must not be written over. */\nasync function noteWaiting(\n store: LeaseStore,\n head: Lease,\n fields: Partial<Lease> & { waiting_for: string }\n): Promise<void> {\n await store\n .withLock(() => store.patch(head.id, fields, { expect: 'pending' }))\n .catch(() => undefined);\n}\n\n/**\n * One judgement of the head: admitted (and, for a start, run to its end), still waiting (its reason recorded), or\n * changed under the watcher (cancelled meanwhile, or cancelled now because it can never fit), so the next head is\n * judged at once. Without `full`, the memory reading is judged against the head's last recorded need first, and its\n * estimate (the sibling measurement, seconds of docker stats) is taken again only when that check lets it fit; `last`\n * is set to the head and the time of each estimate taken.\n */\nasync function judgeHead(\n deps: WatcherDeps,\n head: Lease,\n last: { id: string | null; at: number },\n full: boolean\n): Promise<'admitted' | 'waiting' | 'changed'> {\n const { store } = deps;\n // its checkout was removed (or is now only a path inside another one): it can never start, and it must not hold\n // every later lease behind it\n if (deps.gone?.(head)) {\n const c = await moveIf(store, head.id, 'pending', 'cancelled', {\n error: 'checkout gone',\n });\n if (c) deps.log(`cancel ${head.id}: checkout gone (${head.root})`);\n return 'changed';\n }\n // an exec whose requester is gone would be marked starting for nobody, and hold every later lease behind it\n if (head.kind === 'exec' && !pidAlive(head.requester_pid)) {\n const c = await moveIf(store, head.id, 'pending', 'cancelled', {\n error: 'requester gone',\n });\n if (c)\n deps.log(`cancel ${head.id}: requester gone (pid ${head.requester_pid})`);\n return 'changed';\n }\n let memory: HostMemory | null;\n let est: Awaited<ReturnType<WatcherDeps['estimate']>>;\n // the head as judged: its apps taken again before a full estimate of a start\n let cur = head;\n try {\n memory = await deps.memory();\n if (!full) {\n const cheap = admit({\n ahead: 0,\n memory,\n need_mib: head.need_mib,\n reserve_mib: head.reserve_mib,\n ramping_mib: rampingMib(store.list(), deps.now(), deps.settleMs(head)),\n });\n if (!cheap.ok && cheap.reason === 'memory') {\n if (head.waiting_for !== cheap.waiting_for)\n await noteWaiting(store, head, { waiting_for: cheap.waiting_for });\n return 'waiting';\n }\n }\n // The child runs `start <target> --lease <id>`, and startApps skips what is online when it looks: the budget is\n // taken over what is not running now (an app online at queue time may have stopped meanwhile), so the launched set\n // equals the budgeted one up to the window between this admission and the child's own look.\n if (head.kind === 'start') {\n const apps = await deps.targetApps(head);\n if (apps.join('\\0') !== head.apps.join('\\0')) cur = { ...head, apps };\n }\n est = await deps.estimate(cur);\n last.id = head.id;\n last.at = deps.now();\n } catch (e) {\n // its checkout cannot be read now: the reason shows in `leases`, the next tick tries again\n const why = `cannot estimate: ${describeError(e)}`;\n if (head.waiting_for !== why) {\n deps.log(`${head.id}: ${why}`);\n await noteWaiting(store, head, { waiting_for: why });\n }\n return 'waiting';\n }\n if (cur !== head) {\n // its apps and their sources under the lock, while it is still pending: a cancel that landed meanwhile wins\n const patched = await store\n .withLock(() =>\n store.patch(\n head.id,\n { apps: cur.apps, sources: est.sources },\n { expect: 'pending' }\n )\n )\n .catch((e: unknown) => {\n if (store.get(head.id)?.state === 'pending') throw e;\n return null;\n });\n if (!patched) return 'changed';\n deps.log(`${head.id}: apps now ${cur.apps.join(', ') || 'none'}`);\n cur = patched;\n }\n // a start admitted seconds ago is not in the reading yet, as the gate charges it\n const ramping_mib = rampingMib(store.list(), deps.now(), deps.settleMs(head));\n const d = admit({\n ahead: 0,\n memory,\n need_mib: est.need_mib,\n reserve_mib: est.reserve_mib,\n ramping_mib,\n });\n if (d.ok) {\n const admitted = await moveIf(store, head.id, 'pending', 'starting', {\n ...est,\n waiting_for: null,\n });\n if (!admitted) return 'changed';\n deps.log(\n `admit ${admitted.id} ${admitted.project} ${admitted.target} (${est.need_mib}M, free ${d.free_mib ?? '?'}M)`\n );\n if (admitted.kind === 'start') {\n try {\n await deps.runStart(admitted);\n } catch (e) {\n await moveIf(store, admitted.id, 'starting', 'failed', {\n error: describeError(e),\n child_pid: null,\n });\n }\n // a start that ended without its answer (the child threw before it, or was killed) is over\n await moveIf(store, admitted.id, 'starting', 'failed', {\n error: 'the start ended without an answer',\n child_pid: null,\n });\n }\n return 'admitted';\n }\n if (d.reason === 'never') {\n const c = await moveIf(store, head.id, 'pending', 'cancelled', {\n error: `never fits now: ${d.waiting_for}`,\n });\n if (c) deps.log(`cancel ${head.id}: ${d.waiting_for}`);\n return 'changed';\n }\n if (cur.waiting_for !== d.waiting_for || cur.need_mib !== est.need_mib)\n await noteWaiting(store, head, { ...est, waiting_for: d.waiting_for });\n return 'waiting';\n}\n\n/**\n * The last look before an idle exit, under the lock: false when something is pending or starting after all; else the\n * exit is noted in `<state>/watcher.json` (`exiting_at`), so a start that queues while this process is still on its way\n * out launches a fresh watcher instead of trusting this one.\n */\nasync function leaveIdle(deps: WatcherDeps): Promise<boolean> {\n const { store } = deps;\n return store.withLock(() => {\n if (\n store.list().some((l) => l.state === 'pending' || l.state === 'starting')\n )\n return false;\n const file = path.join(path.dirname(store.dir), WATCHER_NOTE);\n const tmp = `${file}.${process.pid}.tmp`;\n fs.writeFileSync(\n tmp,\n JSON.stringify({ exiting_at: new Date(deps.now()).toISOString() })\n );\n fs.renameSync(tmp, file);\n return true;\n });\n}\n\n/**\n * The watcher loop: on every tick (or wake) prune, reconcile running leases against what is online, then judge the\n * head of the FIFO: admit it (starting → the child runs the start → running / failed; an exec lease is only marked\n * starting, its owner runs it), then settle before the next head; or record why it waits. The running leases that\n * have not settled yet are charged on top of the memory reading, and a running lease whose starter still lives is not\n * reconciled. A head is estimated in full when it becomes the head, when the queue changed, when the memory reading\n * lets its last need fit, and at least every ESTIMATE_EVERY_MS; the ticks between read the memory alone. A lease\n * directory that cannot be read is logged once (a failing prune too) and the tick goes on as if nothing were queued,\n * never into an idle exit it cannot judge. Exits once nothing has been pending or starting for `idleExitMs` (leaving the exit note, see\n * leaveIdle); a starting lease that never recorded a child for `stuckMs` is failed, an exec lease whose requester\n * is gone is ended at once (cancelled at the head, failed while starting, freed while running), and one left starting\n * for EXEC_TURN_GRACE_MS is failed. A tick that throws is logged, not fatal.\n */\nexport async function watchLeases(\n deps: WatcherDeps,\n opts: {\n tickMs?: number;\n idleExitMs?: number;\n stuckMs?: number;\n signal?: AbortSignal;\n once?: boolean;\n } = {}\n): Promise<'idle' | 'aborted'> {\n const tickMs = opts.tickMs ?? 2000;\n const idleExitMs = opts.idleExitMs ?? 60_000;\n const stuckMs = opts.stuckMs ?? 10 * 60 * 1000;\n const { store } = deps;\n let idleSince = deps.now();\n let tick: AbortController | null = null;\n // what the queue looked like before the head was judged: only a change of it wakes the loop, so the watcher's own\n // patches (a waiting_for with live figures), the lock's files and the temp files never do; one made during the\n // judgement (a lease queued or cancelled while a long estimate ran) skips the sleep\n let asleepOn = '';\n // the head's last full estimate, and whether the queue changed since the last judgement: both call for a new one\n const last: { id: string | null; at: number } = { id: null, at: 0 };\n let woken = false;\n // a failure that repeats every tick is logged once, and again only once it changed or cleared\n const said = new Map<string, string>();\n const sayOnce = (key: string, line: string | null) => {\n if (line === null) said.delete(key);\n else if (said.get(key) !== line) {\n said.set(key, line);\n deps.log(line);\n }\n };\n // whether a read of the lease directory failed in this tick: nothing is known about the queue then\n let blind = false;\n const unreadable = (e: unknown) => {\n blind = true;\n sayOnce(\n 'read',\n `error: the lease directory cannot be read: ${describeError(e)}`\n );\n };\n const readable = <T>(read: () => T, fallback: T): T => {\n try {\n const v = read();\n sayOnce('read', null);\n return v;\n } catch (e) {\n unreadable(e);\n return fallback;\n }\n };\n const queueOf = () =>\n readable(\n () =>\n store\n .list()\n .map((l) => `${l.id}:${l.state}`)\n .join(','),\n asleepOn\n );\n const unwatch = deps.watch?.(() => {\n if (tick && queueOf() !== asleepOn) tick.abort();\n });\n try {\n for (;;) {\n if (opts.signal?.aborted) return 'aborted';\n blind = false;\n try {\n await store.withLock(() => store.prune());\n sayOnce('prune', null);\n } catch (e) {\n sayOnce('prune', `error: prune: ${describeError(e)}`);\n }\n try {\n await reconcile(deps, stuckMs);\n } catch (e) {\n unreadable(e); // its own list: each lease's errors are caught inside\n }\n asleepOn = queueOf();\n const starting = readable(\n () => store.list().some((l) => l.state === 'starting'),\n false\n );\n const head = readable(() => store.head(), null);\n const now = deps.now();\n if (!head && !starting && !blind) {\n if (now - idleSince >= idleExitMs) {\n if (await leaveIdle(deps)) return 'idle';\n // a start queued in the moment before the exit: it is taken first\n idleSince = now;\n continue;\n }\n } else idleSince = now;\n if (head && !starting) {\n const full =\n woken ||\n last.id !== head.id ||\n deps.now() - last.at >= ESTIMATE_EVERY_MS;\n woken = false;\n let r: 'admitted' | 'waiting' | 'changed' = 'waiting';\n try {\n r = await judgeHead(deps, head, last, full);\n } catch (e) {\n deps.log(`error: ${head.id}: ${describeError(e)}`);\n }\n if (r === 'admitted')\n await deps.sleep(deps.settleMs(head), opts.signal);\n if (r !== 'waiting') {\n if (opts.once) return 'idle';\n continue;\n }\n }\n if (opts.once) return 'idle';\n if (queueOf() !== asleepOn) {\n woken = true;\n continue;\n }\n tick = new AbortController();\n const onAbort = () => tick?.abort();\n opts.signal?.addEventListener('abort', onAbort, { once: true });\n await deps.sleep(tickMs, tick.signal);\n opts.signal?.removeEventListener('abort', onAbort);\n woken = tick.signal.aborted;\n tick = null;\n }\n } finally {\n unwatch?.();\n }\n}\n\n/**\n * The wake of the pm2-managed watcher: `fs.watch` on the lease directory. The lock's own files (`.lock`, its token\n * and stale files, `.seq`) are dot-names and never wake it.\n */\nexport function leaseDirWatch(dir: string): (cb: () => void) => () => void {\n return (cb) => {\n const w = fs.watch(dir, (_e, name) => {\n if (!name?.startsWith('.')) cb();\n });\n return () => w.close();\n };\n}\n\n/**\n * The apps a start of the lease's target launches on this machine now: the target's apps and their dependencies, in\n * dependency order and with the lease's host selection kept (as actOn picks them), that run on a local host and are\n * not running in `procs`. `m` is the checkout's full manifest.\n */\nexport function appsToLaunch(\n m: Manifest,\n l: Pick<Lease, 'target' | 'host'>,\n procs: Pm2Process[]\n): string[] {\n const fleet = new Fleet(m, l.host ?? undefined);\n return fleet\n .withDeps(fleet.select([l.target]))\n .filter((n) => pickHost(m, fleet.hostOf(n)).local)\n .filter((n) => {\n const p = findProcess(procs, m.project, n);\n return !(p && isRunning(p.status));\n });\n}\n\n/** The local host the watcher reads its memory on: a plain local shell in `cwd`, no ssh, no docker. */\nconst localHost = (cwd: string): Host => ({\n name: 'local',\n local: true,\n ssh_args: [],\n cwd,\n readonly: false,\n shell: parseShell(DEFAULT_SHELL),\n env: {},\n});\n\n/**\n * The real deps of the pm2-managed watcher: the state directory's store, the host's meminfo, each lease's checkout for\n * its estimate and pm2 state, the CLI entry for the child starts. An exec lease keeps the size its caller named, with\n * the reserve taken again from its manifest and the current reading (`memory`, as the deps hold it at the call).\n */\nexport function defaultWatcherDeps(dir: string, entry: string): WatcherDeps {\n const store = new LeaseStore(dir);\n const host = localHost(dir);\n const transport = createTransport(host);\n const ctxOf = async (l: Lease) => connect(prepare({ project: l.root }));\n const deps: WatcherDeps = {\n store,\n memory: () => readHostMemory(transport, host),\n estimate: async (l) => {\n // an exec has no apps to measure: what it needs is what its caller named, never a sum over `apps` (none)\n if (l.kind === 'exec') {\n let reserve: Resources['reserve'] | null = null;\n try {\n reserve = loadManifest(l.root).resources.reserve;\n } catch {\n // its checkout cannot be read: the reserve it was queued with\n }\n return {\n estimate_mib: l.estimate_mib,\n need_mib: l.need_mib,\n reserve_mib: reserve\n ? reserveMib(reserve, await deps.memory())\n : l.reserve_mib,\n sources: {},\n };\n }\n const m = loadManifest(l.root);\n const measured = await measureSiblings(m, {\n registry: registryOf(m, dir),\n list: (root) => listCheckout(root),\n });\n const apps = l.apps\n .filter((a) => Object.hasOwn(m.apps, a))\n .map((a) => m.apps[a]);\n const { estimate_mib, sources } = estimateApps(apps, measured);\n const memory = await readHostMemory(transport, host);\n return {\n estimate_mib,\n need_mib: needOf(estimate_mib, m.resources.margin),\n reserve_mib: reserveMib(m.resources.reserve, memory),\n sources,\n };\n },\n gone: (l) => !ownsManifest(l.root),\n runStart: async (l) => {\n // the checkout went away since the head was judged: nothing to start there (nor the project around it)\n if (!ownsManifest(l.root)) {\n await moveIf(store, l.id, 'starting', 'cancelled', {\n error: 'checkout gone',\n });\n return;\n }\n await new Promise<void>((resolve, reject) => {\n const child = spawn(\n process.execPath,\n [\n entry,\n '--project',\n l.root,\n // the caller's host selection: the replay acts on the hosts the queued start named\n ...(l.host ? ['--host', l.host] : []),\n 'start',\n l.target,\n ...(l.reload ? ['--reload'] : []),\n '--lease',\n l.id,\n ],\n { stdio: 'inherit', env: { ...process.env, MCPROC_STATE_DIR: dir } }\n );\n const pid = child.pid;\n const patched = pid\n ? store\n .withLock(() =>\n store.patch(l.id, { child_pid: pid }, { expect: 'starting' })\n )\n .then(\n () => undefined,\n () => {\n // the lease ended before its child was recorded (a stop cancelled it): the start must not go on\n if (store.get(l.id)?.state !== 'starting')\n child.kill('SIGTERM');\n }\n )\n : Promise.resolve();\n child.on('error', (e) => {\n void patched.then(() => reject(e));\n });\n child.on('exit', (code, signal) => {\n // a child that exited without its answer (it threw before it, or was killed) leaves the lease failed\n void patched\n .then(() =>\n moveIf(store, l.id, 'starting', 'failed', {\n error: `child exited ${code ?? signal}`,\n exit_code: code,\n child_pid: null,\n })\n )\n .then(() => resolve(), reject);\n });\n });\n },\n targetApps: async (l) => {\n const prep = prepare({ project: l.root });\n const ctx = await connect(prep);\n return appsToLaunch(prep.manifest, l, await ctx.pm2.jlist());\n },\n onlineApps: async (l) => {\n const ctx = await ctxOf(l);\n const procs = await ctx.pm2.jlist();\n return new Set(\n l.apps.filter((a) => {\n const p = findProcess(procs, ctx.manifest.project, a);\n return Boolean(p && isRunning(p.status));\n })\n );\n },\n settleMs: (l) => {\n try {\n return loadManifest(l.root).resources.settle * 1000;\n } catch {\n return SETTLE_DEFAULT_S * 1000;\n }\n },\n sleep: abortableSleep,\n now: () => Date.now(),\n log: (line) => console.log(`${new Date().toISOString()} ${line}`),\n };\n return deps;\n}\n","import path from 'node:path';\nimport { describeError, McprocError } from './errors.js';\nimport type { Dep, DepCondition, Manifest } from './manifest.js';\nimport {\n appCwd,\n buildEcosystem,\n ecosystemPath,\n generatedDir,\n} from './ecosystem.js';\nimport { findProcess, pm2Name, type Pm2Process } from './pm2.js';\nimport { rowsFor, snapshot, unreachableRow, type LsRow } from './list.js';\nimport { depFailure, waitDependency, type WaitResult } from './wait.js';\nimport type { Context } from './resolve.js';\nimport { shq } from '../transport/quote.js';\nimport { ensureOk } from '../transport/index.js';\n\nexport function resolveTargets(m: Manifest, target: string): string[] {\n if (target === 'all') return Object.keys(m.apps);\n if (Object.hasOwn(m.profiles, target)) return [...m.profiles[target]];\n if (Object.hasOwn(m.apps, target)) return [target];\n throw new McprocError(\n 'UNKNOWN_APP',\n `\"${target}\" is neither an app nor a profile in ${m.path}`,\n {\n hint: `Apps: ${Object.keys(m.apps).join(', ')}. Profiles: ${[...Object.keys(m.profiles), 'all'].join(', ')}.`,\n }\n );\n}\n\nexport function orderWithDeps(m: Manifest, names: string[]): string[] {\n const out: string[] = [];\n const seen = new Set<string>();\n const visit = (n: string) => {\n if (seen.has(n)) return;\n seen.add(n);\n for (const d of m.apps[n].depends_on) visit(d.app);\n out.push(n);\n };\n for (const n of names) visit(n);\n return out;\n}\n\n/**\n * Refuse before touching pm2 when one of the names already belongs to someone else: pm2 would restart that\n * process with this project's config instead of starting a new one. \"Someone else\" is another namespace, or the\n * same namespace running from another directory (a second checkout declaring the same `project`).\n */\nexport function assertNoCollision(\n ctx: Context,\n procs: Pm2Process[],\n names: string[]\n): void {\n for (const n of names) {\n const name = pm2Name(ctx.manifest.project, n);\n const expectedCwd = appCwd(ctx.host, ctx.manifest.apps[n]);\n const other = procs.find(\n (p) =>\n p.name === name &&\n (p.namespace !== ctx.manifest.project ||\n (p.cwd !== '' && path.posix.resolve(p.cwd) !== expectedCwd))\n );\n if (other && other.namespace !== ctx.manifest.project) {\n throw new McprocError(\n 'NAME_COLLISION',\n `pm2 process \"${name}\" on ${ctx.transport.describe()} belongs to namespace \"${other.namespace}\" (running from ${other.cwd || 'an unknown cwd'}), not to this project`,\n {\n hint: 'pm2 would restart that process with this config. Give this checkout a distinct `project:` in .mcproc/mcproc.yaml, or delete the other process if it is stale.',\n }\n );\n }\n if (other) {\n throw new McprocError(\n 'NAME_COLLISION',\n `\"${n}\" (pm2 process \"${name}\") on ${ctx.transport.describe()} is running from ${other.cwd}, not from ${expectedCwd}`,\n {\n hint: `pm2 keeps a process's cwd on restart. If the app moved in the manifest, run delete ${n} then start ${n}; if this is another checkout of the same project, give it its own \\`project:\\`.`,\n }\n );\n }\n }\n}\n\n/** A target string resolves within the context's host (an app, a profile or \"all\"); a list is taken as already resolved and ordered. */\nexport type Targets = string | string[];\nconst namesOf = (ctx: Context, t: Targets) =>\n typeof t === 'string' ? resolveTargets(ctx.manifest, t) : t;\n\nexport async function shipEcosystem(ctx: Context): Promise<string> {\n const eco = buildEcosystem(ctx.manifest, ctx.host);\n const file = ecosystemPath(ctx.host);\n const dir = generatedDir(ctx.host);\n const gi = path.posix.join(path.posix.dirname(dir), '.gitignore');\n const cmd = `mkdir -p ${shq(dir)} && { [ -e ${shq(gi)} ] || printf '*\\\\n' > ${shq(gi)}; } && cat > ${shq(file)}`;\n const res = ensureOk(\n await ctx.transport.exec(cmd, { stdin: JSON.stringify(eco, null, 2) }),\n ctx.host,\n 'write ecosystem'\n );\n if (res.code !== 0)\n throw new McprocError(\n 'TRANSPORT_FAILED',\n `Could not write ${file} on ${ctx.transport.describe()}: ${res.stderr.trim()}`\n );\n return file;\n}\n\n/** One wait made on behalf of an app before it started: how long, and how it ended. */\nexport interface WaitRecord {\n app: string;\n dep: string;\n condition: DepCondition;\n ms: number;\n ok: boolean;\n reason?: string;\n}\nexport interface StartOptions {\n reload?: boolean;\n /** waits for one dependency (default: on this context); actOn passes one that finds the dependency's host */\n waitDep?: (dep: Dep, forApp: string) => Promise<WaitResult>;\n /** the dependencies of an app to wait for; default the context's (host-scoped) manifest entry, the fleet passes the full manifest's */\n depsOf?: (app: string) => Dep[];\n /** every wait made, appended */\n waits?: WaitRecord[];\n /** apps that failed or were skipped so far (app -> why), shared across host runs by actOn */\n failed?: Map<string, string>;\n /** ends the default dependency wait as `aborted` (a client that cancelled the call); a waitDep of the caller's own is not given it */\n signal?: AbortSignal;\n}\n\n/**\n * Starts the apps in dependency order. Before launching an app it waits, in the order declared, for each of its\n * ready/completed dependencies; one that times out, fails or dies leaves the app (and everything that depends on\n * it) unstarted: its row is `skipped` with the reason, while unrelated apps still start.\n */\nexport async function startApps(\n ctx: Context,\n target: Targets,\n opts: StartOptions = {}\n): Promise<LsRow[]> {\n const names =\n typeof target === 'string'\n ? orderWithDeps(ctx.manifest, namesOf(ctx, target))\n : target;\n const waitDep =\n opts.waitDep ??\n ((d: Dep) => waitDependency(ctx, d, { signal: opts.signal }));\n const depsOf =\n opts.depsOf ?? ((n: string) => ctx.manifest.apps[n].depends_on);\n const failed = opts.failed ?? new Map<string, string>();\n const skipped = new Map<string, string>();\n /** an app that is not started, and the apps that need it must not be either */\n const skip = (n: string, why: string) => {\n skipped.set(n, why);\n failed.set(n, why);\n };\n /** One dependency wait, recorded. Why it is unmet, or undefined when met; a wait that throws (a host that cannot be reached, say) is an unmet one, not a crash of the whole start. */\n const unmetAfterWait = async (d: Dep, n: string) => {\n const t0 = Date.now();\n const record = (ok: boolean, reason?: string) =>\n opts.waits?.push({\n app: n,\n dep: d.app,\n condition: d.condition,\n ms: Date.now() - t0,\n ok,\n ...(reason ? { reason } : {}),\n });\n try {\n const r = await waitDep(d, n);\n record(r.ok, r.reason);\n return r.ok ? undefined : depFailure(d, r);\n } catch (e) {\n record(false, 'error');\n return `${d.app}: ${describeError(e)}`;\n }\n };\n const file = await shipEcosystem(ctx);\n const before = await ctx.pm2.jlist(); // pm2's own list: the URL checks of a full probe could time out the start before it began\n assertNoCollision(ctx, before, names);\n for (const n of names) {\n // running already: left alone, whatever happened to what it needs (it is neither waited for nor skipped)\n const p = findProcess(before, ctx.manifest.project, n);\n if (p && p.status === 'online' && !opts.reload) continue;\n // the caller cancelled: nothing more is launched, unrelated apps included\n if (opts.signal?.aborted) {\n skip(n, 'start cancelled');\n continue;\n }\n if (failed.has(n)) {\n // decided before this run (a dependency on another host failed, timed out or was not started)\n skip(n, failed.get(n)!);\n continue;\n }\n // a dependency that did not start (on this host or another): the dependent cannot either\n const blocked = depsOf(n).find((d) => failed.has(d.app));\n if (blocked) {\n skip(\n n,\n `skipped: ${blocked.app} was not started (${failed.get(blocked.app)})`\n );\n continue;\n }\n let unmet: string | undefined;\n for (const d of depsOf(n)) {\n if (d.condition === 'started') continue;\n unmet = await unmetAfterWait(d, n);\n if (unmet !== undefined) break;\n }\n if (unmet !== undefined) {\n skip(n, unmet);\n continue;\n }\n // the client may have gone while the dependency waits ran (a probe that found the condition met still answers ok)\n if (opts.signal?.aborted) {\n skip(n, 'start cancelled');\n continue;\n }\n await ctx.pm2.startOrRestart(file, pm2Name(ctx.manifest.project, n));\n }\n const live = names.filter((n) => !skipped.has(n));\n const rows = live.length\n ? rowsFor(ctx, await snapshot(ctx, { urls: live }), live)\n : [];\n const byApp = new Map(rows.map((r) => [r.app, r]));\n return names.map(\n (n) =>\n byApp.get(n) ??\n unreachableRow(\n ctx.manifest.apps[n],\n ctx.host.name,\n skipped.get(n)!,\n 'skipped'\n )\n );\n}\n\nexport async function restartApps(\n ctx: Context,\n target: Targets\n): Promise<LsRow[]> {\n const names = namesOf(ctx, target);\n const file = await shipEcosystem(ctx);\n assertNoCollision(ctx, await ctx.pm2.jlist(), names);\n for (const n of names)\n await ctx.pm2.startOrRestart(file, pm2Name(ctx.manifest.project, n));\n return rowsFor(ctx, await snapshot(ctx, { urls: names }), names);\n}\n\n/** Stop or delete acts from pm2's own list and answers without URL checks: no stalled URL can hold back taking an app down. */\nasync function forEachProcess(\n ctx: Context,\n target: Targets,\n act: (id: number, status: string) => Promise<unknown>\n): Promise<LsRow[]> {\n const names = namesOf(ctx, target);\n const procs = await ctx.pm2.jlist();\n for (const n of names) {\n const p = findProcess(procs, ctx.manifest.project, n);\n if (p) await act(p.pm_id, p.status);\n }\n return rowsFor(ctx, await snapshot(ctx, { urls: 'none' }), names);\n}\n\nexport function stopApps(ctx: Context, target: Targets): Promise<LsRow[]> {\n return forEachProcess(ctx, target, (id, status) =>\n status === 'stopped' ? Promise.resolve() : ctx.pm2.stop(id)\n );\n}\n\nexport function deleteApps(ctx: Context, target: Targets): Promise<LsRow[]> {\n return forEachProcess(ctx, target, (id) => ctx.pm2.delete(id));\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { McprocError } from './errors.js';\nimport { VERSION } from '../version.js';\nimport type { App, AppKind, Dep, Manifest } from './manifest.js';\nimport {\n findProcess,\n isRunning,\n parseJlist,\n pm2Name,\n runtimeDir,\n PM2_NOT_FOUND_HINT,\n type Pm2Process,\n} from './pm2.js';\nimport { treeMetrics, type TreeMetrics } from './metrics.js';\nimport type { HostMemory } from './memory.js';\nimport { hostStamp } from './logsince.js';\nimport {\n appPids,\n joinPorts,\n parseProbe,\n type AppPorts,\n type Listener,\n} from './ports.js';\nimport type { ProcStats, StatSample } from './stats.js';\nimport { buildEcosystem, type Pm2AppConfig } from './ecosystem.js';\nimport type { Context } from './resolve.js';\nimport type { ReloadCount } from './reloads.js';\nimport { settleUrls, type UrlApp, type UrlResult } from './urlcheck.js';\nimport { leasesCovering, type LeaseView } from './leases/view.js';\nimport { stateDir } from './state.js';\nimport { MARK, probeScript, probeTimeoutMs } from '../shell/snippets.js';\nimport { describeHost, ensureOk } from '../transport/index.js';\n\nexport interface LsRow {\n app: string;\n host: string;\n kind: AppKind;\n description: string;\n status: string;\n pm_id: number | null;\n pid: number | null;\n uptime_ms: number | null;\n /** when pm2 last started the process, as the host's local time with milliseconds (pm2's log stamp shape, YYYY-MM-DDTHH:mm:ss.SSS); null without a process, a start time or the host's zone */\n started: string | null;\n restarts: number;\n /** pm2's last recorded exit code for the process, any app; null when none is recorded (see statusWord) */\n exit_code: number | null;\n cpu: number | null;\n memory: number;\n /** the memory of the app's declared docker containers, inside memory */\n containers_memory: number;\n procs: number | null;\n runtime: string | null;\n pm2_cpu: number;\n pm2_memory: number;\n metrics_source: 'tree' | 'pm2-root';\n url: string | null;\n url_status: 'ok' | 'error' | 'down' | 'unchecked';\n url_code: number | null;\n /** where the url's answer came from: its host's probe, or this machine (url_check); null when unchecked */\n url_from: 'host' | 'here' | null;\n /** why the url is down, or why it was taken from this machine (\"on box: refused; here: refused\"); null otherwise */\n url_reason: string | null;\n ports: AppPorts;\n /**\n * only when asked (ls --reloads) and the app runs with reloads on and a known start: its in-process reloads since pm2\n * started it, the last one's stamp as its log wrote it, and partial when the logs read did not reach back to the start\n * (the count is then a lower bound)\n */\n reloads?: ReloadCount;\n /** the lease that covers an app that is not running yet: queued (its position) or starting */\n lease?: {\n id: string;\n state: 'pending' | 'starting';\n position: number;\n waiting_for: string | null;\n };\n /** set when the app's host could not be reached; status is then \"unreachable\" */\n error?: string;\n /** something the change did not finish beside the app itself, such as the leases a stop could not update */\n note?: string;\n}\n/** One look at a host for this project: pm2's processes, the ports, the metrics, the url checks, the memory and the leases. */\nexport interface Snapshot {\n procs: Pm2Process[];\n ports: Record<string, AppPorts>;\n listeners: Listener[];\n tree: Map<number, number>;\n stats: ProcStats;\n metrics: Record<string, TreeMetrics | null>;\n sampledAt: number;\n /** each asked app's url as decided (its host's answer, the check from here, url_check), by app name */\n urlChecks: Record<string, UrlResult>;\n /** the host's UTC offset ('+0200'); null when the probe could not read it */\n zone: string | null;\n /** the host's /proc/meminfo numbers; null where it has none */\n memory: HostMemory | null;\n /** this checkout's pending and starting leases on this machine (none on another host, or when not asked) */\n leases: LeaseView[];\n}\n/** `urls`: check every app's URL, none, or only those of the named apps (a mutation answers about what it touched). */\nexport interface SnapshotOptions {\n cpu?: 'inline' | 'none';\n /** 'none': the light probe (no /proc stat, RSS, args or docker); tree metrics stay null */\n metrics?: 'tree' | 'none';\n prev?: { sample: StatSample; at: number };\n urls?: 'check' | 'none' | string[];\n /** 'probe': ask docker for the declared containers' memory (about 2 s); default 'none', so a polling loop never pays it */\n containers?: 'probe' | 'none';\n /** 'read' (the default): read this checkout's leases from the state directory, on the local host only; 'none': skip it */\n leases?: 'read' | 'none';\n}\nexport interface HostInfo {\n name: string;\n transport: string;\n readonly: boolean;\n cwd: string;\n runtime: string;\n pm2: string | null;\n pm2_home:\n | string\n | null /** apps bound to this host (`host:` in the manifest) */;\n apps: string[];\n}\n\n/** An app's decided url check; undefined when its url was not asked for (own keys only: an app may be named constructor). */\nexport const urlCheckOf = (\n snap: Snapshot,\n app: string\n): UrlResult | undefined =>\n Object.hasOwn(snap.urlChecks, app) ? snap.urlChecks[app] : undefined;\n\n/** The row's url fields from the decided check; unchecked when the url was not asked for. */\nfunction urlFields(\n u: UrlResult | undefined\n): Pick<LsRow, 'url_status' | 'url_code' | 'url_from' | 'url_reason'> {\n return u\n ? {\n url_status: u.status,\n url_code: u.code,\n url_from: u.from,\n url_reason: u.reason,\n }\n : {\n url_status: 'unchecked',\n url_code: null,\n url_from: null,\n url_reason: null,\n };\n}\n\n/** Probes the context's host once (see SnapshotOptions for what it asks), and on this machine reads the checkout's leases. */\nexport async function snapshot(\n ctx: Context,\n opts: SnapshotOptions = {}\n): Promise<Snapshot> {\n const withMetrics = opts.metrics !== 'none';\n const cpuSample = (opts.cpu ?? 'inline') === 'inline' && withMetrics;\n const which = opts.urls ?? 'check';\n const asked: UrlApp[] =\n which === 'none'\n ? []\n : Object.values(ctx.manifest.apps).flatMap((a) =>\n a.url !== null && (which === 'check' || which.includes(a.name))\n ? [{ name: a.name, url: a.url, url_check: a.url_check }]\n : []\n );\n // the host requests each asked url once, except those checked only from here (url_check: here, on a host that is not this machine)\n const urls = [\n ...new Set(\n asked\n .filter((a) => ctx.host.local || a.url_check !== 'here')\n .map((a) => a.url)\n ),\n ];\n const containers =\n withMetrics && opts.containers === 'probe'\n ? [\n ...new Set(\n Object.values(ctx.manifest.apps).flatMap((a) => a.containers)\n ),\n ]\n : [];\n const res = ensureOk(\n await ctx.transport.exec(\n probeScript(ctx.pm2.bin, {\n cpuSample,\n urls,\n metrics: withMetrics,\n containers,\n }),\n {\n env: ctx.pm2.env(),\n // each url adds its bounded lookup and request: many on a host whose resolver drops packets outlast the default\n timeoutMs: probeTimeoutMs(urls.length),\n }\n ),\n ctx.host,\n 'probe'\n );\n const sampledAt = Date.now();\n if (!res.stdout.includes(MARK.JLIST)) {\n const tail = (res.stderr || res.stdout)\n .trim()\n .split('\\n')\n .slice(-5)\n .join('\\n');\n throw new McprocError(\n 'TRANSPORT_FAILED',\n `the shell on ${ctx.transport.describe()} did not run the probe (exit ${res.code}): ${tail}`,\n {\n hint: `Check hosts.${ctx.host.name}.shell (default /bin/bash -lc) exists on that host.`,\n }\n );\n }\n const data = parseProbe(res.stdout);\n if (data.jlistRc === 127)\n throw new McprocError(\n 'PM2_NOT_FOUND',\n `pm2 not found on ${ctx.transport.describe()}`,\n { hint: PM2_NOT_FOUND_HINT }\n );\n if (data.jlistRc !== 0)\n throw new McprocError(\n 'PM2_FAILED',\n `pm2 jlist exited ${data.jlistRc} on ${ctx.transport.describe()}`,\n { details: res.stderr.slice(-500) }\n );\n const procs = parseJlist(data.jlistRaw);\n const pids = appPids(\n ctx.manifest.apps,\n procs,\n data.tree,\n ctx.manifest.project\n );\n const metricOpts = opts.prev\n ? { prev: opts.prev.sample, intervalSec: (sampledAt - opts.prev.at) / 1000 }\n : {};\n const metrics: Record<string, TreeMetrics | null> = {};\n for (const [name, set] of pids)\n metrics[name] = treeMetrics(set, data.stats, data.listeners, metricOpts);\n for (const app of Object.values(ctx.manifest.apps)) {\n const m = metrics[app.name];\n if (!m || app.containers.length === 0) continue;\n const mib = app.containers.reduce(\n (sum, c) => sum + (data.containers.get(c) ?? 0),\n 0\n );\n const bytes = mib * 1024 * 1024;\n metrics[app.name] = {\n ...m,\n memory: m.memory + bytes,\n containers_memory: bytes,\n };\n }\n // the checks from here that url_check asks for, after the probe: a url the host answered costs nothing more\n const urlChecks = await settleUrls(\n asked,\n { host: ctx.host.name, local: ctx.host.local },\n data,\n ctx.hereCheck\n );\n return {\n procs,\n ports: joinPorts(ctx.manifest.apps, procs, data, ctx.manifest.project),\n listeners: data.listeners,\n tree: data.tree,\n stats: data.stats,\n metrics,\n sampledAt,\n urlChecks,\n zone: data.zone,\n memory: data.memory,\n leases:\n ctx.host.local && opts.leases !== 'none'\n ? leasesCovering(stateDir(), ctx.manifest)\n : [],\n };\n}\n\n/** Exit codes bash reports for SIGINT and SIGTERM: the process was stopped, it did not fail. */\nconst SIGNAL_EXITS = new Set([130, 143]);\n\n/**\n * The word a process is shown with: pm2's status, except that a one-shot app (autorestart off, every kind: task) that\n * exited reads done / failed (exit N) / stopped by its exit code — pm2 itself says only \"stopped\" and cannot tell a\n * manual stop from a natural exit. A manual stop reaches 130 / 143 through the trap the ecosystem puts in front of the\n * command of every autorestart-off app; null and those codes read as stopped.\n */\nexport function statusWord(p: Pm2Process | undefined, app: App): string {\n if (!p) return 'not-started';\n if (p.status !== 'stopped' || app.autorestart) return p.status;\n const c = p.exit_code;\n if (c === 0) return 'done';\n if (c === null || SIGNAL_EXITS.has(c)) return 'stopped';\n return `failed (exit ${c})`;\n}\n\n/** One row per named app, in that order: what pm2 and the probe show, or for an app not running that a lease covers, its place in the queue. */\nexport function rowsFor(\n ctx: Context,\n snap: Snapshot,\n names: string[]\n): LsRow[] {\n return names.map((name) => {\n const app = ctx.manifest.apps[name];\n const p = findProcess(snap.procs, ctx.manifest.project, name);\n // a lease speaks for an app whose process is not running (none yet, or stopped before a start that queued); a\n // running process is shown as it is\n const cover =\n p && isRunning(p.status)\n ? undefined\n : snap.leases.find((l) => l.apps.includes(name));\n if (cover) return queuedRow(app, ctx.host.name, cover, cover.position);\n const m = snap.metrics[name];\n return {\n app: name,\n host: ctx.host.name,\n kind: app.kind,\n description: app.description,\n status: statusWord(p, app),\n pm_id: p?.pm_id ?? null,\n pid: p && p.pid > 0 ? p.pid : null,\n uptime_ms: p?.uptime_ms ?? null,\n started:\n p?.started_at != null && snap.zone\n ? hostStamp(p.started_at, snap.zone)\n : null,\n restarts: p?.restarts ?? 0,\n exit_code: p?.exit_code ?? null,\n cpu: m ? m.cpu : (p?.cpu ?? 0),\n memory: m ? m.memory : (p?.memory ?? 0),\n containers_memory: m?.containers_memory ?? 0,\n procs: m ? m.procs : null,\n runtime: m ? m.runtime : null,\n pm2_cpu: p?.cpu ?? 0,\n pm2_memory: p?.memory ?? 0,\n metrics_source: m ? 'tree' : 'pm2-root',\n url: app.url,\n ...urlFields(urlCheckOf(snap, name)),\n ports: snap.ports[name],\n };\n });\n}\n\n/** The row of an app whose host did not answer (or whose change failed or was skipped): what the manifest declares, no runtime facts, and why. */\nexport function unreachableRow(\n app: App,\n host: string,\n error: string,\n status = 'unreachable'\n): LsRow {\n return {\n app: app.name,\n host,\n kind: app.kind,\n description: app.description,\n status,\n pm_id: null,\n pid: null,\n uptime_ms: null,\n started: null,\n restarts: 0,\n exit_code: null,\n cpu: null,\n memory: 0,\n containers_memory: 0,\n procs: null,\n runtime: null,\n pm2_cpu: 0,\n pm2_memory: 0,\n metrics_source: 'pm2-root',\n url: app.url,\n url_status: 'unchecked',\n url_code: null,\n url_from: null,\n url_reason: null,\n ports: { actual: [], declared: app.ports, checks: [], undeclared: [] },\n error,\n };\n}\n\n/** The row of an app whose start is queued: no runtime facts, the lease's position and reason instead. */\nexport function queuedRow(\n app: App,\n host: string,\n lease: {\n id: string;\n state: 'pending' | 'starting';\n waiting_for: string | null;\n },\n position: number\n): LsRow {\n const base = unreachableRow(\n app,\n host,\n '',\n lease.state === 'starting' ? 'starting' : `queued #${position}`\n );\n const { error: _dropped, ...row } = base;\n return {\n ...row,\n lease: {\n id: lease.id,\n state: lease.state,\n position,\n waiting_for: lease.waiting_for,\n },\n };\n}\n\nexport async function listApps(ctx: Context, app?: string): Promise<LsRow[]> {\n const names = app ? [app] : Object.keys(ctx.manifest.apps);\n // one app's read asks only its own url\n return rowsFor(\n ctx,\n await snapshot(ctx, {\n urls: app ? [app] : 'check',\n containers: 'probe',\n }),\n names\n );\n}\n\nexport async function portsReport(\n ctx: Context,\n port?: number\n): Promise<{\n port: number | null;\n listeners: Array<Listener & { app: string | null }>;\n}> {\n // no url is shown, so none is asked; the full probe stays for the docker-published ports\n const snap = await snapshot(ctx, { urls: 'none' });\n const pidToApp = new Map<number, string>();\n for (const [name, ap] of Object.entries(snap.ports))\n for (const l of ap.actual)\n for (const pid of l.pids) pidToApp.set(pid, name);\n const listeners = snap.listeners\n .filter((l) => port === undefined || l.port === port)\n .map((l) => ({\n ...l,\n app: l.pids.map((p) => pidToApp.get(p)).find(Boolean) ?? null,\n }))\n .sort((a, b) => a.port - b.port);\n return { port: port ?? null, listeners };\n}\n\nexport function hostsInfo(m: Manifest): HostInfo[] {\n const names = ['local', ...Object.keys(m.hosts).filter((n) => n !== 'local')];\n return names.map((n) => {\n const h = m.hosts[n];\n return {\n name: n,\n transport: describeHost(h),\n readonly: h.readonly,\n cwd: h.cwd,\n runtime: runtimeDir(h),\n pm2: h.pm2 ?? null,\n pm2_home: h.pm2_home ?? null,\n apps: Object.values(m.apps)\n .filter((a) => a.host === n)\n .map((a) => a.name),\n };\n });\n}\n\nexport async function describeApp(\n ctx: Context,\n name: string\n): Promise<{\n app: App;\n row: LsRow;\n logs: { out: string; err: string } | null;\n pm2: Pm2AppConfig;\n}> {\n const app = ctx.manifest.apps[name];\n const snap = await snapshot(ctx, { urls: [name], containers: 'probe' });\n const [row] = rowsFor(ctx, snap, [name]);\n const p = findProcess(snap.procs, ctx.manifest.project, name);\n const pm2 = buildEcosystem(ctx.manifest, ctx.host).apps.find(\n (a) => a.name === pm2Name(ctx.manifest.project, name)\n )!;\n return { app, row, logs: p ? { out: p.out_log, err: p.err_log } : null, pm2 };\n}\n\n/** A dependency as the describe answers show it (the manifest keeps the timeout in ms): one shape for the project and for one app. */\nexport const depView = (d: Dep) => ({\n app: d.app,\n condition: d.condition,\n timeout_s: d.timeoutMs / 1000,\n});\n\nexport function describeProject(m: Manifest) {\n const readmePath = path.join(m.root, '.mcproc', 'README.md');\n const readme = fs.existsSync(readmePath)\n ? fs.readFileSync(readmePath, 'utf8')\n : null;\n return {\n project: m.project,\n root: m.root,\n manifest_path: m.path,\n /** the mcproc that wrote the manifest (null when it names none) and the one answering */\n mcproc: { manifest: m.mcproc, running: VERSION },\n base_project: m.base_project,\n vars: m.vars,\n override: m.override,\n slot: m.slot,\n resources: m.resources,\n worktree: m.worktree,\n exec: m.exec,\n apps: Object.values(m.apps).map((a) => ({\n name: a.name,\n kind: a.kind,\n description: a.description,\n ports: a.ports,\n url: a.url,\n memory_mib: a.memory_mib,\n containers: a.containers,\n depends_on: a.depends_on.map(depView),\n host: a.host,\n })),\n profiles: { ...m.profiles, all: Object.keys(m.apps) },\n hosts: hostsInfo(m),\n readme,\n };\n}\n","import type { Listener } from './ports.js';\nimport type { ProcStats, StatSample } from './stats.js';\n\nexport interface TreeMetrics {\n memory: number;\n /** the share of memory that is the app's declared docker containers (bytes); 0 until the snapshot adds them */\n containers_memory: number;\n cpu: number | null;\n procs: number;\n runtime: string | null;\n metrics_source: 'tree' | 'pm2-root';\n}\n\n/** Percent of one core used by the tree between two samples; pids absent from either sample contribute nothing. */\nexport function cpuPercent(\n pids: Set<number>,\n before: StatSample,\n after: StatSample,\n clkTck: number,\n intervalSec: number\n): number {\n let delta = 0;\n for (const pid of pids) {\n const a = before.ticks.get(pid);\n const b = after.ticks.get(pid);\n if (a !== undefined && b !== undefined && b >= a) delta += b - a;\n }\n if (intervalSec <= 0 || clkTck <= 0) return 0;\n return (delta / clkTck / intervalSec) * 100;\n}\n\nexport function shortCommand(args: string): string {\n const [argv0, ...rest] = args.trim().split(/\\s+/);\n return [\n argv0.includes('/') ? argv0.slice(argv0.lastIndexOf('/') + 1) : argv0,\n ...rest,\n ].join(' ');\n}\n\nconst INLINE_INTERVAL_SEC = 0.5; // the `sleep 0.5` between the probe's two samples\n\nexport function treeMetrics(\n pids: Set<number>,\n stats: ProcStats,\n listeners: Listener[],\n opts: { prev?: StatSample; intervalSec?: number } = {}\n): TreeMetrics | null {\n if (stats.samples.length === 0) return null;\n let memory = 0;\n let biggest: { pid: number; kb: number } | null = null;\n for (const pid of pids) {\n const kb = stats.rssKb.get(pid) ?? 0;\n memory += kb * 1024;\n if (!biggest || kb > biggest.kb) biggest = { pid, kb };\n }\n let cpu: number | null = null;\n if (stats.samples.length >= 2)\n cpu = cpuPercent(\n pids,\n stats.samples[0],\n stats.samples[1],\n stats.clkTck,\n INLINE_INTERVAL_SEC\n );\n else if (opts.prev && opts.intervalSec)\n cpu = cpuPercent(\n pids,\n opts.prev,\n stats.samples[0],\n stats.clkTck,\n opts.intervalSec\n );\n if (pids.size === 0) cpu = 0;\n const holder = listeners\n .find((l) => l.pids.some((p) => pids.has(p)))\n ?.pids.find((p) => pids.has(p));\n const runtimePid = holder ?? biggest?.pid;\n const args =\n runtimePid !== undefined ? stats.args.get(runtimePid) : undefined;\n return {\n memory,\n containers_memory: 0,\n cpu,\n procs: pids.size,\n runtime: args ? shortCommand(args) : null,\n metrics_source: 'tree',\n };\n}\n","import { McprocError } from './errors.js';\nimport { findProcess, type Pm2Process } from './pm2.js';\nimport type { Context } from './resolve.js';\nimport { shq } from '../transport/quote.js';\nimport { ensureOk } from '../transport/index.js';\n\n// eslint-disable-next-line no-control-regex\nexport const ANSI_RE = /\\x1b\\[[0-9;?]*[ -/]*[@-~]/g;\n/** SGR sequences, the color and style codes an app writes (`ESC [ … m`, the colon form of true color included). */\n// eslint-disable-next-line no-control-regex\nexport const SGR_RE = /\\x1b\\[[0-9;:]*m/g;\n/** Every other escape: OSC up to BEL, ST or the line end (titles, links; one an app never terminated must not eat what follows), other CSI (cursor, erase), two-byte escapes (charsets, keypad), a stray ESC. */\n// eslint-disable-next-line no-control-regex\nconst NON_SGR_RE =\n /\\x1b\\][^\\x07\\x1b\\n]*(?:\\x07|\\x1b\\\\)?|\\x1b\\[[0-9;:?<=>]*[ -/]*[@-ln-~]|\\x1b(?!\\[[0-9;:]*m)[ -/]*[0-~]?/g;\n/** An app's colors stay, everything else a terminal would act on (cursor moves, titles) goes: what a log view can show. */\nexport function keepSgr(s: string): string {\n return s.replace(NON_SGR_RE, '');\n}\n/** Plain text: no escapes at all. */\nexport function stripAnsi(s: string): string {\n return keepSgr(s).replace(SGR_RE, '');\n}\n\nexport type LogStream = 'out' | 'err' | 'both';\nexport const MAX_LINES = 2000;\nexport interface LogsResult {\n app: string;\n lines: number;\n paths: { out: string; err: string };\n out?: string;\n err?: string;\n}\n\nconst OUT = '__MCPROC_OUT__';\nconst ERR = '__MCPROC_ERR__';\n\nfunction section(text: string, from: string, to?: string): string | undefined {\n const i = text.indexOf(from);\n if (i < 0) return undefined;\n const start = i + from.length + 1;\n const j = to ? text.indexOf(to, start) : -1;\n return text.slice(start, j >= 0 ? j : undefined).replace(/\\n$/, '');\n}\n\nexport async function readLogs(\n ctx: Context,\n app: string,\n opts: { lines?: number; stream?: LogStream } = {}\n): Promise<LogsResult> {\n const lines = Math.min(Math.max(Math.trunc(opts.lines ?? 100), 1), MAX_LINES);\n const stream = opts.stream ?? 'both';\n const p = findProcess(await ctx.pm2.jlist(), ctx.manifest.project, app);\n if (!p) {\n throw new McprocError(\n 'NOT_STARTED',\n `\"${app}\" has no pm2 process on ${ctx.transport.describe()} (never started, or deleted)`,\n { hint: `Run start ${app} first; ls shows the current state.` }\n );\n }\n const parts: string[] = [];\n if (stream !== 'err')\n parts.push(`echo ${OUT}; tail -n ${lines} ${shq(p.out_log)} 2>/dev/null`);\n if (stream !== 'out')\n parts.push(`echo ${ERR}; tail -n ${lines} ${shq(p.err_log)} 2>/dev/null`);\n const res = ensureOk(\n await ctx.transport.exec(parts.join('; ')),\n ctx.host,\n 'tail logs'\n );\n const text = stripAnsi(res.stdout);\n const result: LogsResult = {\n app,\n lines,\n paths: { out: p.out_log, err: p.err_log },\n };\n if (stream !== 'err') result.out = section(text, OUT, ERR) ?? '';\n if (stream !== 'out') result.err = section(text, ERR) ?? '';\n return result;\n}\n\n/**\n * Truncate the log files of one app, of the listed apps, or of every app of the context's host; each with its pm2 process\n * as it was and the files it could not truncate (a file is named there unless the host confirmed it is empty now).\n */\nexport async function flushLogs(\n ctx: Context,\n app?: string | string[]\n): Promise<\n {\n app: string;\n out_bytes: number;\n err_bytes: number;\n failed: string[];\n proc: Pm2Process;\n }[]\n> {\n const procs = await ctx.pm2.jlist();\n const names =\n app === undefined\n ? Object.keys(ctx.manifest.apps)\n : typeof app === 'string'\n ? [app]\n : app;\n const targets = names.flatMap((n) => {\n const p = findProcess(procs, ctx.manifest.project, n);\n return p ? [{ n, p }] : [];\n });\n if (targets.length === 0) return [];\n const cmd = targets\n .flatMap(({ p }) => [p.out_log, p.err_log])\n .map(\n (f) =>\n `{ wc -c < ${shq(f)} 2>/dev/null || echo 0; }; if : > ${shq(f)} 2>/dev/null; then echo ok; else echo fail; fi`\n )\n .join('; ');\n const res = ensureOk(await ctx.transport.exec(cmd), ctx.host, 'flush logs');\n const out = res.stdout\n .trim()\n .split('\\n')\n .map((s) => s.trim()); // per file: its size before, then ok or fail\n return targets.map(({ n, p }, i) => ({\n app: n,\n out_bytes: Number(out[i * 4]) || 0,\n err_bytes: Number(out[i * 4 + 2]) || 0,\n failed: [p.out_log, p.err_log].filter(\n (_, k) => out[i * 4 + k * 2 + 1] !== 'ok'\n ),\n proc: p,\n }));\n}\n","import { stripAnsi } from '../logs.js';\nimport { shq } from '../../transport/quote.js';\nimport { hex16 } from '../../shell/snippets.js';\nimport { stampOf } from './detect.js';\n\n/** At most this many new bytes are read per file per poll; when more is new, the most recent part is read. */\nexport const READ_CAP = 1048576;\n/** Bytes before the new part read as context, so an error at the start of the new part still gets lines before it. */\nexport const CONTEXT_BYTES = 4096;\n\n/** `at`/`anchor`: the hex of the 16 bytes before byte `at` when the mark was taken; if they changed, the file was replaced. */\nexport interface FileMark {\n path: string;\n offset: number;\n at?: number;\n anchor?: string;\n /** the latest pm2 stamp read in this file (ms), carried across clears: what is stamped at or before it was taken */\n stamp?: string;\n}\nexport interface Anchor {\n at: number;\n hex: string;\n}\nconst HEX = /^[0-9a-f]{0,64}$/;\n/** U+FFFD as UTF-8: what the decoding of the read's output put in place of bytes that were not valid UTF-8. */\nconst REPLACEMENT = Buffer.from('\\ufffd');\n\n/**\n * Written by a poll that looked for reloads, and carried over as they were by a clear of the logs (clearLogs), which\n * ends no run: `start`, the run it looked at (pm2's start in the host's wall time, pm2's stamp shape; null when the\n * host's zone or pm2's start was unknown), and `boot`, true while that run's first burst is still ahead of the point\n * (a `listening`-only first burst is the boot, not a reload).\n */\nexport interface AppMark {\n out?: FileMark;\n err?: FileMark;\n restarts: number;\n status: string;\n start?: string | null;\n boot?: boolean;\n}\n/** Where the previous poll stopped: per `host/app` the read offset of each log file, pm2's restart count and status. */\nexport interface CursorState {\n v: 1;\n apps: Record<string, AppMark>;\n}\n\nexport const markKey = (host: string, app: string): string => `${host}/${app}`;\n\n/** A poll covers some apps; the entries of the others stay as they were. */\nexport function mergeCursor(\n base: CursorState | undefined,\n next: CursorState\n): CursorState {\n return { v: 1, apps: { ...(base?.apps ?? {}), ...next.apps } };\n}\n\n/**\n * Shell for one file: its size, where the new part starts (the offset; 0 for a first call or a file that shrank; never\n * more than READ_CAP before the end), where the read starts (CONTEXT_BYTES earlier), then those bytes.\n */\nexport function readSnippet(\n id: number,\n file: string,\n offset: number | null,\n anchor: Anchor | null = null\n): string {\n const f = shq(file);\n const a =\n anchor &&\n HEX.test(anchor.hex) &&\n Number.isInteger(anchor.at) &&\n anchor.at >= 0\n ? anchor\n : null; // the store is a file a person can edit\n return [\n `echo __MCPROC_INC_${id}__`,\n `sz=$(wc -c < ${f} 2>/dev/null || echo 0); sz=$((sz+0)); off=${offset ?? -1}; at=${a ? a.at : -1}; ah='${a ? a.hex : ''}'`,\n `same=1; if [ \"$at\" -ge 0 ]; then if [ \"$sz\" -lt \"$at\" ] || [ \"${hex16(f, '$at')}\" != \"$ah\" ]; then same=0; fi; fi`,\n 'if [ \"$off\" -ge 0 ] && [ \"$sz\" -ge \"$off\" ] && [ \"$same\" = 1 ]; then st=$off; else st=0; fi',\n `if [ $((sz-st)) -gt ${READ_CAP} ]; then st=$((sz-${READ_CAP})); fi`,\n `cs=$((st-${CONTEXT_BYTES})); if [ \"$cs\" -lt 0 ]; then cs=0; fi`,\n `echo \"$sz $st $cs ${hex16(f, '$sz')}\"`,\n `if [ \"$sz\" -gt \"$cs\" ]; then tail -c +$((cs+1)) ${f} 2>/dev/null | head -c $((sz-cs)); fi`,\n ].join('; ');\n}\n\n/**\n * `short`: fewer bytes arrived than the read announced (the file changed between measuring and reading): do not analyse\n * or move on. `anchor` is taken at the measured size; `nextAnchor` at `nextOffset`, the end of the last complete line,\n * which is where a reader that goes on from this read starts.\n */\nexport interface FileRead {\n size: number;\n start: number;\n skipped: number;\n lines: string[];\n contextOnly: number;\n nextOffset: number;\n short: boolean;\n anchor: Anchor | null;\n nextAnchor: Anchor | null;\n}\n\n/**\n * One file's section of the read script's output: its lines, how many are context, where to go on. `clean` turns a raw\n * line into the text kept: by default every escape is removed (incidents match plain text); a terminal reader passes\n * keepSgr to keep the colors.\n */\nexport function parseRead(\n stdout: string,\n id: number,\n offset: number | null,\n opts: { clean?: (line: string) => string } = {}\n): FileRead | null {\n const clean = opts.clean ?? stripAnsi;\n const mark = `__MCPROC_INC_${id}__\\n`;\n const at = stdout.indexOf(mark);\n if (at < 0) return null;\n const next = stdout.indexOf(`__MCPROC_INC_${id + 1}__\\n`, at);\n let sec = stdout.slice(at + mark.length, next < 0 ? undefined : next);\n const nl = sec.indexOf('\\n');\n const head = sec.slice(0, nl).trim().split(/\\s+/);\n const [size, start, ctxStart] = head.slice(0, 3).map((n) => Number(n) || 0);\n const hex = head[3] ?? '';\n sec = nl < 0 ? '' : sec.slice(nl + 1);\n const buf = Buffer.from(sec, 'utf8');\n const ctxBytes = Math.max(0, start - ctxStart);\n const complete = buf.lastIndexOf(0x0a) + 1; // bytes up to and including the last newline\n const partial = buf.length - complete;\n let pos = 0;\n const lines: string[] = [];\n let contextOnly = 0;\n for (const raw of buf\n .subarray(0, complete)\n .toString('utf8')\n .split('\\n')\n .slice(0, -1)) {\n const lineStart = pos;\n pos += Buffer.byteLength(raw, 'utf8') + 1;\n if (lineStart === 0 && ctxStart > 0) continue; // the read began mid-line: that head is only a fragment\n if (lineStart < ctxBytes) contextOnly++;\n lines.push(clean(raw));\n }\n const skipped =\n offset !== null && offset >= 0 && size >= offset\n ? Math.max(0, start - offset)\n : 0;\n const nextOffset = Math.max(start, size - partial);\n const short = buf.length < size - ctxStart;\n const anchor = hex && HEX.test(hex) ? { at: size, hex } : null;\n return {\n size,\n start,\n skipped,\n lines,\n contextOnly,\n nextOffset,\n short,\n anchor,\n nextAnchor: anchorAt(buf, nextOffset, { size, ctxStart, short, anchor }),\n };\n}\n\n/**\n * The anchor at `at` (the end of the last complete line, at or before the size) from the bytes a read holds: the hex of\n * the up to 16 bytes before it, as hex16 gives it. Positions are counted back from the end of the read, which is the\n * measured size; null unless every byte from there to the end is in the read and came through the UTF-8 decoding of\n * the output unchanged (a replaced byte changes the length, so its position is no longer known), and the read's last\n * bytes are the ones the anchor at the size was taken from.\n */\nfunction anchorAt(\n buf: Buffer,\n at: number,\n read: {\n size: number;\n ctxStart: number;\n short: boolean;\n anchor: Anchor | null;\n }\n): Anchor | null {\n const { size, ctxStart, short, anchor } = read;\n if (at === size) return anchor;\n const n = Math.min(16, at);\n const end = buf.length - (size - at);\n if (!anchor || short || n <= 0 || at - n < ctxStart || end - n < 0)\n return null;\n const tail = buf.subarray(end - n);\n if (tail.includes(REPLACEMENT)) return null;\n if (buf.subarray(-Math.min(16, size)).toString('hex') !== anchor.hex)\n return null;\n return { at, hex: buf.subarray(end - n, end).toString('hex') };\n}\n\n/**\n * For a first call: the stamp `sinceMin` minutes before `now`, the host's current time in pm2's stamp shape (that host's\n * own clock and zone, never the agent's). Without it (a host whose `date` printed nothing), before the newest stamp here.\n * Lines without any stamp (an app with pm2's `time: false`) cannot be placed in time: no window, every line counts.\n */\nexport function windowStart(\n lines: string[],\n sinceMin: number,\n now: string | null = null\n): string | null {\n if (!lines.some((l) => stampOf(l) !== null)) return null;\n let ref = now;\n for (let i = lines.length - 1; i >= 0 && !ref; i--) ref = stampOf(lines[i]);\n return ref\n ? new Date(Date.parse(`${ref}Z`) - sinceMin * 60_000)\n .toISOString()\n .slice(0, 19)\n : null;\n}\n\n/** Asks the host for its current time in pm2's stamp shape; `hostNow` reads it back from the script's output. */\nexport const NOW_SNIPPET = `echo \"__MCPROC_NOW__ $(date '+%Y-%m-%dT%H:%M:%S' 2>/dev/null)\"`;\nexport const hostNow = (stdout: string): string | null =>\n /__MCPROC_NOW__ (\\d{4}-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d)/.exec(stdout)?.[1] ?? null;\n","import { McprocError, describeError } from './errors.js';\nimport { stampOf } from './incidents/detect.js';\nimport {\n readSnippet,\n parseRead,\n type FileMark,\n type Anchor,\n type FileRead,\n} from './incidents/cursor.js';\nimport { findProcess } from './pm2.js';\nimport type { Fleet, HostError } from './fleet.js';\nimport { keepSgr, stripAnsi } from './logs.js';\nimport { ensureOk } from '../transport/index.js';\n\nexport type SinceSpec =\n | { kind: 'relative'; ms: number }\n | { kind: 'local'; stamp: string }\n | { kind: 'instant'; epochMs: number }\n | { kind: 'last' }\n | { kind: 'tail'; n: number };\nexport const MAX_RELATIVE_MS = 24 * 3600_000;\n/** `since: last` with no mark yet reads this many last lines of each file: a plain recent tail, not a guessed window. */\nexport const FIRST_LAST_LINES = 100;\n\nconst RELATIVE = /^(\\d+(?:\\.\\d+)?)(ms|s|m|h)$/;\nconst ABSOLUTE =\n /^(\\d{4}-\\d{2}-\\d{2})T(\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.(\\d{1,3}))?)?(Z|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)?$/;\nconst UNIT: Record<string, number> = {\n ms: 1,\n s: 1000,\n m: 60_000,\n h: 3_600_000,\n};\nconst HINT =\n \"since is a span like 90s, 5m or 2h (at most 24h), a time like 2026-10-14T07:30[:00[.000]] in the host's local time (add Z or +02:00 for an absolute instant), or last (MCP only: since your previous logs call).\";\nconst bad = (s: string) =>\n new McprocError('BAD_ARGUMENT', `unknown since \"${s}\"`, { hint: HINT });\n\nexport function parseSince(s: string): SinceSpec {\n if (s === 'last') return { kind: 'last' };\n const rel = RELATIVE.exec(s);\n if (rel) {\n const ms = Math.round(Number(rel[1]) * UNIT[rel[2]]);\n if (!(ms > 0) || ms > MAX_RELATIVE_MS) throw bad(s);\n return { kind: 'relative', ms };\n }\n const abs = ABSOLUTE.exec(s);\n if (!abs) throw bad(s);\n const [, date, hh, mm, ss = '00', frac = '0', zone] = abs;\n const stamp = `${date}T${hh}:${mm}:${ss}.${frac.padEnd(3, '0')}`;\n const wall = wallMs(stamp);\n if (Number.isNaN(wall)) throw bad(s);\n if (!zone) return { kind: 'local', stamp };\n const offsetMin =\n zone === 'Z'\n ? 0\n : (zone[0] === '-' ? -1 : 1) *\n (Number(zone.slice(1, 3)) * 60 + Number(zone.slice(4, 6)));\n return { kind: 'instant', epochMs: wall - offsetMin * 60_000 };\n}\n\n/** A host's wall clock as its `date` prints it: `now` in pm2's stamp shape (seconds), `zone` as `+hhmm`. */\nexport interface HostClock {\n now: string;\n zone: string;\n}\n\n/** Asks the host for its wall clock and UTC offset in one line; `hostClock` reads it back from the script's output. */\nexport const CLOCK_SNIPPET = `echo \"__MCPROC_LS_CLOCK__ $(date '+%Y-%m-%dT%H:%M:%S %z' 2>/dev/null)\"`;\n/** null when the marker is missing or garbled (a host whose `date` printed nothing or another shape). */\nexport const hostClock = (stdout: string): HostClock | null => {\n const m =\n /__MCPROC_LS_CLOCK__ (\\d{4}-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d) ([+-]\\d{4})/.exec(\n stdout\n );\n return m ? { now: m[1], zone: m[2] } : null;\n};\n\n/** A wall-clock instant held as if it were UTC, in pm2's millisecond stamp shape. */\nconst wallStamp = (ms: number): string =>\n new Date(ms).toISOString().slice(0, 23);\n/**\n * A wall-clock stamp read as if it were UTC; NaN when it names no real time. Date.parse rolls `02-30` or `24:00`\n * over to the next day, so the stamp must come back unchanged.\n */\nfunction wallMs(stamp: string): number {\n const ms = Date.parse(`${stamp}Z`);\n return !Number.isNaN(ms) && new Date(ms).toISOString().startsWith(stamp)\n ? ms\n : Number.NaN;\n}\nconst HOST_NOW = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}$/;\n/** A UTC offset as `date +%z` prints it: sign, hours 00..23, minutes 00..59. */\nconst ZONE = /^([+-])([01]\\d|2[0-3])([0-5]\\d)$/;\n/** Whether a host's `date +%z` output is a real offset (`+0200`), not just its shape (`+9900`). */\nexport const isZone = (zone: string): boolean => ZONE.test(zone);\n/** The host's `date +%z` (`+0200`) as milliseconds east of UTC; null when it is not one. */\nconst zoneMs = (zone: string): number | null => {\n const m = ZONE.exec(zone);\n if (!m) return null;\n return (m[1] === '-' ? -1 : 1) * (Number(m[2]) * 60 + Number(m[3])) * 60_000;\n};\n/** An instant (epoch ms) as the host's wall time in pm2's millisecond stamp shape; null for a zone that does not parse. */\nexport function hostStamp(epochMs: number, zone: string): string | null {\n const z = zoneMs(zone);\n return z === null ? null : wallStamp(epochMs + z);\n}\nconst noClock = () =>\n new McprocError(\n 'TRANSPORT_FAILED',\n 'the host did not report a readable clock and zone, so a relative time or a time with a zone cannot be placed there',\n {\n hint: \"Pass a time without a zone (2026-10-14T07:30), read as the host's local time, or check that `date` works on that host.\",\n }\n );\n\n/** The pm2 stamp (host-local, with milliseconds) a line must reach; null when the spec selects by position, not time. */\nexport function cutoffFor(\n spec: SinceSpec,\n clock: HostClock | null\n): string | null {\n switch (spec.kind) {\n case 'last':\n case 'tail':\n return null;\n case 'local':\n return spec.stamp;\n case 'relative': {\n // the host's wall time read as if UTC: pure arithmetic on wall clocks, so only the clock is needed\n const now =\n clock && HOST_NOW.test(clock.now) ? wallMs(clock.now) : Number.NaN;\n if (Number.isNaN(now)) throw noClock();\n return wallStamp(now - spec.ms);\n }\n case 'instant': {\n // an instant becomes the host's wall time through its zone alone\n const zone = clock ? zoneMs(clock.zone) : null;\n if (zone === null) throw noClock();\n return wallStamp(spec.epochMs + zone);\n }\n }\n}\n\n/** A pm2 stamp normalised to milliseconds: `…:ss` reads as `…:ss.000`. */\nexport const msStamp = (t: string): string => (t.length > 19 ? t : `${t}.000`);\n/** pm2's stamp of a line, normalised to milliseconds (`…:ss` reads as `…:ss.000`); null for an unstamped line. */\nexport function stampMs(line: string): string | null {\n const t = stampOf(line);\n return t === null ? null : msStamp(t);\n}\n\nexport interface Stamped {\n time: string | null;\n text: string;\n}\n/**\n * The lines at or after the cutoff. An unstamped line (a stack frame, a continuation) belongs to the stamped line\n * before it and inherits its time; lines before the first stamp cannot be placed and are dropped (kept with a null\n * cutoff). `beforeCutoff` counts stamped lines older than the cutoff: 0 means the window may have been cut short.\n */\nexport function selectSince(\n lines: string[],\n cutoff: string | null\n): { kept: Stamped[]; beforeCutoff: number } {\n const kept: Stamped[] = [];\n let current: string | null = null;\n let beforeCutoff = 0;\n for (const text of lines) {\n const t = stampMs(text);\n if (t !== null) current = t;\n if (cutoff !== null) {\n if (current === null) continue;\n if (current < cutoff) {\n if (t !== null) beforeCutoff++;\n continue;\n }\n }\n kept.push({ time: current, text });\n }\n return { kept, beforeCutoff };\n}\n\nexport interface SinceLine {\n app: string;\n host: string;\n stream: 'out' | 'err';\n time: string | null;\n text: string;\n}\n/**\n * Stable order by the moment each line was written (an unstamped line already carries its inherited time), then the\n * LAST `cap` lines are kept. pm2 stamps in its host's local time, so a stamp read as UTC minus its host's offset\n * (`offsets`, ms east of UTC; a host without one counts as UTC) places hosts in different zones on one timeline. A\n * line without a time sorts as the oldest.\n */\nexport function mergeLines(\n lines: SinceLine[],\n cap: number,\n offsets: Record<string, number> = {}\n): { lines: SinceLine[]; truncated: number } {\n const moment = (l: SinceLine): number => {\n const ms = l.time === null ? Number.NaN : Date.parse(`${l.time}Z`);\n return Number.isNaN(ms)\n ? Number.NEGATIVE_INFINITY\n : ms - (offsets[l.host] ?? 0);\n };\n const sorted = lines\n .map((l, i) => ({ l, i, k: moment(l) }))\n .sort((a, b) => (a.k < b.k ? -1 : a.k > b.k ? 1 : a.i - b.i))\n .map((x) => x.l);\n const truncated = Math.max(0, sorted.length - cap);\n return { lines: sorted.slice(truncated), truncated };\n}\n\n/** Where the merged reads of one MCP session stopped, per file; never shared with other sessions or callers. */\nexport class LogMarks {\n private readonly m = new Map<string, { out?: FileMark; err?: FileMark }>();\n static key(manifestPath: string, host: string, app: string): string {\n return `${manifestPath}|${host}/${app}`;\n }\n get(key: string): { out?: FileMark; err?: FileMark } | undefined {\n return this.m.get(key);\n }\n set(key: string, stream: 'out' | 'err', mark: FileMark): void {\n const e = this.m.get(key) ?? {};\n e[stream] = mark;\n this.m.set(key, e);\n }\n}\n/**\n * Where the next read of a file goes on after this one: the end of its last complete line, with the anchor of the\n * bytes before it (taken at that offset, so a follower that continues there can tell a replaced file from a grown one).\n */\nexport const sinceMark = (path: string, r: FileRead): FileMark => ({\n path,\n offset: r.nextOffset,\n ...(r.nextAnchor ? { at: r.nextAnchor.at, anchor: r.nextAnchor.hex } : {}),\n});\nexport const MAX_MERGED_LINES = 2000;\nexport interface SinceOptions {\n since: SinceSpec;\n lines?: number;\n stream?: 'out' | 'err' | 'both';\n marks?: LogMarks;\n keepColors?: boolean;\n}\nexport interface SinceAnswer {\n mode: SinceSpec['kind'];\n since: Record<string, string | null>;\n lines: SinceLine[];\n truncated: number;\n skipped: {\n app: string;\n host: string;\n stream: 'out' | 'err';\n bytes: number;\n }[];\n not_started: string[];\n /** hosts whose UTC offset could not be read: their lines are placed by their raw stamps among the other hosts' */\n unzoned: string[];\n errors: HostError[];\n apps: number;\n hosts: number;\n}\nconst STREAMS = ['out', 'err'] as const;\n\ninterface HostRead {\n host: string;\n cutoff: string | null;\n /** the host's UTC offset in ms; null when its clock line or zone could not be read */\n offset: number | null;\n lines: SinceLine[];\n skipped: SinceAnswer['skipped'];\n notStarted: string[];\n}\ninterface HostFailure {\n host: string;\n error: HostError;\n cause: unknown;\n}\n\n/**\n * The lines of the named apps since the cutoff (or since the session's marks, or the last n per file), each app read\n * on its own host, hosts in parallel: one jlist and one read script per host, the host's clock in the same script.\n * A host that fails is a note for its apps unless none answers.\n */\nexport async function readSince(\n fleet: Fleet,\n names: string[],\n opts: SinceOptions\n): Promise<SinceAnswer> {\n const spec = opts.since;\n const clampLines = (n: number) =>\n Math.min(Math.max(1, Math.trunc(n)), MAX_MERGED_LINES);\n const tailN = spec.kind === 'tail' ? clampLines(spec.n) : 0;\n const cap = clampLines(\n opts.lines ?? (spec.kind === 'tail' ? tailN : MAX_MERGED_LINES)\n );\n const stream = opts.stream ?? 'both';\n // only the requested streams are read, so the other stream's mark stays where its last read left it\n const streams = STREAMS.filter((s) => stream === 'both' || s === stream);\n const clean = opts.keepColors ? keepSgr : stripAnsi;\n const groups = fleet.groups(names);\n const perHost = await Promise.all(\n groups.map(async (g): Promise<HostRead | HostFailure> => {\n try {\n const ctx = await fleet.ctx(g.host);\n const procs = await ctx.pm2.jlist();\n const targets = g.apps.flatMap((app) => {\n const p = findProcess(procs, fleet.manifest.project, app);\n return p ? [{ app, p }] : [];\n });\n const notStarted = g.apps.filter(\n (a) => !targets.some((t) => t.app === a)\n );\n const files = targets.flatMap((t) =>\n streams.map((stream) => {\n const path = stream === 'out' ? t.p.out_log : t.p.err_log;\n const key = LogMarks.key(fleet.manifest.path, g.host, t.app);\n const mark =\n spec.kind === 'last' ? opts.marks?.get(key)?.[stream] : undefined;\n const same = mark !== undefined && mark.path === path;\n const anchor: Anchor | null =\n same && mark.at !== undefined && mark.anchor !== undefined\n ? { at: mark.at, hex: mark.anchor }\n : null;\n return {\n app: t.app,\n stream,\n path,\n key,\n offset: same ? mark.offset : null,\n anchor,\n hadMark: same,\n };\n })\n );\n // the clock always, so the header can say the cutoff even when nothing runs here\n const script = [\n CLOCK_SNIPPET,\n ...files.map((f, i) => readSnippet(i, f.path, f.offset, f.anchor)),\n ].join('; ');\n const res = ensureOk(\n await ctx.transport.exec(script),\n ctx.host,\n 'read logs since'\n );\n const clock = hostClock(res.stdout);\n const cutoff = cutoffFor(spec, clock);\n const offset = clock ? zoneMs(clock.zone) : null;\n const lines: SinceLine[] = [];\n const skipped: SinceAnswer['skipped'] = [];\n files.forEach((f, i) => {\n const r = parseRead(res.stdout, i, f.offset, { clean });\n // a read cut short (the file changed meanwhile) is not used: no lines, the old mark kept, read again next time\n if (!r || r.short) return;\n // stamps are taken over every line read, so a slice that begins on a continuation line still knows its time\n const sel = selectSince(r.lines, cutoff);\n // a cutoff selects by time; without one (last, tail) every line is kept, in step with r.lines, and position\n // selects: past a mark only the part after it, else the last n of the file\n let kept = sel.kept;\n if (f.hadMark) kept = kept.slice(r.contextOnly);\n else if (spec.kind === 'tail') kept = kept.slice(-tailN);\n else if (spec.kind === 'last') kept = kept.slice(-FIRST_LAST_LINES);\n // the 1 MB cap bit (the read began past byte 0) and nothing older than the cutoff was seen: lines between\n // the cutoff and the window start may be missing\n if (\n cutoff !== null &&\n r.start > 0 &&\n sel.beforeCutoff === 0 &&\n sel.kept.length > 0\n )\n skipped.push({\n app: f.app,\n host: g.host,\n stream: f.stream,\n bytes: r.start,\n });\n if (spec.kind === 'last' && r.skipped > 0)\n skipped.push({\n app: f.app,\n host: g.host,\n stream: f.stream,\n bytes: r.skipped,\n });\n for (const k of kept)\n lines.push({\n app: f.app,\n host: g.host,\n stream: f.stream,\n time: k.time,\n text: k.text,\n });\n if (opts.marks) opts.marks.set(f.key, f.stream, sinceMark(f.path, r));\n });\n return { host: g.host, cutoff, offset, lines, skipped, notStarted };\n } catch (e) {\n return {\n host: g.host,\n error: { host: g.host, apps: g.apps, message: describeError(e) },\n cause: e,\n };\n }\n })\n );\n const failed = perHost.filter((h): h is HostFailure => 'error' in h);\n if (failed.length === perHost.length && failed.length > 0)\n throw failed[0].cause;\n const ok = perHost.filter((h): h is HostRead => !('error' in h));\n // the reads come back grouped by host: equal moments follow the order of the names, then out before err, then file order\n const rank = new Map(names.map((n, i) => [n, i]));\n const byName = (a: string, b: string) =>\n (rank.get(a) ?? 0) - (rank.get(b) ?? 0);\n // each host's stamps are its local time: its offset puts them on one timeline (a host without a zone stays as stamped)\n const merged = mergeLines(\n ok.flatMap((h) => h.lines).sort((a, b) => byName(a.app, b.app)),\n cap,\n Object.fromEntries(ok.map((h) => [h.host, h.offset ?? 0]))\n );\n // a host without a zone can only be misplaced against another host's lines\n const withLines = ok.filter((h) => h.lines.length > 0);\n const unzoned =\n withLines.length > 1\n ? withLines.filter((h) => h.offset === null).map((h) => h.host)\n : [];\n return {\n mode: spec.kind,\n since: Object.fromEntries(ok.map((h) => [h.host, h.cutoff])),\n lines: merged.lines,\n truncated: merged.truncated,\n skipped: ok.flatMap((h) => h.skipped),\n not_started: ok.flatMap((h) => h.notStarted).sort(byName),\n unzoned,\n errors: failed.map((f) => f.error),\n apps: names.length,\n hosts: groups.length,\n };\n}\n","export interface StatSample {\n ticks: Map<number, number>;\n ppid: Map<number, number>;\n}\nexport interface ProcStats {\n clkTck: number;\n samples: StatSample[];\n rssKb: Map<number, number>;\n args: Map<number, string>;\n dockerPorts: Map<number, string>;\n}\n\nexport const EMPTY_STATS: ProcStats = {\n clkTck: 100,\n samples: [],\n rssKb: new Map(),\n args: new Map(),\n dockerPorts: new Map(),\n};\n\n/** \"CLK <n>\" then \"pid ppid ticks\" lines (awk over /proc/[0-9]*\\/stat); anything else is ignored. */\nexport function parseStat(text: string): {\n clkTck: number;\n sample: StatSample;\n} {\n let clkTck = 100;\n const ticks = new Map<number, number>();\n const ppid = new Map<number, number>();\n for (const raw of text.split('\\n')) {\n const t = raw.trim().split(/\\s+/);\n if (t[0] === 'CLK' && /^\\d+$/.test(t[1] ?? '')) {\n clkTck = Number(t[1]);\n continue;\n }\n if (t.length === 3 && t.every((x) => /^\\d+$/.test(x))) {\n ticks.set(Number(t[0]), Number(t[2]));\n ppid.set(Number(t[0]), Number(t[1]));\n }\n }\n return { clkTck, sample: { ticks, ppid } };\n}\n\nexport function parseRss(text: string): Map<number, number> {\n const m = new Map<number, number>();\n for (const raw of text.split('\\n')) {\n const [pid, kb] = raw.trim().split(/\\s+/);\n if (/^\\d+$/.test(pid ?? '') && /^\\d+$/.test(kb ?? ''))\n m.set(Number(pid), Number(kb));\n }\n return m;\n}\n\n/** `ps -eo pid=,args=` (GNU, no header) or busybox `ps -o pid,args` (with a header line). */\nexport function parseArgs(text: string): Map<number, string> {\n const m = new Map<number, string>();\n for (const raw of text.split('\\n')) {\n const r = /^\\s*(\\d+)\\s+(.*)$/.exec(raw);\n if (r) m.set(Number(r[1]), r[2].trim());\n }\n return m;\n}\n\n/** `docker ps --format '{{.Names}}\\t{{.Ports}}'`: every \"host:port->\" pair maps the host port to the container. */\nexport function parseDockerPorts(text: string): Map<number, string> {\n const m = new Map<number, string>();\n for (const raw of text.split('\\n')) {\n const [name, ports] = raw.split('\\t');\n if (!name || !ports) continue;\n for (const hit of ports.matchAll(/:(\\d+)->/g))\n m.set(Number(hit[1]), name.trim());\n }\n return m;\n}\n","import type { App } from './manifest.js';\nimport { findProcess, type Pm2Process } from './pm2.js';\nimport { MARK } from '../shell/snippets.js';\nimport { isZone } from './logsince.js';\nimport { parseMeminfo, parseDockerStats, type HostMemory } from './memory.js';\nimport type { HostEnv, HostUrl } from './urlcheck.js';\nimport {\n EMPTY_STATS,\n parseArgs,\n parseDockerPorts,\n parseRss,\n parseStat,\n type ProcStats,\n} from './stats.js';\n\nexport interface Listener {\n proto: 'tcp' | 'udp';\n addr: string;\n port: number;\n pid: number | null;\n pids: number[];\n command: string | null;\n container: string | null;\n}\nexport interface ProbeData {\n jlistRaw: string;\n jlistRc: number;\n tree: Map<number, number>;\n listeners: Listener[];\n stats: ProcStats;\n urls: Map<string, HostUrl>;\n /** the host's environment section; null when the probe checked no url (or the section is missing) */\n env: HostEnv | null;\n /** the host's UTC offset as `date +%z` prints it ('+0200', '-0330'); null when the section is absent or garbled */\n zone: string | null;\n /** the host's /proc/meminfo numbers; null where the host has none */\n memory: HostMemory | null;\n /** the declared containers' memory in MiB by name; empty unless the probe asked docker */\n containers: Map<string, number>;\n}\nexport interface PortCheck {\n port: number;\n status: 'listening' | 'declared-not-listening';\n held_by?: {\n pid: number | null;\n command: string | null;\n app?: string;\n container?: string;\n };\n}\nexport interface AppPorts {\n actual: Listener[];\n declared: number[];\n checks: PortCheck[];\n undeclared: number[];\n}\n\nexport function splitAddr(s: string): { addr: string; port: number } {\n const i = s.lastIndexOf(':');\n return {\n addr: s.slice(0, i).replace(/^\\[|\\]$/g, ''),\n port: Number(s.slice(i + 1)),\n };\n}\n\nexport function parsePs(text: string): Map<number, number> {\n const tree = new Map<number, number>();\n for (const raw of text.split('\\n')) {\n const [pid, ppid] = raw.trim().split(/\\s+/);\n if (/^\\d+$/.test(pid ?? '') && /^\\d+$/.test(ppid ?? ''))\n tree.set(Number(pid), Number(ppid));\n }\n return tree;\n}\n\nexport function parseSs(text: string, proto: 'tcp' | 'udp'): Listener[] {\n const out: Listener[] = [];\n for (const raw of text.split('\\n')) {\n const line = raw.trim();\n if (!line) continue;\n const tok = line.split(/\\s+/);\n if (tok.length < 5) continue;\n const { addr, port } = splitAddr(tok[3]);\n if (!Number.isInteger(port) || port <= 0) continue;\n const pids = [...line.matchAll(/pid=(\\d+)/g)].map((h) => Number(h[1]));\n const cmd = /users:\\(\\(\"([^\"]*)\"/.exec(line);\n out.push({\n proto,\n addr,\n port,\n pid: pids[0] ?? null,\n pids,\n command: cmd ? cmd[1] : null,\n container: null,\n });\n }\n return out;\n}\n\nexport function hexToIp(hex: string): string {\n if (hex.length === 8) {\n return [6, 4, 2, 0].map((i) => parseInt(hex.slice(i, i + 2), 16)).join('.');\n }\n if (hex.length === 32) {\n const groups: string[] = [];\n for (let w = 0; w < 4; w++) {\n const word = hex.slice(w * 8, w * 8 + 8);\n const bytes = [6, 4, 2, 0].map((i) => word.slice(i, i + 2));\n groups.push(\n (bytes[0] + bytes[1]).toLowerCase(),\n (bytes[2] + bytes[3]).toLowerCase()\n );\n }\n if (groups.every((g) => g === '0000')) return '::';\n return groups.map((g) => g.replace(/^0+(?=\\w)/, '')).join(':');\n }\n return hex;\n}\n\nexport function parseProcNet(\n text: string,\n proto: 'tcp' | 'udp'\n): { addr: string; port: number; inode: number }[] {\n const want = proto === 'tcp' ? '0A' : '07';\n const out: { addr: string; port: number; inode: number }[] = [];\n for (const raw of text.split('\\n')) {\n const tok = raw.trim().split(/\\s+/);\n if (tok.length < 10 || !/^\\d+:$/.test(tok[0]) || tok[3] !== want) continue;\n const [a, p] = tok[1].split(':');\n out.push({\n addr: hexToIp(a),\n port: parseInt(p, 16),\n inode: Number(tok[9]),\n });\n }\n return out;\n}\n\nexport function parseFdMap(text: string): Map<number, number> {\n const m = new Map<number, number>();\n for (const raw of text.split('\\n')) {\n const [pid, inode] = raw.trim().split(/\\s+/);\n if (/^\\d+$/.test(pid ?? '') && /^\\d+$/.test(inode ?? ''))\n m.set(Number(inode), Number(pid));\n }\n return m;\n}\n\n/**\n * \"<url>\\t<code>\\t<exit>\\t<addr>\" lines of the URL section. code: the HTTP status, 0 when nothing answered, null when\n * the host has neither curl nor wget (\"-\"); a line whose code is neither is skipped. exit and addr: null when empty or\n * missing, so a shorter line still reads.\n */\nexport function parseUrlChecks(text: string): Map<string, HostUrl> {\n const m = new Map<string, HostUrl>();\n for (const raw of text.split('\\n')) {\n const [url, code, exit, addr] = raw.replace(/\\r$/, '').split('\\t');\n if (!url || code === undefined) continue;\n const c = code.trim();\n if (c !== '-' && !/^\\d{3}$/.test(c)) continue;\n m.set(url, {\n code: c === '-' ? null : Number(c),\n exit: exit?.trim() || null,\n addr: addr?.trim() || null,\n });\n }\n return m;\n}\n\n/** The environment section: `container <kind>`, `hostname <name>`, `self <addr> …` (each address once); null when absent. */\nexport function parseEnv(text: string): HostEnv | null {\n let container: HostEnv['container'] | null = null;\n let hostname: string | null = null;\n const self: string[] = [];\n for (const raw of text.split('\\n')) {\n const l = raw.trim();\n const c = /^container (docker|podman|lxc|none)$/.exec(l);\n if (c) container = c[1] as HostEnv['container'];\n const h = /^hostname (\\S+)$/.exec(l);\n if (h) hostname = h[1];\n if (l === 'self' || l.startsWith('self '))\n for (const a of l.slice(4).trim().split(/\\s+/))\n if (a && !self.includes(a)) self.push(a);\n }\n if (container === null && hostname === null && self.length === 0) return null;\n return { container: container ?? 'none', hostname, self };\n}\n\nfunction sections(stdout: string, marks: string[]): Record<string, string> {\n const lines = stdout.split('\\n');\n const idx = marks.map((m) => lines.findIndex((l) => l.trim() === m));\n const out: Record<string, string> = {};\n marks.forEach((m, k) => {\n const start = idx[k];\n if (start < 0) {\n out[m] = '';\n return;\n }\n const next = idx.slice(k + 1).find((i) => i > start) ?? lines.length;\n out[m] = lines.slice(start + 1, next).join('\\n');\n });\n return out;\n}\n\n/** The environment and URL sections of a probe's output, or of doctor's url check, which prints only those two. */\nexport function parseUrlProbe(stdout: string): {\n env: HostEnv | null;\n urls: Map<string, HostUrl>;\n} {\n const sec = sections(stdout, [MARK.ENV, MARK.URL]);\n return { env: parseEnv(sec[MARK.ENV]), urls: parseUrlChecks(sec[MARK.URL]) };\n}\n\n/** The clock section's `date +%z`; null when it is absent or not a real offset, as logs since reads a zone. */\nconst zoneOf = (section: string | undefined): string | null => {\n const z = (section ?? '').trim();\n return isZone(z) ? z : null;\n};\n\nexport function parseProbe(stdout: string): ProbeData {\n const sec = sections(stdout, [\n MARK.JLIST,\n MARK.CLOCK,\n MARK.PS,\n MARK.TCP,\n MARK.UDP,\n MARK.FD,\n MARK.STAT,\n MARK.STAT2,\n MARK.RSS,\n MARK.ARGS,\n MARK.DOCKER,\n MARK.MEM,\n MARK.DOCKERMEM,\n MARK.ENV,\n MARK.URL,\n ]);\n const rc = new RegExp(`${MARK.JLIST_RC} (\\\\d+)`).exec(sec[MARK.JLIST]);\n const jlistRaw = sec[MARK.JLIST].replace(\n new RegExp(`${MARK.JLIST_RC} \\\\d+\\\\s*$`),\n ''\n );\n const tree = parsePs(sec[MARK.PS]);\n const fd = parseFdMap(sec[MARK.FD]);\n const listeners: Listener[] = [];\n for (const [proto, text] of [\n ['tcp', sec[MARK.TCP]],\n ['udp', sec[MARK.UDP]],\n ] as const) {\n if (text.trim().startsWith(MARK.PROC)) {\n for (const e of parseProcNet(text.replace(MARK.PROC, ''), proto))\n listeners.push({\n proto,\n addr: e.addr,\n port: e.port,\n pid: fd.get(e.inode) ?? null,\n pids: fd.has(e.inode) ? [fd.get(e.inode)!] : [],\n command: null,\n container: null,\n });\n } else {\n listeners.push(...parseSs(text, proto));\n }\n }\n const s1 = parseStat(sec[MARK.STAT]);\n const samples = [s1.sample];\n if (sec[MARK.STAT2].trim()) samples.push(parseStat(sec[MARK.STAT2]).sample);\n // docker-published ports do not depend on /proc: a host without stat samples (no tree metrics) still attributes them\n const dockerPorts = parseDockerPorts(sec[MARK.DOCKER]);\n const stats: ProcStats =\n s1.sample.ticks.size === 0\n ? { ...EMPTY_STATS, dockerPorts }\n : {\n clkTck: s1.clkTck,\n samples,\n rssKb: parseRss(sec[MARK.RSS]),\n args: parseArgs(sec[MARK.ARGS]),\n dockerPorts,\n };\n for (const l of listeners)\n if (l.pid === null) l.container = stats.dockerPorts.get(l.port) ?? null;\n return {\n jlistRaw,\n jlistRc: rc ? Number(rc[1]) : -1,\n tree,\n listeners,\n stats,\n urls: parseUrlChecks(sec[MARK.URL]),\n env: parseEnv(sec[MARK.ENV]),\n zone: zoneOf(sec[MARK.CLOCK]),\n memory: parseMeminfo(sec[MARK.MEM]),\n containers: parseDockerStats(sec[MARK.DOCKERMEM]),\n };\n}\n\nexport function descendants(\n tree: Map<number, number>,\n root: number\n): Set<number> {\n const out = new Set<number>();\n if (root <= 0) return out;\n const children = new Map<number, number[]>();\n for (const [pid, ppid] of tree) {\n const arr = children.get(ppid) ?? [];\n arr.push(pid);\n children.set(ppid, arr);\n }\n const queue = [root];\n while (queue.length) {\n const p = queue.shift()!;\n for (const c of children.get(p) ?? [])\n if (!out.has(c)) {\n out.add(c);\n queue.push(c);\n }\n }\n return out;\n}\n\nexport function holderOf(\n listeners: Listener[],\n port: number,\n pidToApp: Map<number, string>\n): PortCheck['held_by'] | undefined {\n const l =\n listeners.find((x) => x.port === port && x.proto === 'tcp') ??\n listeners.find((x) => x.port === port);\n if (!l) return undefined;\n const app = l.pids.map((p) => pidToApp.get(p)).find(Boolean);\n const base = {\n pid: l.pid,\n command: l.command,\n ...(l.container ? { container: l.container } : {}),\n };\n return app ? { ...base, app } : base;\n}\n\n/** pm2 root pid plus every descendant, per manifest app; an app without a running process gets an empty set. */\nexport function appPids(\n apps: Record<string, App>,\n procs: Pm2Process[],\n tree: Map<number, number>,\n project: string\n): Map<string, Set<number>> {\n const out = new Map<string, Set<number>>();\n for (const app of Object.values(apps)) {\n const p = findProcess(procs, project, app.name);\n const set = p && p.pid > 0 ? descendants(tree, p.pid) : new Set<number>();\n if (p && p.pid > 0) set.add(p.pid);\n out.set(app.name, set);\n }\n return out;\n}\n\nexport function joinPorts(\n apps: Record<string, App>,\n procs: Pm2Process[],\n data: ProbeData,\n project: string\n): Record<string, AppPorts> {\n const pidsOf = appPids(apps, procs, data.tree, project);\n const pidToApp = new Map<number, string>();\n for (const [name, set] of pidsOf)\n for (const pid of set) pidToApp.set(pid, name);\n const result: Record<string, AppPorts> = {};\n for (const app of Object.values(apps)) {\n const pids = pidsOf.get(app.name)!;\n const actual = data.listeners.filter((l) =>\n l.pids.some((p) => pids.has(p))\n );\n const actualPorts = new Set(actual.map((l) => l.port));\n const checks: PortCheck[] = app.ports.map((port) => {\n if (actualPorts.has(port)) return { port, status: 'listening' };\n const held_by = holderOf(data.listeners, port, pidToApp);\n return held_by\n ? { port, status: 'declared-not-listening', held_by }\n : { port, status: 'declared-not-listening' };\n });\n const undeclared = [...actualPorts]\n .filter((p) => !app.ports.includes(p))\n .sort((a, b) => a - b);\n result[app.name] = { actual, declared: app.ports, checks, undeclared };\n }\n return result;\n}\n","import { keepSgr, SGR_RE } from './logs.js';\nimport type { Context } from './resolve.js';\nimport { shq } from '../transport/quote.js';\nimport { ensureOk } from '../transport/index.js';\nimport { hex16 } from '../shell/snippets.js';\nimport type { FileMark } from './incidents/cursor.js';\nimport { selectSince } from './logsince.js';\nimport { open, type FileHandle } from 'node:fs/promises';\nimport path from 'node:path';\nimport { dirWatchers } from './logwatch.js';\nimport { hostStreamFor, type HostStream } from './hoststream.js';\nimport {\n type ChunkRequest,\n HEX,\n HISTORY_BYTES,\n type LogChunk,\n READ_CAP,\n} from './logchunk.js';\n\nexport interface LogLine {\n stream: 'out' | 'err';\n text: string;\n}\n\n/**\n * One poll: the new lines; `reset` when a file was replaced under the follower (its lines start over); `lost` when\n * lines written since the last poll are missing from them: a burst too big for one read was skipped to its last part,\n * a replaced file was read from its tail, or the host stream delivered more lines than a poll keeps. The follower\n * always says; a stand-in for it may leave `lost` out.\n */\nexport interface FollowPoll {\n lines: LogLine[];\n reset: boolean;\n lost?: boolean;\n}\n\n/** An unfinished line longer than this is shown cut. */\nconst MAX_PENDING = 65536;\n/** Lines a host stream delivered that nobody polled yet are kept up to this many (the newest). */\nconst MAX_READY = 10_000;\n\nexport type { ChunkRequest, LogChunk } from './logchunk.js';\ntype ChunkReader = (reqs: ChunkRequest[]) => Promise<LogChunk[]>;\n\n/**\n * Where a follower starts after a one-shot read: each stream with a mark continues right after it; a stream without one\n * (its app was not running, or its read was cut short) shows from its history the lines at or after `cutoff`, a pm2\n * stamp in the host's local time, instead of the last initialLines.\n */\nexport interface StartAt {\n out?: FileMark;\n err?: FileMark;\n cutoff?: string;\n}\n\n/**\n * Every read is bounded to the size just measured: bytes appended between `wc -c` and `tail` belong to the next poll,\n * never to both. The host sends the header and the raw bytes; lines are picked by the follower.\n */\nfunction chunkScript(reqs: ChunkRequest[]): string {\n return reqs\n .map(({ path, off, anchor }, i) => {\n const f = shq(path);\n const tail = `st=$((sz>${HISTORY_BYTES}?sz-${HISTORY_BYTES}:0))`; // history: the last lines of what was measured\n const replaced =\n off !== null && anchor\n ? ` || [ \"${hex16(f, String(off))}\" != '${anchor}' ]`\n : '';\n const pick =\n off === null\n ? `k=H; ${tail}`\n : `if [ \"$sz\" -lt ${off} ]${replaced}; then k=R; ${tail}; elif [ $((sz-${off})) -gt ${READ_CAP} ]; then k=S; st=$((sz-${READ_CAP})); else k=N; st=${off}; fi`;\n return `echo ${CHUNK_MARK[i]}; sz=$(wc -c < ${f} 2>/dev/null || echo 0); sz=$((sz+0)); ${pick}; echo \"$sz $st $k ${hex16(f, '$sz')}\"; if [ \"$sz\" -gt \"$st\" ]; then tail -c +$((st+1)) ${f} 2>/dev/null | head -c $((sz-st)); fi`;\n })\n .join('; ');\n}\nconst CHUNK_MARK = ['__MCPROC_LF_out__', '__MCPROC_LF_err__'];\n\n/** Reads through the host's shell: one command for both files. */\nfunction shellReader(ctx: Context): ChunkReader {\n return async (reqs) => {\n const res = ensureOk(\n await ctx.transport.exec(chunkScript(reqs)),\n ctx.host,\n 'follow logs'\n );\n return reqs.map((_, i) => {\n const mark = `${CHUNK_MARK[i]}\\n`;\n const at = res.stdout.indexOf(mark);\n const from = reqs[i].off;\n if (at < 0)\n return {\n from,\n size: 0,\n start: 0,\n kind: 'N',\n anchor: '',\n body: '',\n got: 0,\n };\n const next =\n i + 1 < reqs.length\n ? res.stdout.indexOf(`${CHUNK_MARK[i + 1]}\\n`, at)\n : -1;\n const text = res.stdout.slice(\n at + mark.length,\n next < 0 ? undefined : next\n );\n const nl = text.indexOf('\\n');\n const [sizeText, stText, kind = 'N', anchor = ''] = text\n .slice(0, nl)\n .trim()\n .split(/\\s+/);\n const body = text.slice(nl + 1);\n return {\n from,\n size: Number(sizeText) || 0,\n start: Number(stText) || 0,\n kind: (/^[HRSN]$/.test(kind) ? kind : 'N') as LogChunk['kind'],\n anchor,\n body,\n got: Buffer.byteLength(body, 'utf8'),\n };\n });\n };\n}\n\n/** The hex of the up to 16 bytes before `end`. */\nasync function hexBefore(fh: FileHandle, end: number): Promise<string> {\n const n = Math.min(16, end);\n if (n <= 0) return '';\n const { buffer, bytesRead } = await fh.read(Buffer.alloc(n), 0, n, end - n);\n return buffer.subarray(0, bytesRead).toString('hex');\n}\n\n/**\n * Reads one file of this machine in-process, with the shell read's rules: same kinds, caps and counting. The anchor\n * comes from the bytes delivered (one read that starts up to 16 bytes before them), never from a later read: a file\n * rewritten in between must not lend its anchor to bytes of the old one.\n */\nexport async function readChunk(\n req: ChunkRequest,\n openFile: (path: string, flags: string) => Promise<FileHandle> = open\n): Promise<LogChunk> {\n let fh: FileHandle;\n try {\n fh = await openFile(req.path, 'r');\n } catch (e) {\n if ((e as NodeJS.ErrnoException).code !== 'ENOENT') throw e;\n const kind = req.off === null ? 'H' : req.off > 0 ? 'R' : 'N';\n const from = req.off;\n return { from, size: 0, start: 0, kind, anchor: '', body: '', got: 0 };\n }\n try {\n const size = (await fh.stat()).size;\n const tail = Math.max(0, size - HISTORY_BYTES);\n const { off } = req;\n let kind: LogChunk['kind'];\n let start: number;\n if (off === null) [kind, start] = ['H', tail];\n else if (\n size < off ||\n (req.anchor && (await hexBefore(fh, off)) !== req.anchor)\n )\n [kind, start] = ['R', tail];\n else if (size - off > READ_CAP) [kind, start] = ['S', size - READ_CAP];\n else [kind, start] = ['N', off];\n const lo = Math.min(start, Math.max(0, size - 16));\n const buf = Buffer.alloc(size - lo);\n let n = 0;\n while (n < buf.length) {\n const { bytesRead } = await fh.read(buf, n, buf.length - n, lo + n);\n if (!bytesRead) break;\n n += bytesRead;\n }\n const pre = start - lo;\n return {\n from: req.off,\n size,\n start,\n kind,\n anchor:\n n >= buf.length\n ? buf.subarray(Math.max(0, n - 16), n).toString('hex')\n : '',\n body: buf.subarray(Math.min(pre, n), n).toString('utf8'),\n got: Math.max(0, n - pre),\n };\n } finally {\n await fh.close();\n }\n}\n\n/** Follows an app's pm2 log files by byte offset: history first, then only new bytes. */\nexport class LogFollower {\n readonly offsets: { out: number | null; err: number | null } = {\n out: null,\n err: null,\n };\n /** the hex of the 16 bytes before each offset: if they changed, the file was replaced or truncated and grew back */\n private anchors: { out: string | null; err: string | null } = {\n out: null,\n err: null,\n };\n private pending: { out: string; err: string } = { out: '', err: '' };\n /** the stamp a stream's first history is cut at, when it was started without a mark */\n private cutoffs: { out: string | null; err: string | null } = {\n out: null,\n err: null,\n };\n private read: ChunkReader;\n private unwatch: (() => void)[] = [];\n private stream: HostStream | null = null;\n private wake: (() => void) | null = null;\n /** what the host stream delivered since the last poll */\n private ready: LogLine[] = [];\n private readyReset = false;\n private readyLost = false;\n constructor(\n private readonly ctx: Context,\n private readonly paths: { out: string; err: string },\n private readonly initialLines = 200,\n /** in-process reads (this machine's files); a file this process may not read sends it back to the shell */\n private readonly local = false\n ) {\n this.read = local ? this.readHere : shellReader(ctx);\n }\n\n /**\n * Calls `wake` when one of the followed files changes, so the caller polls right away instead of on its clock. This\n * machine's files: their directories are watched, so a rotated file is seen under its name again. A remote host's:\n * its host stream reads them as they grow, and a poll takes what it delivered without running a command.\n */\n watch(wake: () => void): void {\n this.close();\n this.wake = wake;\n if (!this.local) {\n this.stream = hostStreamFor(this.ctx.transport);\n this.stream?.add(this);\n return;\n }\n const byDir = new Map<string, Set<string>>();\n for (const p of [this.paths.out, this.paths.err]) {\n const dir = path.dirname(p);\n byDir.set(dir, (byDir.get(dir) ?? new Set()).add(path.basename(p)));\n }\n for (const [dir, names] of byDir)\n this.unwatch.push(\n dirWatchers.watch(dir, (file) => {\n if (file === null || names.has(file)) wake();\n })\n );\n }\n\n /** Stops the wakes; the follower can still be polled. */\n close(): void {\n for (const off of this.unwatch.splice(0)) off();\n this.stream?.remove(this);\n this.stream = null;\n this.wake = null;\n }\n\n /**\n * Continue after marks a one-shot read returned (the end of what it read, with the anchor of the bytes before it): the\n * next poll reads only what came after them, and a file replaced since is detected through the anchor and read from\n * its start. A mark of another path is ignored; an anchor taken elsewhere than at the offset is dropped. A stream left\n * without a mark that has not been read yet takes the cutoff for its first history, so what its app wrote between\n * that read and this follower's first poll is still shown.\n */\n seek(at: StartAt): void {\n for (const s of ['out', 'err'] as const) {\n const m = at[s];\n if (!m || m.path !== this.paths[s]) {\n if (at.cutoff !== undefined && this.offsets[s] === null)\n this.cutoffs[s] = at.cutoff;\n continue;\n }\n this.offsets[s] = m.offset;\n this.anchors[s] =\n m.anchor !== undefined && m.at === m.offset && HEX.test(m.anchor)\n ? m.anchor\n : null;\n this.pending[s] = '';\n this.cutoffs[s] = null;\n }\n }\n\n /** where each file is followed from, for the host stream */\n requests(): ChunkRequest[] {\n return (['out', 'err'] as const).map((s) => ({\n path: this.paths[s],\n off: this.offsets[s],\n anchor: this.anchors[s],\n }));\n }\n\n /** a read the host stream made of file `k` (0 out, 1 err); false when it does not continue where this one stands */\n offer(k: number, c: LogChunk): boolean {\n const s = k === 0 ? 'out' : 'err';\n if (!this.fits(s, c)) return false;\n const kind = this.apply(s, c, this.ready);\n if (kind === 'R') this.readyReset = true;\n if (kind === 'R' || kind === 'S') this.readyLost = true;\n if (this.ready.length > MAX_READY) {\n this.ready.splice(0, this.ready.length - MAX_READY);\n this.readyLost = true;\n }\n this.wake?.();\n return true;\n }\n\n private fits(s: 'out' | 'err', c: LogChunk): boolean {\n return (c.from ?? -1) === (this.offsets[s] ?? -1);\n }\n\n private readHere: ChunkReader = async (reqs) => {\n try {\n return await Promise.all(reqs.map((r) => readChunk(r)));\n } catch (e) {\n const code = (e as NodeJS.ErrnoException).code;\n if (code !== 'EACCES' && code !== 'EPERM') throw e;\n this.read = shellReader(this.ctx);\n return this.read(reqs);\n }\n };\n\n async poll(): Promise<FollowPoll> {\n if (!this.stream?.covers(this)) {\n const chunks = await this.read(this.requests());\n const out: LogLine[] = [];\n let reset = false;\n let lost = false;\n (['out', 'err'] as const).forEach((s, i) => {\n // a read the stream overtook meanwhile is not applied twice\n if (!this.fits(s, chunks[i])) return;\n const kind = this.apply(s, chunks[i], out);\n reset ||= kind === 'R';\n lost ||= kind === 'R' || kind === 'S';\n });\n this.ready.push(...out);\n this.readyReset ||= reset;\n this.readyLost ||= lost;\n }\n const r = {\n lines: this.ready,\n reset: this.readyReset,\n lost: this.readyLost,\n };\n this.ready = [];\n this.readyReset = false;\n this.readyLost = false;\n return r;\n }\n\n /** Picks the lines of one read and moves the stream on by what arrived; returns the read's kind. */\n private apply(\n s: 'out' | 'err',\n c: LogChunk,\n out: LogLine[]\n ): LogChunk['kind'] {\n const { size, start: st, kind, body } = c;\n const off = this.offsets[s];\n const fresh = kind !== 'N'; // history, a replaced file or a skipped burst: what came before is not continued\n if (fresh) this.pending[s] = '';\n if (kind === 'S')\n out.push({\n stream: s,\n text: `… ${Math.max(0, st - (off ?? 0))} bytes of new log skipped`,\n });\n // a window that begins inside a line starts with a fragment of it\n const text =\n fresh && st > 0\n ? body.slice(body.indexOf('\\n') + 1 || body.length)\n : this.pending[s] + body;\n const complete = text.endsWith('\\n')\n ? text\n : text.slice(0, text.lastIndexOf('\\n') + 1);\n this.pending[s] = text.slice(complete.length);\n // a line that never ends is shown cut once it is long enough, instead of waiting in memory without limit\n const longLine =\n this.pending[s].length > MAX_PENDING\n ? `${keepSgr(this.pending[s].slice(0, MAX_PENDING))}…`\n : null;\n if (longLine) this.pending[s] = '';\n // escapes are cleaned per complete line: a color code cut by a read boundary waits in `pending` with its line\n const lines = complete.split('\\n').slice(0, -1);\n // history is cut to the last initialLines (none for 0), or by time when a cutoff was given: the lines at or after\n // it, an unstamped line going with the stamped one before it. A replaced file is cut to the last initialLines too,\n // except that with 0 the follower asked for no history, and everything a file replaced under it holds was written\n // after it began\n const cutoff = this.cutoffs[s];\n this.cutoffs[s] = null; // only the first read, the one that starts the stream, is a history\n const shown =\n kind === 'H'\n ? cutoff !== null\n ? selectSince(lines, cutoff).kept.map((k) => k.text)\n : this.initialLines > 0\n ? lines.slice(-this.initialLines)\n : []\n : kind === 'R' && this.initialLines > 0\n ? lines.slice(-this.initialLines)\n : lines;\n for (const line of shown) {\n const t = keepSgr(line);\n if (t.replace(SGR_RE, '').length) out.push({ stream: s, text: t });\n }\n if (longLine) out.push({ stream: s, text: longLine });\n // what arrived, counted exactly: a read cut short (the file changed or failed meanwhile) goes on from there next poll\n const whole = c.got >= size - st;\n this.offsets[s] = whole ? size : st + c.got;\n this.anchors[s] = whole && HEX.test(c.anchor) ? c.anchor : null; // known only for the measured size\n return kind;\n }\n}\n\n/** The follower a host gets: this machine's files are read in-process, a remote host's through its shell. */\nexport function createFollower(\n ctx: Context,\n paths: { out: string; err: string },\n initialLines = 200\n): LogFollower {\n return new LogFollower(ctx, paths, initialLines, ctx.host.local);\n}\n\nconst STAMP = /^(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{3})?)/; // seconds, or milliseconds\n/** Stamped lines are ordered by pm2's timestamp prefix (stable); lines without a stamp keep their positions. */\nexport function sortByStamp<T extends { text: string }>(lines: T[]): T[] {\n const keyed = lines.map((l, i) => ({\n l,\n i,\n k: STAMP.exec(l.text)?.[1] ?? null,\n }));\n const stamped = keyed\n .filter((x) => x.k !== null)\n .sort((a, b) => (a.k! < b.k! ? -1 : a.k! > b.k! ? 1 : a.i - b.i));\n let j = 0;\n return keyed.map((x) => (x.k === null ? x.l : stamped[j++].l));\n}\n","import { watch as fsWatch, type FSWatcher } from 'node:fs';\n\ntype Listener = (file: string | null) => void;\ntype Watch = (\n dir: string,\n opts: { persistent: boolean },\n cb: (event: string, file: string | Buffer | null) => void\n) => Pick<FSWatcher, 'close' | 'on'>;\ninterface Entry {\n watcher: Pick<FSWatcher, 'close' | 'on'> | null;\n listeners: Set<Listener>;\n}\n\n/**\n * Tells subscribers which file of a directory changed (null when the system does not say). One OS watcher per\n * directory, shared by every subscriber and closed with the last one; it never keeps the process alive. A directory\n * that cannot be watched (missing, no access) gives no events, and the next subscriber tries again: callers keep their\n * own clock as the fallback.\n */\nexport class DirWatchers {\n private dirs = new Map<string, Entry>();\n constructor(private readonly open: Watch = fsWatch as unknown as Watch) {}\n\n watch(dir: string, onChange: Listener): () => void {\n let e = this.dirs.get(dir);\n if (!e) {\n e = { watcher: null, listeners: new Set() };\n this.dirs.set(dir, e);\n }\n const entry = e;\n if (!entry.watcher) {\n try {\n entry.watcher = this.open(dir, { persistent: false }, (_ev, file) => {\n for (const l of entry.listeners) l(file ? String(file) : null);\n });\n // the directory went away: no more events until someone subscribes again\n entry.watcher.on('error', () => {\n entry.watcher?.close();\n entry.watcher = null;\n });\n } catch {\n entry.watcher = null;\n }\n }\n entry.listeners.add(onChange);\n return () => {\n entry.listeners.delete(onChange);\n if (entry.listeners.size || this.dirs.get(dir) !== entry) return;\n entry.watcher?.close();\n this.dirs.delete(dir);\n };\n }\n}\n\n/** the watchers of this process */\nexport const dirWatchers = new DirWatchers();\n","import { randomBytes } from 'node:crypto';\nimport { shq } from '../transport/quote.js';\nimport type { StreamProc, Transport } from '../transport/types.js';\nimport { hex16 } from '../shell/snippets.js';\nimport {\n type ChunkRequest,\n HEX,\n HISTORY_BYTES,\n type LogChunk,\n READ_CAP,\n} from './logchunk.js';\n\n/**\n * The loop a host runs for its followed files, under a plain POSIX sh. Every 250 ms one `stat` measures them all: size,\n * inode and mtime (`wc -c` per file, size only, where stat has no -c). A file whose size moved is read with the\n * follower's rules (H/R/S/N); one whose size stayed but whose inode or mtime changed has its anchor checked, so a\n * replacement of the same length is seen too. The bytes are copied to a temp file together with up to 16 bytes before\n * them, counted, and sent as a frame: `<nonce> <i> <from> <size> <start> <kind> <got> <anchor>`, the raw bytes,\n * `\\n<nonce> end`; the anchor comes from that copy, never from a later read. Its own position becomes start + got.\n *\n * The loop ends with its client either way the client can go: its stdin closes (a killed `docker exec` client leaves\n * the command running and its output still read by the daemon, but closes its stdin), or its output does (a heartbeat\n * line per round meets SIGPIPE). The outer shell waits on stdin with the `read` builtin, so no extra process is left\n * behind in a container whose first process never reaps orphans.\n */\nexport function loopScript(\n nonce: string,\n files: ChunkRequest[],\n /** the stat format (size, inode, mtime), or null to measure with `wc -c` as on a host without `stat -c` */\n opts: { stat?: string | null } = {}\n): string {\n const statFormat = opts.stat === undefined ? '%s %i %.9Y' : opts.stat;\n const vars = files\n .map(\n (f, i) =>\n `p${i}=${shq(f.path)} o${i}=${f.off ?? -1} a${i}=${f.anchor && HEX.test(f.anchor) ? f.anchor : \"''\"} q${i}= c${i}=0`\n )\n .join('\\n');\n return [\n `N=${nonce} K=${files.length} HB=${HISTORY_BYTES} CAP=${READ_CAP}`,\n vars,\n '(',\n `t=$(mktemp 2>/dev/null) || t=\"\\${TMPDIR:-/tmp}/mcproc-follow.$$\"`,\n `trap 'rm -f \"$t\"; kill $$ 2>/dev/null' EXIT`, // gone by itself (SIGPIPE): the waiting shell goes too\n `trap 'exit 1' HUP INT TERM PIPE`,\n statFormat === null\n ? 'gs='\n : `SF=${shq(statFormat)}; gs=; stat -L -c %s / >/dev/null 2>&1 && gs=1`,\n 'nap=1; sleep 0.01 2>/dev/null && nap=0.25',\n 'one() {',\n ' eval \"p=\\\\$p$1 o=\\\\$o$1 a=\\\\$a$1 q=\\\\$q$1 c=\\\\$c$1\"',\n ' sz=$2',\n // same size: the file was replaced only if the bytes before the position differ. They are checked when the\n // identity moved; a whole-second mtime (busybox) can hide a rewrite within the second of the last change, so a\n // changed file is checked for five rounds after; with no identity at all (`wc`), also every 8th round\n ' if [ \"$o\" -ge 0 ] && [ \"$sz\" -eq \"$o\" ]; then',\n ' if [ \"$3\" = \"$q\" ]; then',\n ' case \"$3\" in *.*.*) return 0 ;; esac', // a nanosecond mtime shows every rewrite\n ' if [ \"$c\" -gt 0 ]; then eval \"c$1=$((c-1))\"',\n ` elif [ \"$3\" != '-.-' ] || [ $((r%8)) -ne 0 ]; then return 0; fi`,\n ' else eval \"q$1=\\\\$3 c$1=5\"; fi',\n ` { [ -z \"$a\" ] || [ \"${hex16('\"$p\"', '$o')}\" = \"$a\" ]; } && return 0`,\n ' fi',\n ' eval \"q$1=\\\\$3 c$1=5\"',\n ' if [ \"$o\" -lt 0 ]; then k=H; st=$((sz>HB?sz-HB:0))',\n ` elif [ \"$sz\" -lt \"$o\" ] || { [ -n \"$a\" ] && [ \"${hex16('\"$p\"', '$o')}\" != \"$a\" ]; }; then k=R; st=$((sz>HB?sz-HB:0))`,\n ' elif [ $((sz-o)) -gt $CAP ]; then k=S; st=$((sz-CAP))',\n ' else k=N; st=$o; fi',\n ' lo=$((sz>16?sz-16:0)); [ \"$lo\" -gt \"$st\" ] && lo=$st',\n ' if [ \"$sz\" -gt \"$lo\" ]; then tail -c +$((lo+1)) \"$p\" 2>/dev/null | head -c $((sz-lo)) >\"$t\"; else : >\"$t\"; fi',\n ' all=$(wc -c <\"$t\"); all=$((all+0)); pre=$((st-lo)); got=$((all>pre?all-pre:0))',\n ` if [ \"$all\" -ge $((sz-lo)) ]; then na=$(tail -c 16 \"$t\" | od -An -tx1 | tr -d ' \\\\n'); no=$sz; else na=; no=$((st+got)); fi`,\n ` printf '%s %s %s %s %s %s %s %s\\\\n' \"$N\" \"$1\" \"$o\" \"$sz\" \"$st\" \"$k\" \"$got\" \"$na\"`,\n ' if [ \"$pre\" -eq 0 ]; then cat \"$t\"; else tail -c +$((pre+1)) \"$t\"; fi',\n ` printf '\\\\n%s end\\\\n' \"$N\"`,\n ' eval \"o$1=\\\\$no a$1=\\\\$na\"',\n '}',\n 'r=0',\n 'while :; do',\n ' r=$((r+1)); set --; e=; i=0; nf=0',\n ' while [ $i -lt $K ]; do',\n ' eval \"f=\\\\$p$i\"',\n ' if [ -f \"$f\" ]; then set -- \"$@\" \"$f\"; e=\"$e 1\"; nf=$((nf+1)); else e=\"$e 0\"; fi',\n ' i=$((i+1))',\n ' done',\n ' z=; ok=1',\n ' if [ $# -gt 0 ]; then',\n ' if [ -n \"$gs\" ]; then z=$(stat -L -c \"$SF\" -- \"$@\" 2>/dev/null) || ok=', // busybox: whole-second mtimes\n ' else for f in \"$@\"; do s=$(wc -c <\"$f\" 2>/dev/null) || { ok=; break; }; z=\"$z $((s+0)) - -\"; done; fi',\n ' fi',\n ' set -- $z',\n ' [ $# -eq $((nf*3)) ] || ok=', // a file that went away between the test and stat: next round\n ' if [ -n \"$ok\" ]; then',\n ' i=0',\n ' for x in $e; do',\n ' if [ \"$x\" = 1 ]; then sz=$1; id=\"$2.$3\"; shift 3; else sz=0; id=; fi',\n ' one $i \"$sz\" \"$id\"',\n ' i=$((i+1))',\n ' done',\n ' fi',\n ` printf '%s hb\\\\n' \"$N\"`,\n ' sleep $nap',\n 'done',\n ') &',\n 'm=$!',\n 'while read -r _; do :; done', // until the client closes stdin\n `trap '' TERM`,\n 'kill $m 2>/dev/null',\n 'wait $m',\n ].join('\\n');\n}\n\nexport interface Frame {\n index: number;\n chunk: LogChunk;\n}\n\n/** Cuts the loop's output into frames and heartbeats; lines that are neither (a login banner) are skipped. */\nexport class FrameReader {\n private buf: Buffer = Buffer.alloc(0);\n private readonly head: string;\n private readonly trailer: Buffer;\n constructor(\n nonce: string,\n private readonly on: {\n frame(f: Frame): void;\n beat(): void;\n broken(): void;\n }\n ) {\n this.head = `${nonce} `;\n this.trailer = Buffer.from(`\\n${nonce} end\\n`);\n }\n\n push(data: Buffer): void {\n this.buf = this.buf.length ? Buffer.concat([this.buf, data]) : data;\n let at = 0;\n for (;;) {\n const nl = this.buf.indexOf(10, at);\n if (nl < 0) {\n if (this.buf.length - at > 4096) at = this.buf.length; // a long line of something else: headers are short\n break;\n }\n const line = this.buf.toString('latin1', at, nl);\n if (!line.startsWith(this.head)) {\n at = nl + 1;\n continue;\n }\n const f = line.slice(this.head.length).split(' ');\n if (f[0] === 'hb') {\n this.on.beat();\n at = nl + 1;\n continue;\n }\n const [index, from, size, start, got] = [\n f[0],\n f[1],\n f[2],\n f[3],\n f[5],\n ].map(Number);\n const kind = f[4];\n if (\n ![index, from, size, start, got].every(Number.isInteger) ||\n !/^[HRSN]$/.test(kind) ||\n got < 0\n ) {\n this.fail();\n return;\n }\n const end = nl + 1 + got + this.trailer.length;\n if (this.buf.length < end) break; // the rest of the frame is still on its way\n if (!this.buf.subarray(nl + 1 + got, end).equals(this.trailer)) {\n this.fail();\n return;\n }\n this.on.frame({\n index,\n chunk: {\n from: from < 0 ? null : from,\n size,\n start,\n kind: kind as LogChunk['kind'],\n got,\n anchor: f[6] ?? '',\n body: this.buf.toString('utf8', nl + 1, nl + 1 + got),\n },\n });\n at = end;\n }\n this.buf = this.buf.subarray(at);\n }\n\n private fail(): void {\n this.buf = Buffer.alloc(0);\n this.on.broken();\n }\n}\n\n/** What a host stream follows for: a follower's files and where it stands in them. */\nexport interface StreamMember {\n requests(): ChunkRequest[];\n /** a read of the member's file `k`; false when it does not continue where the member stands */\n offer(k: number, chunk: LogChunk): boolean;\n}\nexport interface HostStreamOptions {\n /** members joining or leaving within this time restart the loop once */\n debounceMs: number;\n /** waits before reconnecting after a drop, one per failure in a row (the last repeats) */\n backoffMs: number[];\n /** a loop silent this long is taken for dead */\n stallMs: number;\n}\nconst DEFAULTS: HostStreamOptions = {\n debounceMs: 150,\n backoffMs: [1000, 2000, 4000, 5000],\n stallMs: 15_000,\n};\n/** a loop that lived this long before it dropped starts the backoff over */\nconst STEADY_MS = 5000;\n\ninterface Run {\n proc: StreamProc;\n index: { m: StreamMember; k: number }[];\n members: Set<StreamMember>;\n live: boolean;\n liveAt: number;\n seen: number;\n}\n\n/**\n * One loop per host for every followed file there: restarted (from the members' own positions) when the set of\n * members changes or a member falls out of step, reconnected with a backoff when it drops or goes silent.\n */\nexport class HostStream {\n private members = new Set<StreamMember>();\n private run: Run | null = null;\n private timer: NodeJS.Timeout | null = null;\n private stall: NodeJS.Timeout | null = null;\n private failures = 0;\n private readonly opts: HostStreamOptions;\n constructor(\n private readonly transport: Transport,\n opts: Partial<HostStreamOptions> = {}\n ) {\n this.opts = { ...DEFAULTS, ...opts };\n }\n\n add(m: StreamMember): void {\n this.members.add(m);\n this.schedule(this.opts.debounceMs);\n }\n\n remove(m: StreamMember): void {\n if (!this.members.delete(m)) return;\n if (this.members.size) this.schedule(this.opts.debounceMs);\n else {\n if (this.timer) clearTimeout(this.timer);\n this.timer = null;\n this.kill();\n this.failures = 0;\n }\n }\n\n /** the loop runs, has been heard from, and follows this member */\n covers(m: StreamMember): boolean {\n return !!this.run?.live && this.run.members.has(m);\n }\n\n private schedule(ms: number): void {\n if (this.timer) clearTimeout(this.timer);\n this.timer = setTimeout(() => {\n this.timer = null;\n this.start();\n }, ms);\n this.timer.unref?.();\n }\n\n private kill(): void {\n const r = this.run;\n this.run = null;\n if (this.stall) clearInterval(this.stall);\n this.stall = null;\n if (!r) return;\n running.delete(r.proc);\n r.proc.kill();\n }\n\n private start(): void {\n this.kill();\n if (!this.members.size || !this.transport.stream) return;\n const index: Run['index'] = [];\n const reqs: ChunkRequest[] = [];\n for (const m of this.members)\n m.requests().forEach((r, k) => {\n index.push({ m, k });\n reqs.push(r);\n });\n const nonce = randomBytes(6).toString('hex');\n const proc = this.transport.stream(loopScript(nonce, reqs));\n const run: Run = {\n proc,\n index,\n members: new Set(this.members),\n live: false,\n liveAt: 0,\n seen: Date.now(),\n };\n this.run = run;\n running.add(proc);\n cleanUpOnExit();\n const heard = () => {\n run.seen = Date.now();\n if (run.live) return;\n run.live = true;\n run.liveAt = run.seen;\n };\n const reader = new FrameReader(nonce, {\n beat: heard,\n frame: ({ index: i, chunk }) => {\n heard();\n const e = run.index[i];\n if (!e || !this.members.has(e.m)) return;\n if (!e.m.offer(e.k, chunk)) this.schedule(this.opts.debounceMs); // out of step: start again from where it stands\n },\n broken: () => {\n if (this.run === run) proc.kill();\n },\n });\n proc.onData((d) => {\n if (this.run === run) reader.push(d);\n });\n proc.onExit(() => {\n running.delete(proc);\n if (this.run !== run) return; // stopped or replaced on purpose\n this.kill();\n if (run.live && Date.now() - run.liveAt > STEADY_MS) this.failures = 0;\n const b = this.opts.backoffMs;\n const wait = b[Math.min(this.failures, b.length - 1)];\n this.failures++;\n if (this.members.size) this.schedule(wait);\n });\n this.stall = setInterval(\n () => {\n if (this.run === run && Date.now() - run.seen > this.opts.stallMs)\n proc.kill();\n },\n Math.min(1000, this.opts.stallMs)\n );\n this.stall.unref?.();\n }\n}\n\n/** the loops of this process: stopped when it exits, so none outlives mcproc on a host */\nconst running = new Set<StreamProc>();\nlet armed = false;\nfunction cleanUpOnExit(): void {\n if (armed) return;\n armed = true;\n process.once('exit', () => {\n for (const p of running) p.kill();\n });\n}\n\nconst streams = new WeakMap<Transport, HostStream>();\n/** The stream of the host behind this transport; null when the transport cannot stream. */\nexport function hostStreamFor(t: Transport): HostStream | null {\n if (!t.stream) return null;\n let s = streams.get(t);\n if (!s) {\n s = new HostStream(t);\n streams.set(t, s);\n }\n return s;\n}\n","/** At most this many new bytes are read per file per read; a bigger burst is read from its newest part. */\nexport const READ_CAP = 1048576;\n/** History (the first read, or a replaced file) comes from this many last bytes: the last lines are picked from them. */\nexport const HISTORY_BYTES = 262144;\nexport const HEX = /^[0-9a-f]{1,64}$/;\n\n/**\n * One file's read: the position it continues from (null: none yet), the size measured, where the read began and why\n * (H history, R the file was replaced or shrank, S a burst over READ_CAP, N new bytes), the hex of the 16 bytes before\n * `size`, and the bytes read, counted exactly.\n */\nexport interface LogChunk {\n from: number | null;\n size: number;\n start: number;\n kind: 'H' | 'R' | 'S' | 'N';\n anchor: string;\n body: string;\n got: number;\n}\n/** Where a file is followed from: the offset reached and the anchor known for it (null before the first read). */\nexport interface ChunkRequest {\n path: string;\n off: number | null;\n anchor: string | null;\n}\n","import { McprocError } from './errors.js';\nimport {\n cut,\n MATCH_BUDGET_MS,\n runOwnPatterns,\n searched,\n stampOf,\n} from './incidents/detect.js';\nimport { msStamp } from './logsince.js';\nimport { stripAnsi } from './logs.js';\nimport type { ReloadSettings } from './manifest.js';\n\n/**\n * Marker lines closer together than this are one reload: a rebuild prints one line per changed file (a library rebuild\n * under Vite printed 43 `page reload` lines within milliseconds), and a restart is followed by the server's new\n * `listening` line within a second.\n */\nexport const RELOAD_GAP_MS = 2000;\nexport type ReloadKind = 'restart' | 'rebuild' | 'relisten';\nexport interface ReloadMarker {\n id: string;\n re: RegExp;\n kind: ReloadKind;\n}\n/** How dev tools report a reload inside their own process, which pm2 never sees (matched against the line without pm2's stamp and without ANSI). */\nexport const BUILTIN_RELOAD_MARKERS: ReloadMarker[] = [\n { id: 'tsx', re: /\\[tsx\\] .*\\bRestarting\\.\\.\\./, kind: 'restart' },\n {\n id: 'nodemon',\n re: /\\[nodemon\\] restarting due to changes/,\n kind: 'restart',\n },\n { id: 'node-watch', re: /^\\s*Restarting '[^']+'\\s*$/, kind: 'restart' },\n {\n id: 'vite',\n re: /\\[vite\\] (?:\\(client\\) )?(?:page reload|hmr update)\\b/,\n kind: 'rebuild',\n },\n // `✓ Compiled /page in` (with a route) is a first compile of that page, not a reload\n { id: 'next', re: /✓ Compiled in \\d|\\bReload env: /, kind: 'rebuild' },\n {\n id: 'tsc',\n re: /File change detected\\. Starting incremental compilation/,\n kind: 'rebuild',\n },\n // an app's own startup line: the first burst after the start is the boot, every later one a reload (bun --watch prints nothing else)\n { id: 'listening', re: /\\blistening (?:on|at)\\b/i, kind: 'relisten' },\n];\n\n/** The built-in markers in force, and the app's own patterns as written (they run under a time budget, see runOwnPatterns). */\nexport interface ReloadRules {\n markers: ReloadMarker[];\n match: string[];\n ignore: string[];\n budgetMs: number;\n}\nexport function compileReloadRules(\n s: ReloadSettings,\n budgetMs = MATCH_BUDGET_MS\n): ReloadRules {\n return {\n markers: s.defaults ? BUILTIN_RELOAD_MARKERS : [],\n match: s.match,\n ignore: s.ignore,\n budgetMs,\n };\n}\n\n/**\n * One reload: a burst of marker lines. `line` (stamp kept), `marker` (the id it matched) and `time` are the burst's\n * first restart or rebuild line, else its first line: a restart that joined the boot's `listening` line is shown, not\n * the boot. `last_time` and `lines` cover the whole burst.\n */\nexport interface Reload {\n time: string | null;\n last_time: string | null;\n lines: number;\n line: string;\n marker: string;\n}\n/** A line as pm2 wrote it (stamp included); each stream's lines come in file order. */\nexport interface ReloadInput {\n stream: 'out' | 'err';\n text: string;\n}\n/**\n * `start`: when the process started (pm2's stamp format); lines before it belong to an earlier run in the same file.\n * `coversStart`: the lines read begin at or before that start, so their first burst may be the boot.\n */\nexport interface DetectOptions {\n app: string;\n start: string | null;\n coversStart: boolean;\n}\n\ntype Kind = Pick<ReloadMarker, 'id' | 'kind'>;\nconst CUSTOM: Kind = { id: 'custom', kind: 'rebuild' };\ntype Stream = ReloadInput['stream'];\n/** Each stream's last stamp as pm2 wrote it (whole seconds or milliseconds), which its unstamped lines inherit. */\ntype LastStamp = Record<Stream, string | null>;\ninterface Hit {\n time: string | null;\n ms: number | null;\n plain: string;\n marker: Kind;\n}\ninterface Burst {\n first: Hit; // the oldest marker, which the join rule measures from\n shown: Hit; // the marker the reload is reported by\n lastTime: string | null;\n lastMs: number | null;\n lines: number;\n relistenOnly: boolean;\n}\ninterface Timed {\n time: string | null;\n ms: number | null;\n plain: string;\n stream: Stream;\n i: number;\n}\n\n/**\n * Whether a stamp is before the start. A stamp in whole seconds (a log written before millisecond stamps were set up)\n * is compared with the start's second: read as `.000`, the boot line logged in the start's own second would fall\n * before a start such as `…:05.700` and the next re-listen would be taken for the boot.\n */\nexport const beforeStart = (stamp: string, start: string): boolean =>\n stamp < (stamp.length > 19 ? start : start.slice(0, 19));\n\n/**\n * A log read from its first byte began with this run when its first stamped line comes this soon after the start (a\n * slow boot included); a log cleared during the run (flush, monit's c) also begins at byte 0, with lines from long after.\n */\nexport const FRESH_LOG_MS = 60_000;\n\n/**\n * How far one stream's lines reach back toward the start. `start`: they hold a line of an earlier run (stamped before\n * the start), or the read began at the file's first byte (or where it began is not known: a follower's history) and\n * its first stamped line comes soon after the start. `nothing`: no line at all, so this run left nothing there to\n * count. `after`: the read is the last part of a longer log, the log was cleared during the run, or its lines carry no\n * stamp and cannot be placed.\n */\nexport type Reach = 'start' | 'nothing' | 'after';\n\nconst wallMs = (stamp: string): number => Date.parse(`${msStamp(stamp)}Z`);\n\n/** `fromFirstByte`: whether the read began at the file's first byte; undefined when the reader cannot tell. */\nexport function reach(\n lines: string[],\n started: string,\n fromFirstByte?: boolean\n): Reach {\n const stamps = lines.map(stampOf).filter((t): t is string => t !== null);\n if (stamps.some((t) => beforeStart(t, started))) return 'start';\n if (fromFirstByte === false) return 'after';\n if (lines.length === 0) return 'nothing';\n if (stamps.length === 0) return 'after';\n return wallMs(stamps[0]) - wallMs(started) <= FRESH_LOG_MS\n ? 'start'\n : 'after';\n}\n\n/** When a reload happened, as its shown line's stamp was written (seconds or milliseconds), else the burst's time. */\nexport const reloadStamp = (r: Reload): string | null =>\n stampOf(r.line) ?? r.time;\n\n/** An app's reloads since its process start: how many, the last one's stamp, and whether the count is only a lower bound. */\nexport interface ReloadCount {\n count: number;\n last: string | null;\n partial: boolean;\n}\n\n/**\n * The count ls and monit report for lines read back toward a process start, from how far each stream's lines reach:\n * the first `listening`-only burst may be the boot when one stream reaches the start, and the count is partial (a\n * lower bound) when one does not. `detect` finds the reloads, told whether the lines cover the start.\n */\nexport function reloadCount(\n reaches: Reach[],\n detect: (coversStart: boolean) => Reload[]\n): ReloadCount {\n const found = detect(reaches.includes('start'));\n const last = found.at(-1);\n return {\n count: found.length,\n last: last ? reloadStamp(last) : null,\n partial: reaches.includes('after'),\n };\n}\n\n/** How far a log follower's lines reach, stream by stream: a follower does not say where in the file its history began. */\nexport const historyReaches = (\n input: ReloadInput[],\n started: string\n): Reach[] =>\n (['out', 'err'] as const).map((s) =>\n reach(\n input.filter((l) => l.stream === s).map((l) => l.text),\n started\n )\n );\n\n/**\n * The reloads in a history read once (monit --once): null when the app turned them off or its start is not known. An\n * app's own patterns that run longer than `budgetMs` (default MATCH_BUDGET_MS) throw TIMEOUT.\n */\nexport function historyReloads(\n input: ReloadInput[],\n settings: ReloadSettings | null,\n run: { app: string; started: string | null },\n budgetMs?: number\n): ReloadCount | null {\n const start = run.started;\n if (!settings || start === null) return null;\n const rules = compileReloadRules(settings, budgetMs);\n return reloadCount(historyReaches(input, start), (coversStart) =>\n detectReloads(input, rules, { app: run.app, start, coversStart })\n );\n}\n\n/**\n * Each line's time: its stamp in milliseconds, or the previous stamp of its own stream (`last` carries it across\n * calls). With a start, lines before it and lines that cannot be placed are dropped. The rest are ordered by time,\n * out before err on equal time, file order within a stream; untimed lines go first. Times are host-local wall clock,\n * parsed as UTC only to subtract them.\n */\nfunction timed(\n input: ReloadInput[],\n start: string | null,\n last: LastStamp\n): Timed[] {\n const lines: Timed[] = [];\n input.forEach((l, i) => {\n const plain = stripAnsi(l.text);\n const own = stampOf(plain);\n if (own !== null) last[l.stream] = own;\n const stamp = own ?? last[l.stream];\n if (start !== null && (stamp === null || beforeStart(stamp, start))) return;\n const time = stamp === null ? null : msStamp(stamp);\n const ms = time === null ? null : Date.parse(`${time}Z`);\n lines.push({ time, ms, plain, stream: l.stream, i });\n });\n const rank = (s: Stream) => (s === 'out' ? 0 : 1);\n return lines.sort((a, b) =>\n a.ms !== b.ms\n ? a.ms === null\n ? -1\n : b.ms === null\n ? 1\n : a.ms - b.ms\n : rank(a.stream) - rank(b.stream) || a.i - b.i\n );\n}\n\n/** Per body: the app's own ignore drops it, its own match makes it a reload, else the first built-in marker that tests true. */\nfunction classify(\n bodies: string[],\n rules: ReloadRules,\n app: string\n): (Kind | null)[] {\n const own = runOwnPatterns(\n bodies,\n rules.match,\n rules.ignore,\n rules.budgetMs,\n () =>\n new McprocError(\n 'TIMEOUT',\n `the reloads patterns of ${app} ran over ${rules.budgetMs} ms on its log: one of them backtracks without end on these lines`,\n {\n hint: `Simplify apps.${app}.reloads.match/ignore (a repeat inside a repeat, or alternatives that match the same text).`,\n }\n )\n );\n return bodies.map((b, k) =>\n own?.[k] === 2\n ? null\n : own?.[k] === 1\n ? CUSTOM\n : (rules.markers.find((m) => m.re.test(b)) ?? null)\n );\n}\n\n/** The marker lines among the input, in time order. Bodies are matched as far as an incident line shows them, so a huge line stays cheap. */\nfunction hits(\n input: ReloadInput[],\n rules: ReloadRules,\n opts: DetectOptions,\n last: LastStamp\n): Hit[] {\n const lines = timed(input, opts.start, last);\n const kinds = classify(\n lines.map((l) => searched(l.plain)),\n rules,\n opts.app\n );\n const out: Hit[] = [];\n lines.forEach((l, k) => {\n const marker = kinds[k];\n if (marker) out.push({ time: l.time, ms: l.ms, plain: l.plain, marker });\n });\n return out;\n}\n\n/**\n * A marker joins the open burst when it comes less than RELOAD_GAP_MS after the burst's last one and less than that\n * before its first one: a line flushed late from inside the burst's span still joins, while a marker pushed later\n * with a much older stamp starts a burst of its own. An untimed marker always joins; a timed one never joins an\n * untimed burst, whose age is unknown, so a burst with a last time was opened by a timed marker and its first has one.\n */\nconst joins = (b: Burst, h: Hit): boolean =>\n h.ms === null ||\n (b.lastMs !== null &&\n h.ms - b.lastMs < RELOAD_GAP_MS &&\n b.first.ms! - h.ms < RELOAD_GAP_MS);\nconst opened = (h: Hit): Burst => ({\n first: h,\n shown: h,\n lastTime: h.time,\n lastMs: h.ms,\n lines: 1,\n relistenOnly: h.marker.kind === 'relisten',\n});\nconst older = (h: Hit, than: Hit): boolean =>\n h.ms !== null && than.ms !== null && h.ms < than.ms;\n/**\n * Whether a marker is shown in place of the one shown so far: a restart or rebuild beats a re-listen (the re-listen is\n * the boot or the restart's own new `listening`), and between two of the same class the older one wins.\n */\nconst shownOver = (h: Hit, shown: Hit): boolean => {\n const relisten = h.marker.kind === 'relisten';\n if (relisten !== (shown.marker.kind === 'relisten')) return !relisten;\n return older(h, shown);\n};\n/** A marker older than the burst's first line (pushed in a later call) becomes its first, as it would in one call. */\nfunction add(b: Burst, h: Hit): void {\n b.lines++;\n b.relistenOnly &&= h.marker.kind === 'relisten';\n if (older(h, b.first)) b.first = h;\n if (shownOver(h, b.shown)) b.shown = h;\n if (h.ms !== null && (b.lastMs === null || h.ms >= b.lastMs)) {\n b.lastMs = h.ms;\n b.lastTime = h.time;\n }\n}\nconst reloadOf = (b: Burst): Reload => ({\n time: b.shown.time,\n last_time: b.lastTime,\n lines: b.lines,\n line: cut(b.shown.plain),\n marker: b.shown.marker.id,\n});\n\n/**\n * Reloads as lines arrive (a follower's pushes). A burst is reported once it is closed: by a marker RELOAD_GAP_MS or\n * more after its last line, by one RELOAD_GAP_MS or more older than its first line, or by `idle` once no marker has\n * ARRIVED for that long. Arrival is wall time, not the stamps: a quiet log has no later stamp to compare with.\n */\nexport class ReloadTracker {\n private last: LastStamp = { out: null, err: null };\n private open: Burst | null = null;\n private openWall = 0; // when the open burst's last marker arrived\n private bootPending: boolean; // the first burst to close may still be the boot\n\n constructor(\n private readonly rules: ReloadRules,\n private readonly opts: DetectOptions\n ) {\n this.bootPending = opts.coversStart;\n }\n\n /**\n * The reloads these lines completed. One call carries every stream's new lines, as the log follower delivers them:\n * lines are put in time order within a call only, so a stream held back for a later call would bring older stamps,\n * and a marker RELOAD_GAP_MS or more older than the open burst's first line closes it rather than joining it. A call\n * that throws (TIMEOUT on the app's own patterns) leaves the tracker as it was.\n */\n push(input: ReloadInput[], nowMs: number): Reload[] {\n // the streams' stamps advance on a copy, kept only once classification succeeded\n const last = { ...this.last };\n const found = hits(input, this.rules, this.opts, last);\n this.last = last;\n const done: Reload[] = [];\n for (const h of found) {\n if (this.open && joins(this.open, h)) add(this.open, h);\n else {\n this.close(done);\n this.open = opened(h);\n }\n this.openWall = nowMs;\n }\n return done;\n }\n\n /** Closes the open burst when no marker arrived for RELOAD_GAP_MS of wall time. */\n idle(nowMs: number): Reload[] {\n const done: Reload[] = [];\n if (this.open && nowMs - this.openWall >= RELOAD_GAP_MS) this.close(done);\n return done;\n }\n\n /** When `idle` will close the open burst if no marker arrives before then (wall ms); null with no burst open. */\n idleAt(): number | null {\n return this.open ? this.openWall + RELOAD_GAP_MS : null;\n }\n\n /**\n * The open burst as the reload it makes once closed, without closing it: null with no burst open, or when it would\n * be dropped as the boot.\n */\n pending(): Reload | null {\n const b = this.open;\n return b && !(this.bootPending && b.relistenOnly) ? reloadOf(b) : null;\n }\n\n /** Whether the next burst to close is still taken for the boot when it is only `listening` lines: none has closed yet. */\n get awaitingBoot(): boolean {\n return this.bootPending;\n }\n\n /** Closes the open burst unconditionally. */\n flush(): Reload[] {\n const done: Reload[] = [];\n this.close(done);\n return done;\n }\n\n /** The first burst after the start, when it is only `listening` lines, is the app booting, not a reload. */\n private close(done: Reload[]): void {\n const b = this.open;\n if (!b) return;\n this.open = null;\n const boot = this.bootPending && b.relistenOnly;\n this.bootPending = false;\n if (!boot) done.push(reloadOf(b));\n }\n}\n\n/** The reloads in lines already read: the tracker's rules applied to them at once, the last burst closed at the end. */\nexport function detectReloads(\n input: ReloadInput[],\n rules: ReloadRules,\n opts: DetectOptions\n): Reload[] {\n const t = new ReloadTracker(rules, opts);\n return [...t.push(input, 0), ...t.flush()];\n}\n","import type { Context } from './resolve.js';\nimport { snapshot as probeSnapshot, type Snapshot } from './list.js';\nimport { findProcess } from './pm2.js';\nimport {\n createFollower,\n sortByStamp,\n type LogLine,\n type StartAt,\n} from './logfollow.js';\nimport { describeError } from './errors.js';\nimport { stripAnsi } from './logs.js';\n\nexport interface StreamLine {\n app: string;\n stream: 'out' | 'err';\n text: string;\n}\n/**\n * The apps of one host: with the host's context, or with the error that kept it from connecting; `connect` lets a\n * follow stream reach the host again later.\n */\nexport interface LogSource {\n host: string;\n apps: string[];\n ctx?: Context;\n error?: unknown;\n connect?: () => Promise<Context>;\n}\nexport interface Follower {\n poll(): Promise<{ lines: LogLine[]; reset: boolean }>;\n /** calls `wake` as soon as the followed files change, when the follower can tell */\n watch?(wake: () => void): void;\n /** stops the wakes */\n close?(): void;\n /** continues after the marks of a one-shot read instead of reading history; a stream without one, since the cutoff */\n seek?(at: StartAt): void;\n}\nexport interface StreamDeps {\n snapshot(ctx: Context): Promise<Snapshot>;\n follower(\n ctx: Context,\n paths: { out: string; err: string },\n lines: number\n ): Follower;\n sleep(ms: number): Promise<void>;\n out(line: string): void;\n}\nexport interface StreamOptions {\n lines: number;\n follow: boolean;\n intervalMs: number;\n color: boolean;\n json: boolean;\n stream: 'out' | 'err' | 'both';\n /** while following, re-probe every N ticks for apps that were not started yet */\n resolveEvery?: number;\n signal?: AbortSignal;\n /**\n * per app, where its follower starts: the end of a read printed before the stream, or that read's cutoff for a stream\n * it left without a mark (applied when the follower is created, also for an app found on a later re-probe)\n */\n startAt?: Record<string, StartAt>;\n}\n\n/** polls a wake asks for run at most this often: a chatty app is printed in steps, not on every write */\nconst WAKE_GAP_MS = 50;\n\n/**\n * What a follow loop waits for: its followers' wakes, its clock and the abort. A signal that comes while nobody waits\n * is kept for the next wait. Each wait is one promise settled once, so nothing piles up however long the loop runs.\n */\nfunction signals() {\n const got = { wake: false, clock: false, abort: false };\n let resume: (() => void) | null = null;\n return {\n fire: (k: keyof typeof got) => {\n got[k] = true;\n const r = resume;\n resume = null;\n r?.();\n },\n next: async () => {\n if (!got.wake && !got.clock && !got.abort)\n await new Promise<void>((r) => {\n resume = r;\n });\n const now = { ...got };\n got.wake = false;\n got.clock = false;\n return now;\n },\n };\n}\n\nconst PALETTE = [36, 32, 33, 35, 34, 31]; // cyan, green, yellow, magenta, blue, red — one per app, like compose\nexport const colorFor = (index: number): number =>\n PALETTE[index % PALETTE.length];\n\n/**\n * `app | text` for stdout, `app ! text` for stderr. With colors (a color for the label) the app's own colors stay,\n * closed by a reset so they never run into the next line; without, they are removed.\n */\nexport function formatLine(\n l: StreamLine,\n width: number,\n color: number | null\n): string {\n const label = l.app.padEnd(width);\n const text =\n color === null\n ? stripAnsi(l.text)\n : l.text.includes('\\x1b[')\n ? `${l.text}\\x1b[0m`\n : l.text;\n return `${color === null ? label : `\\x1b[${color}m${label}\\x1b[0m`} ${l.stream === 'err' ? '!' : '|'} ${text}`;\n}\n\n/** --no-color / --color win, then NO_COLOR, then FORCE_COLOR (0 or false = off), else colors only on a terminal. */\nexport function resolveColor(\n flag: boolean | undefined,\n env: NodeJS.ProcessEnv,\n isTTY: boolean\n): boolean {\n if (flag !== undefined) return flag;\n if (env.NO_COLOR) return false;\n if (env.FORCE_COLOR !== undefined && env.FORCE_COLOR !== '')\n return env.FORCE_COLOR !== '0' && env.FORCE_COLOR !== 'false';\n return isTTY;\n}\n\nexport function defaultStreamDeps(): StreamDeps {\n return {\n snapshot: (ctx) => probeSnapshot(ctx, { cpu: 'none', urls: 'none' }),\n follower: createFollower,\n sleep: (ms) => new Promise((r) => setTimeout(r, ms)),\n out: (s) => {\n process.stdout.write(`${s}\\n`);\n },\n };\n}\n\n/**\n * Merged logs of several apps, possibly on several hosts, compose style: history first (app order), then, while\n * following, one loop per host polling its apps when their followers wake (their files changed) and every interval —\n * a slow or silent host never holds the others back.\n * A host that does not answer gets one note line per app per outage and is tried again: its followers resume at the\n * byte offset they had, a host that was down at the start is connected on the re-probe ticks. If no host answers at\n * the start, the first error is thrown instead.\n */\nexport async function streamLogs(\n sources: LogSource[],\n opts: StreamOptions,\n deps: StreamDeps\n): Promise<void> {\n const apps = sources.flatMap((s) => s.apps);\n const width = Math.max(...apps.map((a) => a.length));\n const colors = new Map(\n apps.map((a, i) => [a, opts.color ? colorFor(i) : null])\n );\n let closed = false; // the reader went away (`| head`): stop quietly, no stack trace\n const emit = (l: StreamLine) => {\n if (closed || (opts.stream !== 'both' && l.stream !== opts.stream)) return;\n try {\n deps.out(\n opts.json\n ? JSON.stringify({ ...l, text: stripAnsi(l.text) })\n : formatLine(l, width, colors.get(l.app) ?? null)\n );\n } catch (e) {\n if ((e as { code?: string }).code === 'EPIPE') closed = true;\n else throw e;\n }\n };\n const followers = new Map<string, Follower>();\n const down = new Map<LogSource, string>(); // hosts in an outage that was already announced\n const announce = (s: LogSource, e: unknown) => {\n if (down.has(s)) return;\n down.set(s, describeError(e));\n for (const app of s.apps)\n emit({\n app,\n stream: 'out',\n text: `(host ${s.host} unreachable: ${describeError(e)})`,\n });\n };\n /** connect when needed, probe once, and follow every app of the source that runs */\n const attach = async (s: LogSource, reconnect: boolean) => {\n if (!s.ctx) {\n if (!reconnect || !s.connect)\n throw s.error ?? new Error(`host ${s.host} is not connected`);\n s.ctx = await s.connect();\n }\n if (s.apps.every((a) => followers.has(a))) return;\n const snap: Snapshot = await deps.snapshot(s.ctx);\n for (const app of s.apps) {\n const p = followers.has(app)\n ? undefined\n : findProcess(snap.procs, s.ctx.manifest.project, app);\n if (p) {\n const f = deps.follower(\n s.ctx,\n { out: p.out_log, err: p.err_log },\n opts.lines\n );\n const at = opts.startAt?.[app];\n if (at) f.seek?.(at);\n followers.set(app, f);\n }\n }\n };\n /** one poll of the source's apps in app order; on the first pass an app that does not run says so */\n const poll = async (s: LogSource, first: boolean) => {\n for (const app of s.apps) {\n if (closed) return;\n const f = followers.get(app);\n if (!f) {\n if (first) emit({ app, stream: 'out', text: '(not started)' });\n continue;\n }\n const got = (await f.poll()).lines;\n // pm2 stamps every line (`time: true`); merge an app's out and err by that stamp instead of printing two blocks\n for (const l of opts.stream === 'both' ? sortByStamp(got) : got)\n emit({ app, stream: l.stream, text: l.text });\n }\n };\n\n // history: every host probed at once, then printed in app order\n const failures = await Promise.all(\n sources.map((s) =>\n attach(s, false).then(\n () => null,\n (e: unknown) => ({ e })\n )\n )\n );\n if (sources.length > 0 && failures.every((f) => f !== null))\n throw failures[0]!.e;\n for (const [i, s] of sources.entries()) {\n const failed = failures[i];\n if (failed) {\n announce(s, failed.e);\n continue;\n }\n try {\n await poll(s, true);\n } catch (e) {\n announce(s, e);\n }\n if (closed) return;\n }\n if (!opts.follow || closed) return;\n const every = opts.resolveEvery ?? 10;\n const watched = new Set<Follower>();\n try {\n await Promise.all(\n sources.map(async (s) => {\n const sig = signals();\n const onAbort = () => sig.fire('abort');\n opts.signal?.addEventListener('abort', onAbort, { once: true });\n const watch = () => {\n for (const app of s.apps) {\n const f = followers.get(app);\n if (!f || watched.has(f)) continue;\n watched.add(f);\n f.watch?.(() => sig.fire('wake'));\n }\n };\n watch();\n // the interval is a clock of its own: wakes in between never push it back\n let ticking = false;\n let last = 0;\n try {\n for (let tick = 0; !opts.signal?.aborted && !closed; ) {\n if (!ticking) {\n ticking = true;\n void deps.sleep(opts.intervalMs).then(() => {\n ticking = false;\n sig.fire('clock');\n });\n }\n const why = await sig.next();\n if (why.abort || opts.signal?.aborted || closed) break;\n if (why.clock) tick++;\n else {\n const left = last + WAKE_GAP_MS - Date.now();\n if (left > 0) await new Promise((r) => setTimeout(r, left));\n }\n last = Date.now();\n try {\n // apps that were not running (or a host that was not reached) are looked for again every `every` ticks\n if (\n why.clock &&\n (!s.ctx || s.apps.some((a) => !followers.has(a))) &&\n tick % every === 0\n ) {\n await attach(s, true);\n watch();\n }\n await poll(s, false);\n down.delete(s);\n } catch (e) {\n announce(s, e);\n }\n }\n } finally {\n opts.signal?.removeEventListener('abort', onAbort);\n }\n })\n );\n } finally {\n for (const f of watched) f.close?.();\n }\n}\n","import type { LsRow, HostInfo } from '../core/list.js';\nimport type { HostError } from '../core/fleet.js';\nimport type { DoctorReport, DoctorUrl } from '../core/doctor.js';\nimport type { AppPorts, Listener } from '../core/ports.js';\nimport type { LogsResult } from '../core/logs.js';\nimport type { UnpackResult } from '../runtime/unpack.js';\nimport type { Cleared, TakenAnswer } from '../core/incidents/store.js';\nimport type { WaitRecord } from '../core/actions.js';\nimport type { WaitResult } from '../core/wait.js';\nimport type { SinceAnswer } from '../core/logsince.js';\nimport type { AdoptResult } from '../core/adopt.js';\nimport type { VarInfo } from '../core/manifest.js';\nimport type { LeasesView } from '../core/leases/view.js';\nimport type { ExecResult } from '../core/exec.js';\nimport type {\n WorktreeAdded,\n WorktreeRemoved,\n WorktreeRow,\n} from '../core/worktree.js';\nimport { fmtMib } from '../core/sizes.js';\nimport {\n type HostEnv,\n reasonWord,\n withoutItselfNote,\n} from '../core/urlcheck.js';\nimport { formatLine } from '../core/logstream.js';\nimport { bodyOf, type Incident } from '../core/incidents/detect.js';\nimport { shq } from '../transport/quote.js';\n\nexport function fmtUptime(ms: number | null): string {\n if (ms === null) return '-';\n const s = Math.floor(ms / 1000);\n if (s < 60) return `${s}s`;\n const m = Math.floor(s / 60);\n if (m < 60) return `${m}m`;\n const h = Math.floor(m / 60);\n if (h < 48) return `${h}h${m % 60}m`;\n return `${Math.floor(h / 24)}d`;\n}\nexport function fmtBytes(b: number): string {\n if (b < 1024) return `${b}B`;\n if (b < 1024 ** 2) return `${(b / 1024).toFixed(0)}K`;\n if (b < 1024 ** 3) return `${(b / 1024 ** 2).toFixed(1)}M`;\n return `${(b / 1024 ** 3).toFixed(2)}G`;\n}\nexport function fmtPorts(p: AppPorts): string {\n const parts: string[] = [];\n for (const c of p.checks) {\n if (c.status === 'listening') parts.push(`:${c.port} ✓`);\n else if (c.held_by) {\n const who = c.held_by.app\n ? `app ${c.held_by.app}`\n : c.held_by.container\n ? `container ${c.held_by.container}`\n : c.held_by.pid !== null\n ? `pid ${c.held_by.pid}${c.held_by.command ? ` (${c.held_by.command})` : ''}`\n : \"another user's process\";\n parts.push(`:${c.port} ✗ held by ${who}`);\n } else parts.push(`:${c.port} ✗ nothing listens`);\n }\n for (const u of p.undeclared) parts.push(`:${u} (undeclared)`);\n return parts.length ? parts.join(', ') : '-';\n}\nexport function table(rows: string[][]): string {\n const w = rows[0].map((_, i) =>\n Math.max(...rows.map((r) => (r[i] ?? '').length))\n );\n return rows\n .map((r) =>\n r\n .map((c, i) => (c ?? '').padEnd(w[i]))\n .join(' ')\n .trimEnd()\n )\n .join('\\n');\n}\nexport function fmtCpu(c: number | null): string {\n return c === null ? '-' : `${c.toFixed(1)}%`;\n}\nexport function cut(s: string, n: number): string {\n return s.length > n ? `${s.slice(0, n - 1)}…` : s;\n}\n/**\n * The declared url with its HTTP answer when one was requested, `(here)` when that answer came from this machine, and\n * the short reason of a url that answered nowhere; the bare url when not requested (monit's live screen never asks).\n */\nexport function fmtUrl(r: LsRow): string {\n // a queued app without a url: the column says what its lease waits for\n if (!r.url) return r.lease?.waiting_for ?? '-';\n const here = r.url_from === 'here' ? ' (here)' : '';\n if (r.url_status === 'ok') return `${r.url} ✓ ${r.url_code}${here}`;\n if (r.url_status === 'error')\n return `${r.url} ✗ ${r.url_code ?? 'error'}${here}`;\n if (r.url_status === 'down')\n return `${r.url} ✗ down${r.url_reason ? ` (${reasonWord(r.url_reason)})` : ''}`;\n return r.url;\n}\n/** describe's line for the url when the table cell does not say it all: where it answered and why, or why it did not. */\nexport function urlNote(r: LsRow): string {\n if (!r.url || !r.url_reason) return '';\n if (r.url_status === 'ok' || r.url_status === 'error')\n return `url: answered ${r.url_from === 'here' ? 'from this machine' : `on ${r.host}`} (${r.url_reason})`;\n return `url: ${r.url_status} (${r.url_reason})`;\n}\n/** pm2's restarts, then the in-process reloads counted since the start when there are any: `0 (+3)`, `0 (+≥3)` when partial. */\nfunction fmtRestarts(r: LsRow): string {\n const n = r.reloads;\n return n && n.count > 0\n ? `${r.restarts} (+${n.partial ? '≥' : ''}${n.count})`\n : String(r.restarts);\n}\n/**\n * One table; a HOST column and the list of hosts only when the rows span more than one, then one line per host that did\n * not answer, then one per error of a later read of a host that did (`errors`, the reload count's).\n */\nexport function renderLs(\n rows: LsRow[],\n host: string,\n errors: HostError[] = []\n): string {\n const hosts = [...new Set(rows.map((r) => r.host))];\n const multi = hosts.length > 1;\n const head = multi\n ? `hosts: ${hosts.join(', ')}`\n : `host: ${hosts[0] ?? host}`;\n const unreachable = [\n ...new Map(\n rows.filter((r) => r.error).map((r) => [r.host, `${r.host}: ${r.error}`])\n ).values(),\n ];\n return [\n head,\n table([\n [\n 'APP',\n ...(multi ? ['HOST'] : []),\n 'KIND',\n 'STATUS',\n 'PID',\n 'UPTIME',\n 'RESTARTS',\n 'MEM',\n 'CPU',\n 'PORTS',\n 'URL',\n 'RUNTIME',\n 'DESCRIPTION',\n ],\n ...rows.map((r) => [\n r.app,\n ...(multi ? [r.host] : []),\n r.kind,\n r.status,\n r.pid === null ? '-' : String(r.pid),\n fmtUptime(r.uptime_ms),\n fmtRestarts(r),\n r.memory ? fmtBytes(r.memory) : '-',\n r.status === 'online' ? fmtCpu(r.cpu) : '-',\n fmtPorts(r.ports),\n fmtUrl(r),\n r.runtime ? cut(r.runtime, 32) : '-',\n cut(r.description.split('\\n')[0], 40),\n ]),\n ]),\n ...unreachable,\n ...errors.map((e) => `${e.host}: ${e.message}`),\n ].join('\\n');\n}\n/** `host` when the rows come from one host (the shape results had before apps could run on several), `hosts` always. */\nexport function hostsOf(\n rows: LsRow[],\n fallback: string\n): { host?: string; hosts: string[] } {\n const hosts = rows.length\n ? [...new Set(rows.map((r) => r.host))]\n : [fallback];\n return hosts.length === 1 ? { host: hosts[0], hosts } : { hosts };\n}\n/** A port sampled right after start may simply not be bound yet; say so instead of letting \"✗\" read as a failure. */\nexport function startNote(rows: LsRow[]): string {\n const booting = rows.filter(\n (r) =>\n r.status === 'online' &&\n r.ports.checks.some(\n (c) => c.status === 'declared-not-listening' && !c.held_by\n )\n );\n return booting.length\n ? `note: ${booting.map((r) => r.app).join(', ')} not listening yet; ports are sampled right after start, call wait until listening instead of polling ls`\n : '';\n}\n\nexport function renderPorts(\n rep: {\n port: number | null;\n listeners: Array<Listener & { app: string | null }>;\n },\n host: string\n): string {\n if (rep.listeners.length === 0)\n return `host: ${host}\\n${rep.port ? `nothing listens on port ${rep.port}` : 'no listening sockets visible'}`;\n return (\n `host: ${host}\\n` +\n table([\n ['PROTO', 'ADDR', 'PORT', 'PID', 'COMMAND', 'APP', 'CONTAINER'],\n ...rep.listeners.map((l) => [\n l.proto,\n l.addr,\n String(l.port),\n l.pid === null ? '?' : String(l.pid),\n l.command ?? '?',\n l.app ?? '-',\n l.container ?? '-',\n ]),\n ])\n );\n}\nexport function renderHosts(info: HostInfo[]): string {\n return table([\n ['HOST', 'TRANSPORT', 'CWD', 'READONLY', 'PM2_HOME', 'APPS'],\n ...info.map((h) => [\n h.name,\n h.transport,\n h.cwd,\n h.readonly ? 'yes' : 'no',\n h.pm2_home ?? '-',\n h.apps.length ? h.apps.join(', ') : '-',\n ]),\n ]);\n}\n/** `container (docker), hostname ws-01`, or `no container, hostname dev-box` */\nexport function fmtEnv(e: HostEnv): string {\n const kind =\n e.container === 'none' ? 'no container' : `container (${e.container})`;\n return e.hostname ? `${kind}, hostname ${e.hostname}` : kind;\n}\n/**\n * `localhost → ::1 on box; answers from this machine (200); on box: refused`: after an answer from here, why the host\n * had none, unless that reason is the host itself, which the first part already says; for the same reason a url that\n * answers nowhere drops the address note from its reason.\n */\nfunction fmtDoctorUrl(host: string, u: DoctorUrl): string {\n const name = u.name ?? u.url;\n const where = `${name} → ${u.addr ?? 'no address'} on ${host}${u.itself ? ', the host itself' : ''}`;\n const c = u.check;\n const code = c.code ?? 'error';\n const why =\n c.reason && !(u.itself && reasonWord(c.reason) === 'itself')\n ? `; ${c.reason}`\n : '';\n const answers =\n c.status === 'unchecked'\n ? `not checked (${c.reason ?? 'not asked'})`\n : c.status === 'down'\n ? `answers nowhere (${u.itself && c.reason ? withoutItselfNote(c.reason) : c.reason})`\n : c.from === 'here'\n ? `answers from this machine (${code})${why}`\n : `answers on ${host} (${code})`;\n return `${where}; ${answers}`;\n}\n/** Each host's report: whether it answers, its Node, pm2 and runtime, on this machine its memory and lease state, its urls and the fixes. */\nexport function renderDoctor(reps: DoctorReport[]): string {\n return reps\n .map((r) => {\n const L = [\n `${r.host} (${r.transport}): ${r.reachable ? 'reachable' : `UNREACHABLE: ${r.error}`}`,\n ];\n if (r.reachable) {\n L.push(\n ` node: ${r.node ?? 'missing'} tools: ps=${r.tools.ps} ss=${r.tools.ss} tar=${r.tools.tar}`\n );\n L.push(\n ` pm2: ${r.pm2 ? `${r.pm2.source} (${r.pm2.reason})${r.pm2.version ? ` ${r.pm2.version}` : ''}` : 'none'} daemon: ${r.daemon}, ${r.processes} processes, ${r.in_namespace} in this project`\n );\n L.push(\n ` PM2_HOME: ${r.pm2_home ?? 'default (~/.pm2)'} runtime: ${r.runtime_present ? `${r.runtime_dir} (pm2 ${r.runtime_pm2 ?? '?'}${r.runtime_node ? `, node ${r.runtime_node}` : ''})` : 'not unpacked'}`\n );\n if (r.runtime_present)\n L.push(\n ` watch from a shell there: ${r.pm2_home ? `PM2_HOME=${shq(r.pm2_home)} ` : ''}${shq(`${r.runtime_dir}/bin/pm2`)} monit`\n );\n if (r.memory)\n L.push(\n ` memory: ${fmtMib(r.memory.available_mib)} available of ${fmtMib(r.memory.total_mib)}`\n );\n if (r.state_dir)\n L.push(\n ` leases: ${r.state_dir}, watcher ${r.watcher ? (r.watcher.online ? `online pid ${r.watcher.pid}` : 'not running') : 'unknown'}`\n );\n if (r.environment) L.push(` environment: ${fmtEnv(r.environment)}`);\n for (const u of r.urls)\n L.push(` url ${u.app}: ${fmtDoctorUrl(r.host, u)}`);\n }\n for (const rec of r.recommendations) L.push(` → ${rec}`);\n return L.join('\\n');\n })\n .join('\\n');\n}\nexport function renderUnpack(r: UnpackResult): string {\n const L = [\n `${r.host}: runtime at ${r.runtime_dir}${r.noop ? ', already up to date' : ''}`,\n ];\n L.push(` pm2 ${r.pm2.version} ${r.pm2.written ? 'unpacked' : 'kept'}`);\n if (r.node)\n L.push(\n ` node ${r.node.version} (${r.node.platform}) ${r.node.written ? 'unpacked' : 'kept'}`\n );\n L.push(` manifest copy on the host: ${r.manifest_copy}`);\n if (r.runtime_line)\n L.push(\n ` add to .mcproc/mcproc.yaml so later calls find it: ${r.runtime_line}`\n );\n L.push(` watch it from a shell there: ${r.monit}`);\n if (r.update_hint) L.push(` note: ${r.update_hint}`);\n return L.join('\\n');\n}\nexport function renderLogs(l: LogsResult): string {\n const parts: string[] = [];\n if (l.out !== undefined)\n parts.push(`--- ${l.app} out (${l.paths.out}) ---\\n${l.out}`);\n if (l.err !== undefined)\n parts.push(`--- ${l.app} err (${l.paths.err}) ---\\n${l.err}`);\n return parts.join('\\n');\n}\n/** `since <cutoff> (<host> time)`; several hosts list each cutoff; a `last` or tail read has no cutoff. */\nfunction sinceWhen(a: SinceAnswer): string {\n if (a.mode === 'last') return 'since the previous logs call';\n if (a.mode === 'tail') return 'latest lines';\n const hosts = Object.entries(a.since);\n return hosts.length === 1\n ? `since ${hosts[0][1]} (${hosts[0][0]} time)`\n : `since ${hosts.map(([h, c]) => `${h} ${c}`).join(', ')} (each host's time)`;\n}\nconst plural = (n: number, w: string) => `${n} ${w}${n === 1 ? '' : 's'}`;\n/** The notes after the lines: what was cut, what may be missing or misplaced, who was not read; the CLI prints the same on stderr. */\nexport function sinceNotes(a: SinceAnswer): string[] {\n const notes: string[] = [];\n if (a.truncated > 0)\n notes.push(`truncated ${plural(a.truncated, 'older line')}`);\n // a last read jumped over new bytes past its mark; a window read may miss lines between the cutoff and its 1 MB\n const why =\n a.mode === 'last'\n ? 'more than 1 MB new since the previous call; the most recent 1 MB was read'\n : 'more than the 1 MB read before the window';\n for (const s of a.skipped)\n notes.push(\n `skipped ${fmtBytes(s.bytes)} of ${s.app} ${s.stream} on ${s.host} (${why})`\n );\n if (a.not_started.length)\n notes.push(`not started: ${a.not_started.join(', ')}`);\n if (a.unzoned.length)\n notes.push(\n `zone unknown on ${a.unzoned.join(', ')}: ${a.unzoned.length === 1 ? 'its' : 'their'} lines are placed by their stamps as if in UTC, so they may be out of place among the other hosts' lines`\n );\n // unreachable, or it answered without a clock the since needs: either way its apps were not read\n for (const e of a.errors)\n notes.push(`${e.host} not read (${e.apps.join(', ')}): ${e.message}`);\n return notes;\n}\n/** Header, then compose lines (`app | text`, `app ! text` for stderr, no colors), then the notes. */\nexport function renderLogsSince(a: SinceAnswer): string {\n const who = `${plural(a.apps, 'app')} on ${plural(a.hosts, 'host')}`;\n const notes = sinceNotes(a);\n if (a.lines.length === 0) {\n const none =\n a.mode === 'last'\n ? `no new log lines ${sinceWhen(a)}`\n : a.mode === 'tail'\n ? 'no log lines'\n : `no log lines ${sinceWhen(a)}`;\n return [`${none} (${who})`, ...notes].join('\\n');\n }\n const width = Math.max(...a.lines.map((l) => l.app.length));\n return [\n `${sinceWhen(a)} · ${who} · ${plural(a.lines.length, 'line')}`,\n ...a.lines.map((l) =>\n formatLine({ app: l.app, stream: l.stream, text: l.text }, width, null)\n ),\n ...notes,\n ].join('\\n');\n}\nconst secs = (ms: number) => `${(ms / 1000).toFixed(1)} s`;\n/** One line: what was reached (or not) after how long, and what was seen (a start still queued says its place). */\nexport function renderWait(app: string, r: WaitResult): string {\n const seen = r.observed ? ` (${r.observed})` : '';\n if (r.ok) {\n if (r.until === 'exited') {\n // \"failed (exit 2)\" already names its code; a stop has none\n const code =\n typeof r.exit_code === 'number' && !r.status.includes('exit')\n ? ` (exit ${r.exit_code})`\n : '';\n return `${app}: ${r.status} after ${secs(r.waited_ms)}${code}`;\n }\n if (r.until.startsWith('log:'))\n return `${app}: log matched after ${secs(r.waited_ms)}: ${r.matched_line}`;\n if (r.reloaded) {\n // the time is shown once, in its own place: the line follows without pm2's stamp\n const { time, lines, line } = r.reloaded;\n const count = `${lines} line${lines === 1 ? '' : 's'}`;\n return `${app}: reloaded after ${secs(r.waited_ms)} (${time ? `${count} from ${time}` : count}): ${bodyOf(line)}`;\n }\n return `${app}: ${r.until} after ${secs(r.waited_ms)}${seen}`;\n }\n if (r.reason === 'timeout')\n return `${app}: ${r.until} not reached after ${secs(r.waited_ms)}${seen}`;\n if (r.reason === 'aborted')\n return `${app}: aborted after ${secs(r.waited_ms)} while waiting for ${r.until}${seen}`;\n return `${app}: ${r.reason} (${r.status}) after ${secs(r.waited_ms)} while waiting for ${r.until}`;\n}\n/** `libs (completed), api (ready), logger`: a started dependency is its bare name. */\nexport function fmtDeps(deps: { app: string; condition: string }[]): string {\n return deps\n .map((d) =>\n d.condition === 'started' ? d.app : `${d.app} (${d.condition})`\n )\n .join(', ');\n}\n\nexport function renderProject(d: {\n project: string;\n root: string;\n mcproc: { manifest: string | null; running: string };\n vars: VarInfo[];\n override: string | null;\n slot: number | null;\n apps: {\n name: string;\n kind: string;\n description: string;\n ports: number[];\n url: string | null;\n depends_on: { app: string; condition: string }[];\n host: string | null;\n }[];\n profiles: Record<string, string[]>;\n hosts: HostInfo[];\n readme: string | null;\n}): string {\n const L = [`project: ${d.project} (${d.root})`];\n const w = d.mcproc.manifest;\n if (w)\n L.push(\n `manifest: written by mcproc ${w}${w === d.mcproc.running ? '' : `, this is ${d.mcproc.running}`}`\n );\n if (d.vars.some((v) => v.source !== 'built-in') || d.override) {\n L.push(\n `vars:${d.override ? ` (override ${d.override})` : ''}${d.slot !== null ? ` slot ${d.slot}` : ''}`\n );\n for (const v of d.vars)\n L.push(` ${v.name} = ${JSON.stringify(v.value)} (${v.source})`);\n }\n L.push('apps:');\n for (const a of d.apps)\n L.push(\n ` ${a.name} [${a.kind}]${a.host ? ` on ${a.host}` : ''}${a.ports.length ? ` :${a.ports.join(',:')}` : ''}${a.url ? ` → ${a.url}` : ''}${a.depends_on.length ? ` after ${fmtDeps(a.depends_on)}` : ''}: ${a.description}`\n );\n L.push('profiles:');\n for (const [p, apps] of Object.entries(d.profiles))\n L.push(` ${p}: ${apps.join(', ')}`);\n L.push(\n 'hosts:',\n renderHosts(d.hosts)\n .split('\\n')\n .map((x) => ` ${x}`)\n .join('\\n')\n );\n if (d.readme) L.push('', 'README:', d.readme.trim());\n return L.join('\\n');\n}\n\n/**\n * Incidents newest first: a header, context lines `│`, the error line `▶`; an app's reloads are one line with the last\n * reload's line; then how to go on. Nothing new is one short line.\n */\n/**\n * One incident as text: its head (app@host, time, kind, ×count, first time, stream), the lines before it, its own line\n * (red with `color`) and the lines after; a reload is one plain line (both streams, no context, not an error).\n */\nexport function incidentLines(\n i: Incident,\n opts: { color?: boolean } = {}\n): string[] {\n const count = i.count > 1 ? ` ×${i.count}` : '';\n const first =\n i.count > 1 && i.first_time && i.first_time !== i.time\n ? i.first_time\n : null;\n if (i.kind === 'reloaded')\n return [\n `${i.app}@${i.host} ${i.time ?? '-'} reloaded${count}${first ? ` (first ${first})` : ''}: ${i.line}`,\n ];\n const red = (s: string) => (opts.color ? `\\x1b[31m${s}\\x1b[0m` : s);\n return [\n `${i.app}@${i.host} ${i.time ?? '-'} ${i.kind}${count} (${first ? `first ${first}, ` : ''}${i.stream})`,\n ...i.before.map((b) => ` │ ${b}`),\n red(` ▶ ${i.line}`),\n ...i.after.map((x) => ` │ ${x}`),\n ];\n}\n\nexport function renderIncidents(\n a: TakenAnswer,\n opts: { color?: boolean } = {}\n): string {\n const tail: string[] = [];\n if (a.more > 0) {\n const short = a.more_by === 'size' ? ' to keep this answer short' : '';\n tail.push(\n a.taken\n ? `+${a.more} older incidents not shown${short}, taken with these (read logs for them)`\n : short\n ? `+${a.more} more incidents not shown${short} (pass app for one app, or read logs)`\n : `+${a.more} more incidents (raise max)`\n );\n }\n for (const s of a.skipped)\n tail.push(\n `skipped ${fmtBytes(s.bytes)} of ${s.app} ${s.stream} on ${s.host} (too much new log; the most recent 1 MB was read)`\n );\n for (const e of a.errors) tail.push(`${e.host}: ${e.message}`);\n if (a.incidents.length === 0) {\n const cleared = a.cleared_at ? `; logs cleared ${a.cleared_at}` : '';\n return [\n `no new incidents since ${a.latest ?? 'the last call'} (${a.apps} app${a.apps === 1 ? '' : 's'} on ${a.hosts} host${a.hosts === 1 ? '' : 's'}${cleared})`,\n ...tail,\n ].join('\\n');\n }\n const L = a.incidents.flatMap((i) => incidentLines(i, opts));\n L.push(\n ...tail,\n `next: call incidents again later (${a.taken ? 'these are taken now' : 'peeked: nothing taken'}); full logs with logs app=${a.incidents[0].app}`\n );\n return L.join('\\n');\n}\n\n/** What a flush did: one line per app (with its host when several answered), naming the files it could not truncate. */\nexport function renderFlushed(r: Cleared[], multi: boolean): string {\n if (r.length === 0)\n return 'nothing to flush (no pm2 processes for this project there)';\n return r\n .map(\n (x) =>\n `${x.app}${multi ? ` (${x.host})` : ''}: freed ${x.out_bytes + x.err_bytes} bytes${x.failed?.length ? `; could not truncate ${x.failed.join(', ')}` : ''}`\n )\n .join('\\n');\n}\n\n/** `waited 4.2 s for libs (completed), 1.1 s for api (ready)`: the waits that were met; the failed ones are in the rows. */\nexport function waitNote(waits: WaitRecord[]): string {\n const ok = waits.filter((w) => w.ok);\n return ok.length\n ? `waited ${ok.map((w) => `${(w.ms / 1000).toFixed(1)} s for ${w.dep} (${w.condition})`).join(', ')}`\n : '';\n}\n\n/** One line per distinct note the change left on its rows, with the apps it concerns. */\nexport function rowNote(rows: LsRow[]): string {\n const by = new Map<string, string[]>();\n for (const r of rows)\n if (r.note) by.set(r.note, [...(by.get(r.note) ?? []), r.app]);\n return [...by]\n .map(([note, apps]) => `${apps.join(', ')}: ${note}`)\n .join('\\n');\n}\n\n/** One line per queued app of a start: its position and what the head of the queue waits for. */\nexport function queuedNote(rows: LsRow[]): string {\n const by = new Map<string, LsRow[]>();\n for (const r of rows)\n if (r.lease) by.set(r.lease.id, [...(by.get(r.lease.id) ?? []), r]);\n return [...by.values()]\n .map((rs) => {\n const l = rs[0].lease!;\n const apps = rs.map((r) => r.app).join(', ');\n return l.state === 'starting'\n ? `${apps}: starting (lease ${l.id})`\n : `${apps}: queued #${l.position}${l.waiting_for ? `: ${l.waiting_for}` : ''} (lease ${l.id}; wait on an app, or leases)`;\n })\n .join('\\n');\n}\n\n/** The queue as a table, oldest first, with the host's memory and the watcher's state above it. */\nexport function renderLeases(v: LeasesView): string {\n const head = [\n `state: ${v.state_dir}`,\n v.memory\n ? `memory: ${fmtMib(v.memory.available_mib)} available of ${fmtMib(v.memory.total_mib)}`\n : 'memory: no reading on this host (leases are admitted in FIFO order without a check)',\n v.watcher\n ? `watcher: ${v.watcher.online ? `online pid ${v.watcher.pid}` : 'not running'}`\n : '',\n ].filter(Boolean);\n if (v.leases.length === 0) return [...head, 'no leases'].join('\\n');\n const rows = v.leases.map((l) => [\n l.position ? `#${l.position}` : '',\n l.state,\n l.kind,\n l.project + (l.slot !== null ? ` (slot ${l.slot})` : ''),\n l.target,\n `${fmtMib(l.estimate_mib)} → ${fmtMib(l.need_mib)}`,\n Object.values(l.sources).some((s) => s.source.startsWith('measured'))\n ? 'measured'\n : 'declared',\n l.waiting_for ?? l.error ?? '',\n l.id,\n ]);\n return [\n ...head,\n table([\n [\n 'POS',\n 'STATE',\n 'KIND',\n 'PROJECT',\n 'TARGET',\n 'EST → NEED',\n 'FROM',\n 'WAITING FOR / ERROR',\n 'ID',\n ],\n ...rows,\n ]),\n ].join('\\n');\n}\n\n/** A fleet mutation's answer: when a host failed or was skipped, a first line that says which apps and why; then the table, the start and queue notes and the waits made. */\nexport function renderMutation(\n rows: LsRow[],\n fallback: string,\n act: string,\n waits: WaitRecord[] = []\n): { text: string; failed: boolean } {\n const bad = rows.filter((r) => r.error);\n const notes = [\n act === 'start' || act === 'restart' ? startNote(rows) : '',\n act === 'start' ? queuedNote(rows) : '',\n waitNote(waits),\n rowNote(rows),\n ].filter(Boolean);\n const head = bad.length\n ? `${act} partly failed: ${bad.map((r) => `${r.app} (${r.host}): ${r.error}`).join('; ')}\\n`\n : '';\n return {\n text: head + renderLs(rows, fallback) + notes.map((n) => `\\n${n}`).join(''),\n failed: bad.length > 0,\n };\n}\n\n/** One line per adopted or skipped app, the hosts not read, then the written file and its diff; `failed` when a host was not read. */\nexport function renderAdopted(r: AdoptResult): {\n text: string;\n failed: boolean;\n} {\n const at = (h: string) => (h === 'local' ? '' : ` (${h})`);\n const lines = [\n ...r.adopted.map(\n (a) => `${a.app}: adopted ${a.ports.join(', ')}${at(a.host)}`\n ),\n ...r.skipped.map(\n (s) =>\n `${s.app}: skipped ${s.ports.join(', ')} (${s.reason})${at(s.host)}`\n ),\n ...r.errors.map(\n (e) => `${e.host} not read (${e.apps.join(', ')}): ${e.message}`\n ),\n ];\n if (r.written) lines.push(`written ${r.path}:`, ...r.diff);\n else if (lines.length === 0)\n lines.push(\n 'nothing to adopt: every port the running apps hold is declared'\n );\n return { text: lines.join('\\n'), failed: r.errors.length > 0 };\n}\n\n/** An exec's answer: the command, how long it waited, its lease, the exit code, then the captured tail. */\nexport function renderExec(command: string[], r: ExecResult): string {\n const head = `exec ${command.join(' ')}: exit ${r.code}${r.waited_ms > 1000 ? ` after ${Math.round(r.waited_ms / 1000)} s in the queue` : ''}${r.lease ? ` (lease ${r.lease.id}, ${r.lease.state})` : ''}`;\n return r.output ? `${head}\\n${r.output}` : head;\n}\n\n/** A new worktree: where, its branch (new or existing), slot and project, what was copied, linked, missing and installed, its vars, then how to go on. */\nexport function renderWorktreeAdded(r: WorktreeAdded): string {\n const L = [\n `worktree ${r.path}`,\n `branch: ${r.branch} (${r.created_branch ? 'new' : 'existing'})`,\n `slot ${r.slot}, project ${r.project}`,\n `decided by: the ${r.manifest === 'worktree' ? \"worktree's own\" : \"main checkout's\"} manifest`,\n ];\n const mark = (e: string) =>\n r.from_override.includes(e) ? `${e} (override)` : e;\n if (r.copied.length) L.push(`copied: ${r.copied.map(mark).join(', ')}`);\n if (r.linked.length) L.push(`linked: ${r.linked.map(mark).join(', ')}`);\n if (r.excluded.length)\n L.push(\n `ignored in git: ${r.excluded.join(', ')} (the repository's info/exclude)`\n );\n if (r.missing.length) L.push(`missing: ${r.missing.join(', ')}`);\n L.push(`installed: ${r.installed ?? 'nothing'}`);\n const vars = r.vars.filter((v) => v.source !== 'built-in');\n if (vars.length) {\n L.push('vars:');\n for (const v of vars) L.push(` ${v.name} = ${JSON.stringify(v.value)}`);\n }\n L.push(`next: ${r.next}`);\n return L.join('\\n');\n}\n\n/** Every checkout of the repository as a table, slot 0 marked as the main one. */\nexport function renderWorktrees(rows: WorktreeRow[]): string {\n return table([\n ['SLOT', 'PROJECT', 'BRANCH', 'ONLINE', 'LEASE', 'PATH'],\n ...rows.map((r) => [\n r.main ? `${r.slot} (main)` : String(r.slot),\n r.project,\n r.branch ?? '(detached)',\n String(r.online),\n r.lease ?? '-',\n r.path,\n ]),\n ]);\n}\n\n/** A removed worktree in one line: its path, the slot it freed, the branch it kept and the apps it stopped. */\nexport function renderWorktreeRemoved(r: WorktreeRemoved): string {\n return `removed ${r.path}: slot ${r.slot} is free, branch ${r.branch ?? '(detached)'} kept; stopped ${r.stopped.length ? r.stopped.join(', ') : 'nothing'}`;\n}\n","import { McprocError } from './errors.js';\nimport { findProcess, isRunning, type Pm2Process } from './pm2.js';\nimport type { Context } from './resolve.js';\nimport {\n snapshot as probeSnapshot,\n statusWord,\n urlCheckOf,\n type Snapshot,\n type SnapshotOptions,\n} from './list.js';\nimport { createFollower, type LogFollower } from './logfollow.js';\nimport { bodyOf, repeatsARepeat } from './incidents/detect.js';\nimport { stripAnsi } from './logs.js';\nimport type { App, Dep } from './manifest.js';\nimport { compileReloadRules, type Reload, ReloadTracker } from './reloads.js';\nimport { fmtPorts } from '../mcp/render.js';\nimport type { UrlResult } from './urlcheck.js';\nimport { leasesCovering, type LeaseView } from './leases/view.js';\nimport { stateDir } from './state.js';\n\nexport type Until =\n | { kind: 'listening' }\n | { kind: 'url-ok' }\n | { kind: 'exited' }\n | { kind: 'log'; re: RegExp; source: string }\n | { kind: 'idle'; seconds: number }\n | { kind: 'reloaded' };\nexport type WaitReason =\n | 'timeout'\n | 'exited'\n | 'crashed'\n | 'failed'\n | 'aborted';\n/** What a wait ended with: ok and the condition met, or not and why; the status word and exit code as of the end. */\nexport interface WaitResult {\n ok: boolean;\n until: string;\n waited_ms: number;\n reason?: WaitReason;\n status: string;\n exit_code?: number | null;\n matched_line?: string;\n observed?: string;\n /** reloaded: the reload that answered; `line` its first restart or rebuild line, else its first line, as written, and `time` that line's stamp */\n reloaded?: { time: string | null; lines: number; line: string };\n}\n/** What a wait reads and how it passes time: pm2's list, the light probe, the log follower, the leases, its sleep and clock. */\nexport interface WaitDeps {\n jlist(ctx: Context): Promise<Pm2Process[]>;\n snapshot(ctx: Context, opts: SnapshotOptions): Promise<Snapshot>;\n follower(\n ctx: Context,\n paths: { out: string; err: string }\n ): Pick<LogFollower, 'poll' | 'watch' | 'close' | 'offsets'>;\n sleep(ms: number, signal?: AbortSignal): Promise<void>;\n now(): number;\n /** this checkout's pending and starting leases: a wait rides through one that covers an app that is not running */\n leases(ctx: Context): Promise<LeaseView[]>;\n}\nexport const WAIT_TIMEOUT_DEFAULT_MS = 60_000;\nexport const WAIT_TIMEOUT_MAX_MS = 600_000;\n/** How often the host is asked: a light probe or jlist, a login shell each time, so not faster than this. */\nconst POLL_LOCAL_MS = 500;\nconst POLL_REMOTE_MS = 1000;\n/** pm2 statuses of a process in the middle of a restart (a watch restart, a restart delay): it is not dead, so a wait goes on. */\nconst TRANSIENT = new Set(['stopping', 'waiting restart']);\n/** Not dead: running, or on its way through a restart. The timeout bounds a restart that does not end. */\nconst notDead = (status: string): boolean =>\n isRunning(status) || TRANSIENT.has(status);\n/** The log:, idle: and reloaded waits look at the follower at least this often (a file wake makes it sooner). */\nconst LOG_TICK_MS = 1000;\n/** ...and ask pm2 about the process this often: each check is a login shell, so not every tick. */\nconst STATUS_EVERY_MS = 5000;\n\nconst bad = (msg: string) =>\n new McprocError('BAD_ARGUMENT', msg, {\n hint: 'until is one of: listening, url-ok, exited, log:<regex>, idle:<seconds>, reloaded',\n });\n\nexport function parseUntil(s: string): Until {\n if (s === 'listening' || s === 'url-ok' || s === 'exited' || s === 'reloaded')\n return { kind: s };\n if (s.startsWith('log:')) {\n const source = s.slice(4);\n if (!source) throw bad('log: needs a regular expression after the colon');\n let re: RegExp;\n try {\n re = new RegExp(source);\n } catch (e) {\n throw bad(\n `log: invalid regular expression \"${source}\": ${(e as Error).message}`\n );\n }\n if (repeatsARepeat(source))\n throw new McprocError(\n 'BAD_ARGUMENT',\n `log: pattern \"${source}\" repeats a group that ends in a repeat (like (a+)+), which can run for minutes on a log line that almost matches`,\n { hint: 'Rewrite it without the nested repeat.' }\n );\n return { kind: 'log', re, source };\n }\n if (s.startsWith('idle:')) {\n const seconds = Number(s.slice(5));\n if (!Number.isFinite(seconds) || !(seconds > 0))\n throw bad(`idle: needs a number of seconds above 0, got \"${s.slice(5)}\"`);\n return { kind: 'idle', seconds };\n }\n throw bad(`unknown until \"${s}\"`);\n}\n\nexport function untilLabel(u: Until): string {\n return u.kind === 'log'\n ? `log:${u.source}`\n : u.kind === 'idle'\n ? `idle:${u.seconds}`\n : u.kind;\n}\n\n/** A sleep of `ms` that the signal ends at once, also when it was aborted before the sleep began. */\nexport function abortableSleep(\n ms: number,\n signal?: AbortSignal\n): Promise<void> {\n return new Promise((resolve) => {\n // an abort that came before the sleep began fires no event: answer at once\n if (signal?.aborted) return resolve();\n const done = () => {\n signal?.removeEventListener('abort', done);\n clearTimeout(timer);\n resolve();\n };\n const timer = setTimeout(done, ms);\n signal?.addEventListener('abort', done, { once: true });\n });\n}\n\n/** The real deps: pm2's list and the light probe over the context's transport, the log follower, the real clock and the state directory's leases. */\nexport function defaultWaitDeps(): WaitDeps {\n return {\n jlist: (ctx) => ctx.pm2.jlist(),\n snapshot: (ctx, opts) => probeSnapshot(ctx, opts),\n // no history: a wait looks only at what is written after it began\n follower: (ctx, paths) => createFollower(ctx, paths, 0),\n sleep: abortableSleep,\n now: () => Date.now(),\n // the queue lives on this machine only: a wait on another host never finds a lease\n leases: async (ctx) =>\n ctx.host.local ? leasesCovering(stateDir(), ctx.manifest) : [],\n };\n}\n\n/** What a url-ok wait saw: `<url> 200`, `<url> 200 from this machine (<why>)`, `<url> down (<why>)`, `<url> unchecked`. */\nfunction urlSeen(url: string, u: UrlResult | undefined): string {\n if (!u || u.status === 'unchecked')\n return `${url} unchecked${u?.reason ? ` (${u.reason})` : ''}`;\n if (u.status === 'down')\n return `${url} down${u.reason ? ` (${u.reason})` : ''}`;\n return `${url} ${u.code ?? 'error'}${u.from === 'here' ? ` from this machine (${u.reason})` : ''}`;\n}\n\nconst unknownApp = (ctx: Context, app: string) =>\n new McprocError(\n 'UNKNOWN_APP',\n `Unknown app \"${app}\" in ${ctx.manifest.path}`\n );\n\nconst notStarted = (ctx: Context, app: string) =>\n new McprocError(\n 'NOT_STARTED',\n `\"${app}\" has no pm2 process on ${ctx.transport.describe()} (never started, or deleted)`,\n { hint: `Run start ${app} first; ls shows the current state.` }\n );\n\ntype Answer = (\n part: Partial<WaitResult> & { ok: boolean; status: string }\n) => WaitResult;\n/** What waitFor hands the log waits: its clock bounds and the ways to end a result. */\ninterface LogRun {\n deps: WaitDeps;\n deadline: number;\n signal?: AbortSignal;\n answer: Answer;\n gone: (p: Pm2Process | undefined, observed?: string) => WaitResult;\n giveUp: (\n reason: 'timeout' | 'aborted',\n p: Pm2Process | undefined,\n observed?: string\n ) => WaitResult;\n /** the app is not running: rides through a covering lease ('again' after a pause), ends at the deadline or on abort, null without a lease */\n queued: () => Promise<WaitResult | 'again' | null>;\n}\n\n/** What a reloaded wait saw when it ends with a burst still open: a reload under way, not the absence of one. */\nconst inProgress = (r: Reload): string =>\n `reload in progress${r.time ? ` since ${r.time}` : ''} (${r.lines} line${r.lines === 1 ? '' : 's'}): ${bodyOf(r.line)}`;\n\n/**\n * log:/idle:/reloaded sit on the log follower, which takes its position at the end of both files: nothing written\n * before that is searched, and a quiet period counts from that moment (or from the last byte since). Lines read in a\n * poll are judged before the process is looked at, so a last line still counts. The process is asked about every few\n * seconds, and once more when the quiet period of idle: ends. reloaded feeds every line to a reload tracker and\n * answers with the first reload it closes: a later marker closes a burst at once, quiet closes it RELOAD_GAP_MS after\n * its last marker arrived, so the tick's sleep is cut to that moment. A re-listen line counts from its first burst:\n * the app's boot was before the call. A wait that times out or is aborted with a burst open says so in `observed`.\n * An app that is not running and that a lease covers is waited for first, as waitFor's other conditions do.\n */\nasync function waitOnLogs(\n ctx: Context,\n app: string,\n a: App,\n until: Extract<Until, { kind: 'log' | 'idle' | 'reloaded' }>,\n run: LogRun\n): Promise<WaitResult> {\n const { deps, signal } = run;\n let p = findProcess(await deps.jlist(ctx), ctx.manifest.project, app);\n // a process seen once makes its absence later a result (gone), never a request for an app that never started\n let seen = p !== undefined;\n // not running (no process yet, or one stopped before a start that queued): while a lease covers the app pm2 is\n // asked again at each poll, and the follower starts once it runs\n while (!p || !isRunning(p.status)) {\n const q = await run.queued();\n if (q === null) break;\n if (q !== 'again') return q;\n p = findProcess(await deps.jlist(ctx), ctx.manifest.project, app);\n if (p) seen = true;\n }\n if (!p) {\n if (!seen) throw notStarted(ctx, app);\n return run.gone(undefined);\n }\n const tracker =\n until.kind === 'reloaded' && a.reloads\n ? new ReloadTracker(compileReloadRules(a.reloads), {\n app,\n start: null,\n coversStart: false,\n })\n : null;\n const f = deps.follower(ctx, { out: p.out_log, err: p.err_log });\n // a file wake, or the signal, ends the sleep of the tick; a wake during a poll skips the next sleep\n let tick: AbortController | null = null;\n let woken = false;\n const wake = () => {\n woken = true;\n tick?.abort();\n };\n const onAbort = () => tick?.abort();\n signal?.addEventListener('abort', onAbort, { once: true });\n try {\n await f.poll(); // takes the position at the end; no history is searched\n f.watch(wake);\n const quietMs = until.kind === 'idle' ? Math.ceil(until.seconds * 1000) : 0;\n let lastCheck = deps.now();\n let lastChange = lastCheck;\n let lastLine: string | undefined;\n let seen = { out: f.offsets.out, err: f.offsets.err };\n /** what the wait ends with when the condition is unmet: the reload under way, else what was last seen */\n const unmet = (observed: string): string => {\n const r = tracker?.pending();\n return r ? inProgress(r) : observed;\n };\n for (;;) {\n const { lines, reset } = await f.poll();\n let now = deps.now();\n // any byte counts as activity, a line still unfinished too, and so does a file replaced by one of the same size\n if (reset || f.offsets.out !== seen.out || f.offsets.err !== seen.err) {\n lastChange = now;\n seen = { out: f.offsets.out, err: f.offsets.err };\n }\n for (const l of lines) {\n const text = stripAnsi(l.text);\n lastLine = text;\n // the pattern sees the line without pm2's stamp; the answer keeps the line as written\n if (until.kind === 'log' && until.re.test(bodyOf(text)))\n return run.answer({\n ok: true,\n status: statusWord(p, a),\n matched_line: text,\n });\n }\n if (tracker) {\n // one batch carries both streams' new lines in arrival order, as the tracker needs them\n const [r] = [...tracker.push(lines, now), ...tracker.idle(now)];\n if (r)\n return run.answer({\n ok: true,\n status: statusWord(p, a),\n reloaded: { time: r.time, lines: r.lines, line: r.line },\n });\n }\n const observed =\n lastLine === undefined ? 'no new output' : `last line: ${lastLine}`;\n if (until.kind === 'idle' && now - lastChange >= quietMs) {\n p = findProcess(await deps.jlist(ctx), ctx.manifest.project, app);\n if (p && isRunning(p.status))\n return run.answer({ ok: true, status: statusWord(p, a), observed });\n if (!p || !notDead(p.status)) return run.gone(p, observed);\n // mid-restart: not settled yet and not dead; look again after a tick\n lastCheck = now = deps.now();\n }\n if (now - lastCheck >= STATUS_EVERY_MS) {\n lastCheck = now;\n p = findProcess(await deps.jlist(ctx), ctx.manifest.project, app);\n if (!p || !notDead(p.status)) return run.gone(p, observed);\n now = deps.now(); // the check took a login shell, more over ssh: do not sleep from the time before it\n }\n if (now >= run.deadline) return run.giveUp('timeout', p, unmet(observed));\n // the next tick, cut to the deadline, the next status check and the end of the quiet period\n const sleeps = [\n LOG_TICK_MS,\n run.deadline - now,\n lastCheck + STATUS_EVERY_MS - now,\n ];\n // (not once the quiet period is over: a process still restarting is looked at again after a tick, not in a spin)\n if (until.kind === 'idle' && now - lastChange < quietMs)\n sleeps.push(lastChange + quietMs - now);\n // the open reload burst is answered once it has been quiet for RELOAD_GAP_MS, not at the next tick after that\n const burstEnd = tracker?.idleAt() ?? null;\n if (burstEnd !== null) sleeps.push(burstEnd - now);\n if (!woken && !signal?.aborted) {\n tick = new AbortController();\n await deps.sleep(Math.max(0, Math.min(...sleeps)), tick.signal);\n tick = null;\n }\n woken = false;\n if (signal?.aborted) return run.giveUp('aborted', p, unmet(observed));\n }\n } finally {\n signal?.removeEventListener('abort', onAbort);\n f.close();\n }\n}\n\n/**\n * Waits until `until` holds for one app, the timeout passes, the process leaves `online` while the condition is\n * still unmet, or the signal aborts. Every end is a result; only a bad request or an app that was never started\n * throws. An app that is not running (no process, or one stopped or errored) and that a pending or starting lease\n * covers is waited for as long as the lease lasts, its queue word (`queued #N`, `starting`) the status. The deadline is checked after each sample and the last sleep is\n * cut to what remains, so a wait never overshoots its timeout by a whole interval.\n */\nexport async function waitFor(\n ctx: Context,\n app: string,\n until: Until,\n opts: { timeoutMs?: number; signal?: AbortSignal; deps?: WaitDeps } = {}\n): Promise<WaitResult> {\n const deps = opts.deps ?? defaultWaitDeps();\n const a = ctx.manifest.apps[app];\n if (!a) throw unknownApp(ctx, app);\n if (until.kind === 'listening' && a.ports.length === 0)\n throw bad(`\"${app}\" declares no port, so listening cannot be observed`);\n if (until.kind === 'url-ok' && !a.url)\n throw bad(`\"${app}\" declares no url, so url-ok cannot be observed`);\n if (until.kind === 'reloaded' && !a.reloads)\n throw bad(\n `\"${app}\" has reloads: false in the manifest, so reloaded cannot be observed`\n );\n\n const timeoutMs = Math.min(\n opts.timeoutMs ?? WAIT_TIMEOUT_DEFAULT_MS,\n WAIT_TIMEOUT_MAX_MS\n );\n const start = deps.now();\n const deadline = start + timeoutMs;\n const interval = ctx.host.local ? POLL_LOCAL_MS : POLL_REMOTE_MS;\n const label = untilLabel(until);\n const answer: Answer = (part) => ({\n until: label,\n waited_ms: deps.now() - start,\n ...part,\n });\n /** the process left online (or is gone) with the condition still unmet */\n const gone = (p: Pm2Process | undefined, observed?: string): WaitResult =>\n answer({\n ok: false,\n reason: p?.status === 'errored' ? 'crashed' : 'exited',\n status: statusWord(p, a),\n exit_code: p?.exit_code ?? null,\n observed,\n });\n /** the wait ends with the condition unmet: the timeout passed or the signal aborted */\n const giveUp = (\n reason: 'timeout' | 'aborted',\n p: Pm2Process | undefined,\n observed?: string\n ): WaitResult =>\n answer({ ok: false, reason, status: statusWord(p, a), observed });\n /** sleeps until the next poll or the deadline, whichever is first; false when the wait was aborted */\n const pause = async (): Promise<boolean> => {\n await deps.sleep(\n Math.max(0, Math.min(interval, deadline - deps.now())),\n opts.signal\n );\n return !opts.signal?.aborted;\n };\n /**\n * the app is not running (no process, or one stopped or errored): while a lease covers it the wait rides through\n * ('again' once the pause is over, or the end at the deadline or on abort, its status the queue word); null when no\n * lease covers it\n */\n const queued = async (): Promise<WaitResult | 'again' | null> => {\n const cover = (await deps.leases(ctx)).find((l) => l.apps.includes(app));\n if (!cover) return null;\n const status =\n cover.state === 'starting' ? 'starting' : `queued #${cover.position}`;\n const observed = `${status}${cover.waiting_for ? `: ${cover.waiting_for}` : ''}`;\n if (deps.now() >= deadline)\n return answer({ ok: false, reason: 'timeout', status, observed });\n if (!(await pause()))\n return answer({ ok: false, reason: 'aborted', status, observed });\n return 'again';\n };\n if (\n until.kind === 'log' ||\n until.kind === 'idle' ||\n until.kind === 'reloaded'\n )\n return waitOnLogs(ctx, app, a, until, {\n deps,\n deadline,\n signal: opts.signal,\n answer,\n gone,\n giveUp,\n queued,\n });\n\n // true until a process is seen, whatever it shows: a lease that ends before any process appeared is still a request\n // for an app that never started at the next look, and a process seen once makes its absence later a result (gone)\n let first = true;\n for (;;) {\n let p: Pm2Process | undefined;\n let observed: string | undefined;\n if (until.kind === 'exited') {\n p = findProcess(await deps.jlist(ctx), ctx.manifest.project, app);\n if (p) first = false;\n // a run that queued: the last run's exit is not its answer\n if (!p || !isRunning(p.status)) {\n const q = await queued();\n if (q === 'again') continue;\n if (q) return q;\n }\n if (!p) {\n // gone at the first look is a request for an app that never started; gone later is a result\n if (first) throw notStarted(ctx, app);\n return gone(undefined);\n }\n if (!isRunning(p.status) && p.status !== 'stopping')\n return answer({\n ok: true,\n status: statusWord(p, a),\n exit_code: p.exit_code,\n });\n observed = `status ${p.status}`;\n } else {\n const snap = await deps.snapshot(ctx, {\n cpu: 'none',\n metrics: 'none',\n // the option names apps, not urls: the probe checks this app's url\n urls: until.kind === 'url-ok' ? [app] : 'none',\n // read below through deps.leases, and only while the app is not running\n leases: 'none',\n });\n p = findProcess(snap.procs, ctx.manifest.project, app);\n if (p) first = false;\n if (!p || !isRunning(p.status)) {\n const q = await queued();\n if (q === 'again') continue;\n if (q) return q;\n }\n if (!p && first) throw notStarted(ctx, app);\n let met: boolean;\n if (until.kind === 'listening') {\n const ports = snap.ports[app];\n met =\n ports.checks.length > 0 &&\n ports.checks.every((c) => c.status === 'listening');\n observed = met\n ? fmtPorts(ports)\n : `status ${p?.status ?? 'not-started'}, ${fmtPorts(ports)}`;\n } else {\n // the same decision as ls: the host's answer, else the check from here (url_check)\n const u = urlCheckOf(snap, app);\n met = u?.status === 'ok';\n observed = urlSeen(a.url as string, u);\n }\n // the process is judged before the condition: a port or url that answers while it is dead or gone (a proxy,\n // another process) is not a ready app, and one that pm2 is restarting is not ready yet, whatever answers\n if (!p || !notDead(p.status)) return gone(p, observed);\n if (met) {\n if (isRunning(p.status))\n return answer({ ok: true, status: statusWord(p, a), observed });\n observed = `status ${p.status}, ${observed}`;\n }\n }\n if (deps.now() >= deadline) return giveUp('timeout', p, observed);\n if (!(await pause())) return giveUp('aborted', p, observed);\n }\n}\n\n/** What a dependency must show before its dependents start: ready is the declared ports (else the url), completed the exit. */\nexport function untilFor(dep: Dep, depApp: App): Until {\n if (dep.condition === 'completed') return { kind: 'exited' };\n return depApp.ports.length > 0 ? { kind: 'listening' } : { kind: 'url-ok' };\n}\n\n/**\n * A dependency's condition observed on its own context; `completed` also requires exit code 0. It never rides through\n * a lease: the start waiting has just started the dependency itself or found it running, so another run's queued\n * lease over the same app (a task that exited reads stopped) must not hold it back.\n */\nexport async function waitDependency(\n ctx: Context,\n dep: Dep,\n opts: { signal?: AbortSignal; deps?: WaitDeps } = {}\n): Promise<WaitResult> {\n const depApp = ctx.manifest.apps[dep.app];\n if (!depApp) throw unknownApp(ctx, dep.app);\n const r = await waitFor(ctx, dep.app, untilFor(dep, depApp), {\n timeoutMs: dep.timeoutMs,\n signal: opts.signal,\n deps: { ...(opts.deps ?? defaultWaitDeps()), leases: async () => [] },\n });\n if (dep.condition === 'completed' && r.ok && r.exit_code !== 0)\n return { ...r, ok: false, reason: 'failed' };\n return r;\n}\n\n/** Why a dependent was not started, as its row says it. */\nexport function depFailure(dep: Dep, r: WaitResult): string {\n const want = dep.condition === 'completed' ? 'completed' : 'ready';\n switch (r.reason) {\n case 'failed':\n return `${dep.app} ${r.status}`;\n case 'timeout':\n return `${dep.app} not ${want} in ${dep.timeoutMs / 1000} s (${r.observed ?? `status ${r.status}`})`;\n case 'crashed':\n return `${dep.app} crashed`;\n case 'aborted':\n return `${dep.app}: wait aborted`;\n default:\n return `${dep.app} exited (${r.status})`;\n }\n}\n","import type { App, Resources } from '../manifest.js';\nimport { RESERVE_DEFAULT_MIB } from '../manifest.js';\nimport type { HostMemory } from '../memory.js';\nimport { fmtMib } from '../sizes.js';\nimport { type Lease, type LeaseSource, starterAlive } from './store.js';\n\n/** What a running sibling slot showed for an app: its resident set plus containers, in MiB, and which slot. */\nexport interface AppMeasure {\n mib: number;\n slot: number;\n}\n\n/** The estimate of starting `apps`: per app the larger of a running sibling's measurement and the declared memory, else nothing. */\nexport function estimateApps(\n apps: App[],\n measured: Map<string, AppMeasure>\n): { estimate_mib: number; sources: Record<string, LeaseSource> } {\n const sources: Record<string, LeaseSource> = {};\n let estimate_mib = 0;\n for (const a of apps) {\n const m = measured.get(a.name);\n const declared = a.memory_mib ?? 0;\n // the larger of the two: a sibling that grew past its declaration counts as it is, and a measurement that\n // missed its containers (docker stats answered nothing) never undercuts what the manifest declares\n const src: LeaseSource =\n m && m.mib > 0 && m.mib >= declared\n ? { mib: m.mib, source: `measured from slot ${m.slot}` }\n : declared > 0\n ? { mib: declared, source: 'declared' }\n : { mib: 0, source: 'none' };\n sources[a.name] = src;\n estimate_mib += src.mib;\n }\n return { estimate_mib, sources };\n}\n\n/** The estimate with the safety margin on top, rounded up (after six decimals, so 100 * 1.1 is 110, not 111). */\nexport const needOf = (estimate_mib: number, margin: number): number =>\n Math.ceil(Math.round(estimate_mib * (1 + margin) * 1e6) / 1e6);\n\n/** The reserve in MiB: as declared, or a percent of the host's total; the default when a percent has no reading to apply to. */\nexport function reserveMib(\n reserve: Resources['reserve'],\n memory: HostMemory | null\n): number {\n if (reserve.kind === 'mib') return reserve.mib;\n return memory\n ? Math.ceil(memory.total_mib * reserve.ratio)\n : RESERVE_DEFAULT_MIB;\n}\n\n/** Whether a lease may run now, and when not, why and how much memory the host had over the reserve. */\nexport type Admission =\n | { ok: true; free_mib: number | null }\n | {\n ok: false;\n reason: 'never' | 'queue' | 'memory';\n waiting_for: string;\n free_mib: number | null;\n };\n\n/**\n * What the running leases that have not settled yet still claim, in MiB: the need of each one that reached running\n * less than `settleMs` ago, or whose starter is still launching it, which the host's memory reading may not show yet.\n */\nexport function rampingMib(\n leases: Lease[],\n now: number,\n settleMs: number\n): number {\n let mib = 0;\n for (const l of leases) {\n if (l.state !== 'running' || !l.running_at) continue;\n if (now - Date.parse(l.running_at) < settleMs || starterAlive(l, now))\n mib += l.need_mib;\n }\n return mib;\n}\n\n/**\n * Whether a lease may run now: not when it can never fit the host, not while others are ahead of it (strict FIFO),\n * and only when what the host can give minus the reserve, less what ramping starts still claim (`ramping_mib`, see\n * rampingMib), covers the need. Without a memory reading only the queue counts.\n */\nexport function admit(opts: {\n ahead: number;\n memory: HostMemory | null;\n need_mib: number;\n reserve_mib: number;\n /** the need of the running leases younger than the settle time, which the reading may not show yet */\n ramping_mib?: number;\n}): Admission {\n const { memory, need_mib, reserve_mib } = opts;\n const ramping = opts.ramping_mib ?? 0;\n const free_mib = memory ? memory.available_mib - ramping - reserve_mib : null;\n if (memory && need_mib > memory.total_mib - reserve_mib)\n return {\n ok: false,\n reason: 'never',\n waiting_for: `needs ${fmtMib(need_mib)} but the host has at most ${fmtMib(memory.total_mib - reserve_mib)} over the reserve`,\n free_mib,\n };\n if (opts.ahead > 0)\n return {\n ok: false,\n reason: 'queue',\n waiting_for: `${opts.ahead} ahead in the queue`,\n free_mib,\n };\n if (free_mib !== null && free_mib < need_mib)\n return {\n ok: false,\n reason: 'memory',\n waiting_for: `needs ${fmtMib(need_mib)}, host has ${fmtMib(Math.max(0, free_mib))} over the reserve (${fmtMib(need_mib - free_mib)} short${ramping > 0 ? `, ${fmtMib(ramping)} ramping` : ''})`,\n free_mib,\n };\n return { ok: true, free_mib };\n}\n","import fs from 'node:fs';\nimport type { Spawner } from '../../transport/types.js';\nimport type { LsRow } from '../list.js';\nimport { rowsFor, snapshot } from '../list.js';\nimport { findManifestPath, type Manifest } from '../manifest.js';\nimport { isRunning } from '../pm2.js';\nimport { connect, prepare } from '../resolve.js';\nimport {\n type Registry,\n readRegistry,\n registryPath,\n siblingsOf,\n} from '../slots.js';\nimport { stateDir } from '../state.js';\nimport type { AppMeasure } from './admission.js';\n\nconst MIB = 1024 * 1024;\n\n/** The main checkout the registry is keyed by: what the override recorded for a worktree, else this root itself. */\nexport const repoOf = (m: Manifest): string => m.repo;\n\n/** The slot registry of a manifest's repository, or null when `worktree add` never ran for it. */\nexport function registryOf(m: Manifest, dir = stateDir()): Registry | null {\n return readRegistry(registryPath(dir, m.base_project, repoOf(m)));\n}\n\n/**\n * Whether `root` is a checkout with a manifest of its own. The manifest search walks up, so a path without one (gone,\n * or nested in another checkout) would otherwise stand for the project that encloses it.\n */\nexport function ownsManifest(root: string): boolean {\n const found = findManifestPath(root);\n if (!found) return false;\n try {\n return fs.realpathSync(found.root) === fs.realpathSync(root);\n } catch {\n return false; // gone meanwhile\n }\n}\n\n/** One checkout's rows, read locally with the full probe (containers included) and no url checks; none when `root` has no manifest of its own. */\nexport async function listCheckout(\n root: string,\n spawner?: Spawner\n): Promise<LsRow[]> {\n if (!ownsManifest(root)) return [];\n const ctx = await connect(prepare({ project: root }), { spawner });\n // the full probe with the containers' memory: this is the measurement the estimate rests on\n const snap = await snapshot(ctx, {\n urls: 'none',\n cpu: 'none',\n containers: 'probe',\n });\n return rowsFor(ctx, snap, Object.keys(ctx.manifest.apps));\n}\n\n/**\n * What the other checkouts of the repository show for each app that is online there, the largest value per app\n * (the conservative estimate), from the registry's slots whose path still exists; a checkout that does not answer\n * contributes nothing. The checkouts are read at the same time and folded in slot order, so a tie goes to the lowest slot.\n */\nexport async function measureSiblings(\n m: Manifest,\n deps: {\n registry: Registry | null;\n list: (root: string) => Promise<LsRow[]>;\n exists?: (p: string) => boolean;\n }\n): Promise<Map<string, AppMeasure>> {\n const out = new Map<string, AppMeasure>();\n if (!deps.registry) return out;\n const exists = deps.exists ?? ((p) => fs.existsSync(p));\n const read = await Promise.all(\n siblingsOf(deps.registry, m.root)\n .filter(({ entry }) => exists(entry.path))\n .map(async ({ slot, entry }) => {\n try {\n return { slot, rows: await deps.list(entry.path) };\n } catch {\n return { slot, rows: [] as LsRow[] }; // a checkout that does not answer\n }\n })\n );\n for (const { slot, rows } of read) {\n for (const r of rows) {\n if (!isRunning(r.status) || r.memory <= 0) continue;\n const mib = Math.ceil(r.memory / MIB);\n const prev = out.get(r.app);\n if (!prev || mib > prev.mib) out.set(r.app, { mib, slot });\n }\n }\n return out;\n}\n","import crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { McprocError } from './errors.js';\n\n/** One checkout of a repository: where it is, which branch, and the project slug it runs under. */\nexport interface SlotEntry {\n path: string;\n branch: string | null;\n project: string;\n}\n/** The slots of one repository on this host: 0 is the main checkout, 1..N its worktrees. */\nexport interface Registry {\n repo: string;\n slots: Record<string, SlotEntry>;\n}\n\n/**\n * `<base project>-<8 hex of sha256(real main path)>`: two unrelated repositories named alike never share slots, and a\n * checkout opened through a symlink finds the registry of its real path.\n */\nexport function registryKey(baseProject: string, repo: string): string {\n return `${baseProject}-${crypto.createHash('sha256').update(realOf(repo)).digest('hex').slice(0, 8)}`;\n}\n/** The file that holds a repository's registry under the host state directory. */\nexport function registryPath(\n stateDir: string,\n baseProject: string,\n repo: string\n): string {\n return path.join(stateDir, 'slots', `${registryKey(baseProject, repo)}.json`);\n}\n/** A registry for a repository with no slots claimed yet. */\nexport function emptyRegistry(repo: string): Registry {\n return { repo, slots: {} };\n}\n/** Reads a registry file, or null when it does not exist. */\nexport function readRegistry(file: string): Registry | null {\n if (!fs.existsSync(file)) return null;\n return JSON.parse(fs.readFileSync(file, 'utf8')) as Registry;\n}\n/** Writes a registry file atomically, creating its directory when needed. */\nexport function writeRegistry(file: string, r: Registry): void {\n fs.mkdirSync(path.dirname(file), { recursive: true });\n const tmp = `${file}.${process.pid}.tmp`;\n fs.writeFileSync(tmp, JSON.stringify(r, null, 2));\n fs.renameSync(tmp, file);\n}\n/** The registry with slot 0 set to the main checkout. */\nexport function withMain(r: Registry, entry: SlotEntry): Registry {\n return { ...r, slots: { ...r.slots, '0': entry } };\n}\n/** The lowest free slot in 1..max, or `want` when it is free; slot 0 is never claimed. */\nexport function claimSlot(\n r: Registry,\n opts: { max: number; want?: number; entry: SlotEntry }\n): { registry: Registry; slot: number } {\n if (opts.want !== undefined) {\n if (opts.want < 1 || opts.want > opts.max)\n throw new McprocError(\n 'BAD_ARGUMENT',\n `slot ${opts.want} is outside 1..${opts.max} (slot 0 is the main checkout)`\n );\n if (Object.hasOwn(r.slots, String(opts.want)))\n throw new McprocError(\n 'SLOT_TAKEN',\n `slot ${opts.want} is taken by ${r.slots[String(opts.want)].path}`,\n { hint: 'Pick another slot, or remove that worktree first.' }\n );\n return {\n registry: { ...r, slots: { ...r.slots, [opts.want]: opts.entry } },\n slot: opts.want,\n };\n }\n for (let s = 1; s <= opts.max; s++)\n if (!Object.hasOwn(r.slots, String(s)))\n return {\n registry: { ...r, slots: { ...r.slots, [s]: opts.entry } },\n slot: s,\n };\n throw new McprocError(\n 'NO_FREE_SLOT',\n `all ${opts.max} worktree slots of ${r.repo} are taken`,\n {\n hint: 'Remove a worktree (worktree remove), or raise worktree.slots in the manifest.',\n }\n );\n}\n/** The registry without the given slot. */\nexport function releaseSlot(r: Registry, slot: number): Registry {\n const slots = { ...r.slots };\n delete slots[String(slot)];\n return { ...r, slots };\n}\n/** A path as the filesystem sees it: symlinks resolved when it exists, else just made absolute. */\nexport function realOf(p: string): string {\n try {\n return fs.realpathSync(p);\n } catch {\n return path.resolve(p);\n }\n}\n/** Drops the slots (never 0) whose checkout path no longer exists; returns them. */\nexport function reclaimGone(\n r: Registry,\n exists: (p: string) => boolean\n): { registry: Registry; freed: number[] } {\n const freed: number[] = [];\n let out = r;\n for (const [k, e] of Object.entries(r.slots)) {\n if (k === '0' || exists(realOf(e.path))) continue;\n out = releaseSlot(out, Number(k));\n freed.push(Number(k));\n }\n return { registry: out, freed: freed.sort((a, b) => a - b) };\n}\n/** Every other checkout of the repository, lowest slot first. */\nexport function siblingsOf(\n r: Registry,\n root: string\n): { slot: number; entry: SlotEntry }[] {\n return Object.entries(r.slots)\n .filter(([, e]) => realOf(e.path) !== realOf(root))\n .map(([k, entry]) => ({ slot: Number(k), entry }))\n .sort((a, b) => a.slot - b.slot);\n}\n","import { describeError, isMcprocError, McprocError } from '../errors.js';\nimport type { LsRow } from '../list.js';\nimport { readHostMemory, type HostMemory } from '../memory.js';\nimport { findProcess, isRunning, type Pm2Process } from '../pm2.js';\nimport type { Context } from '../resolve.js';\nimport { stateDir } from '../state.js';\nimport { abortableSleep } from '../wait.js';\nimport {\n admit,\n estimateApps,\n needOf,\n rampingMib,\n reserveMib,\n type AppMeasure,\n} from './admission.js';\nimport { ensureWatcher } from './ensure.js';\nimport { listCheckout, measureSiblings, registryOf } from './siblings.js';\nimport {\n LeaseStore,\n pidAlive,\n starterAlive,\n type Lease,\n type NewLease,\n} from './store.js';\n\n/** What the gate reads and writes: the lease store, the host's memory, the sibling measurement and the watcher. */\nexport interface GateDeps {\n store: LeaseStore;\n /** the host's memory reading, or null where it has none */\n memory(ctx: Context): Promise<HostMemory | null>;\n /** what the running sibling checkouts show per app */\n siblings(ctx: Context): Promise<Map<string, AppMeasure>>;\n /** makes sure the watcher runs once a lease is pending: the pm2 process mcproc-watcher on the context's daemon */\n ensureWatcher(ctx: Context): Promise<unknown>;\n /** the requester's pid kept on the lease; default this process */\n pid?: number;\n}\n/** A lease that still waits for memory: queued, or handed to the watcher and not up yet. */\nexport type QueuedLease = Lease & { state: 'pending' | 'starting' };\n/** The gate's answer: go ahead (under a running lease, or none when nothing is budgeted), or queued behind others. */\nexport type GateResult =\n | { kind: 'proceed'; lease: Lease | null }\n | {\n kind: 'queued';\n lease: QueuedLease;\n position: number;\n waiting_for: string;\n };\n/** How long a stop waits for the child of a starting lease it cancelled to exit after SIGTERM, in milliseconds. */\nexport const CANCEL_WAIT_MS = 10_000;\nconst CANCEL_POLL_MS = 200;\n\n/** The real deps: the host state directory, the host's meminfo, the sibling checkouts of the registry, the pm2 watcher. */\nexport function defaultGateDeps(dir = stateDir()): GateDeps {\n return {\n store: new LeaseStore(dir),\n memory: (ctx) => readHostMemory(ctx.transport, ctx.host),\n siblings: (ctx) =>\n measureSiblings(ctx.manifest, {\n registry: registryOf(ctx.manifest, dir),\n list: (root) => listCheckout(root),\n }),\n ensureWatcher: (ctx) => ensureWatcher(ctx, dir),\n };\n}\n\n/**\n * Whether a start of `apps` on this context may run now. Apps already online count zero; a start with no declared\n * memory never touches the queue. Otherwise the estimate (measured from a sibling slot where one runs, else declared,\n * plus the margin) is judged under the lock, the running leases younger than the manifest's settle time charged on\n * top of the reading: admitted at once as a running lease, or queued as a pending one behind whatever is pending\n * already, in which case the watcher is made sure of and the caller returns. When the watcher cannot be launched, the\n * pending lease this call created is cancelled with the reason (one it joined is left to its caller) and the start\n * fails (the McprocError as it came, else PM2_FAILED).\n */\nexport async function gateStart(\n ctx: Context,\n apps: string[],\n opts: {\n /** the target as the caller named it (an app, a profile, all): the watcher starts it again by this name */\n target: string;\n /** the `--host` the caller gave, else none: kept on the lease so the watcher's child acts on the same hosts */\n host?: string | null;\n reload?: boolean;\n note?: string | null;\n procs: Pm2Process[];\n },\n deps: GateDeps\n): Promise<GateResult> {\n const m = ctx.manifest;\n const toStart = apps.filter((n) => {\n const p = findProcess(opts.procs, m.project, n);\n return !(p && isRunning(p.status));\n });\n const budgeted = toStart.filter((n) => m.apps[n].memory_mib !== null);\n if (budgeted.length === 0) return { kind: 'proceed', lease: null };\n if (!ctx.host.local)\n throw new McprocError(\n 'LEASE_UNSUPPORTED_HOST',\n `${budgeted.join(', ')} declare memory but run on host ${ctx.host.name}; the lease queue works on the local host only in this version`,\n { hint: 'Drop memory: from apps bound to remote hosts.' }\n );\n const memory = await deps.memory(ctx);\n const measured = await deps.siblings(ctx);\n const { estimate_mib, sources } = estimateApps(\n toStart.map((n) => m.apps[n]),\n measured\n );\n if (estimate_mib === 0) return { kind: 'proceed', lease: null };\n const need_mib = needOf(estimate_mib, m.resources.margin);\n const reserve_mib = reserveMib(m.resources.reserve, memory);\n const target = opts.target;\n const host = opts.host ?? null;\n const input: NewLease = {\n kind: 'start',\n project: m.project,\n root: m.root,\n slot: m.slot,\n repo: m.repo,\n target,\n host,\n apps: toStart,\n reload: Boolean(opts.reload),\n estimate_mib,\n need_mib,\n margin: m.resources.margin,\n reserve_mib,\n sources,\n note: opts.note ?? null,\n requester_pid: deps.pid ?? process.pid,\n };\n // `created`: whether this call wrote the lease, or joined one an earlier caller queued\n const { result, created } = await deps.store.withLock(\n async (): Promise<{\n result: GateResult;\n created: boolean;\n }> => {\n const same = deps.store\n .list()\n .find(\n (l): l is QueuedLease =>\n (l.state === 'pending' || l.state === 'starting') &&\n l.root === m.root &&\n l.project === m.project &&\n l.target === target &&\n (l.host ?? null) === host\n );\n if (same)\n return {\n result: {\n kind: 'queued',\n lease: same,\n position: deps.store.positionOf(same.id),\n waiting_for: same.waiting_for ?? same.state,\n },\n created: false,\n };\n const all = deps.store.list();\n const ahead = all.filter(\n (l) => l.state === 'pending' || l.state === 'starting'\n ).length;\n // a start admitted seconds ago is not in the reading yet: two starts on one reading must not both fit\n const ramping_mib = rampingMib(\n all,\n Date.now(),\n m.resources.settle * 1000\n );\n const d = admit({ ahead, memory, need_mib, reserve_mib, ramping_mib });\n if (!d.ok && d.reason === 'never')\n throw new McprocError('NEVER_FITS', `${target}: ${d.waiting_for}`, {\n hint: \"Lower the apps' memory: declarations or the resources.reserve, or run fewer apps.\",\n });\n if (d.ok) {\n // this process runs the start: until it is done, the watcher must not judge the lease by its apps\n const lease = await deps.store.create(input, 'running', {\n child_pid: process.pid,\n });\n return { result: { kind: 'proceed', lease }, created: true };\n }\n const created = await deps.store.create(input, 'pending');\n const lease = await deps.store.patch(created.id, {\n waiting_for: d.waiting_for,\n });\n return {\n result: {\n kind: 'queued',\n lease: { ...lease, state: 'pending' },\n position: deps.store.positionOf(lease.id),\n waiting_for: d.waiting_for,\n },\n created: true,\n };\n }\n );\n if (result.kind === 'queued')\n try {\n await deps.ensureWatcher(ctx);\n } catch (e) {\n // nothing would ever admit it, and it would hold every later start of the host behind it; a lease joined from an\n // earlier caller is that caller's, and is left alone\n const error = `the watcher could not be launched: ${describeError(e)}`;\n const id = result.lease.id;\n if (created)\n await deps.store\n .withLock(async () => {\n if (deps.store.get(id)?.state === 'pending')\n await deps.store.transition(id, 'cancelled', { error });\n })\n .catch(() => undefined);\n throw isMcprocError(e) ? e : new McprocError('PM2_FAILED', error);\n }\n return result;\n}\n\n/** After the watcher's child ran the start, under the lock: running when any app came up (failures noted), failed when none did. */\nexport async function finishLeasedStart(\n store: LeaseStore,\n id: string,\n rows: LsRow[]\n): Promise<Lease> {\n const bad = rows.filter((r) => r.error);\n const error = bad.length\n ? bad.map((r) => `${r.app}: ${r.error}`).join('; ')\n : null;\n return store.withLock(() =>\n bad.length === rows.length\n ? store.transition(id, 'failed', { error, child_pid: null })\n : store.transition(id, 'running', { error, child_pid: null })\n );\n}\n\n/** A start admitted at once that then threw: its running lease is freed with the error and without its starter, under the lock. */\nexport async function freeOnFailure(\n store: LeaseStore,\n lease: Lease,\n e: unknown\n): Promise<void> {\n const error = e instanceof Error ? e.message : String(e);\n try {\n await store.withLock(() =>\n store.transition(lease.id, 'freed', { error, child_pid: null })\n );\n } catch {\n /* already ended by someone else */\n }\n}\n\n/** How many times endFastStart tries its clear, and how long it pauses between two tries, in milliseconds. */\nconst END_FAST_TRIES = 3;\nconst END_FAST_PAUSE_MS = 2000;\n\n/**\n * A start admitted at once that went through: its starter is cleared under the lock, while the lease is still running\n * and still names it. A clear that fails (the lock is busy) is tried END_FAST_TRIES times END_FAST_PAUSE_MS apart before\n * the last error is let through; a lease left naming its starter is then trusted no longer than STARTER_TRUST_MS.\n */\nexport async function endFastStart(\n store: LeaseStore,\n lease: Lease,\n sleep: (ms: number) => Promise<void> = abortableSleep\n): Promise<void> {\n for (let attempt = 1; ; attempt++) {\n try {\n await store.withLock(async () => {\n const cur = store.get(lease.id);\n if (\n cur?.state === 'running' &&\n cur.child_pid !== null &&\n cur.child_pid === lease.child_pid\n )\n await store.patch(lease.id, { child_pid: null });\n });\n return;\n } catch (e) {\n if (attempt >= END_FAST_TRIES) throw e;\n await sleep(END_FAST_PAUSE_MS);\n }\n }\n}\n\n/** The leases of this checkout that still wait for or hold memory (pending, starting, running), read without the lock. */\nexport function liveLeasesOf(store: LeaseStore, ctx: Context): Lease[] {\n const m = ctx.manifest;\n return store\n .list()\n .filter(\n (l) =>\n l.root === m.root &&\n l.project === m.project &&\n (l.state === 'pending' ||\n l.state === 'starting' ||\n l.state === 'running')\n );\n}\n\n/**\n * Before a stop or delete of `stopped` on this checkout: every pending or starting lease of it whose apps overlap the\n * stopped ones is cancelled under the lock; then the child of each cancelled starting lease is sent SIGTERM and\n * waited for, up to CANCEL_WAIT_MS, so it cannot launch an app after the stop. Returns the cancelled ids.\n */\nexport async function cancelBefore(\n store: LeaseStore,\n ctx: Context,\n stopped: string[]\n): Promise<string[]> {\n const m = ctx.manifest;\n // nothing of this checkout is live: the lock (and the state directory) is left alone\n if (liveLeasesOf(store, ctx).length === 0) return [];\n const cancelled: string[] = [];\n const children: number[] = [];\n await store.withLock(async () => {\n for (const l of store.list()) {\n if (l.root !== m.root || l.project !== m.project) continue;\n if (l.state !== 'pending' && l.state !== 'starting') continue;\n if (!l.apps.some((a) => stopped.includes(a))) continue;\n await store.transition(l.id, 'cancelled', {\n error: `stop of ${stopped.join(', ')}`,\n });\n cancelled.push(l.id);\n if (l.state === 'starting' && l.child_pid) children.push(l.child_pid);\n }\n });\n // outside the lock: the child may want it on its way out, and the wait can take seconds\n await Promise.all(children.map((pid) => endChild(pid)));\n return cancelled;\n}\n\n/** Sends SIGTERM to a lease's child and polls until it is gone, for up to CANCEL_WAIT_MS. */\nasync function endChild(pid: number): Promise<void> {\n if (!pidAlive(pid)) return;\n try {\n process.kill(pid, 'SIGTERM');\n } catch {\n return; // gone meanwhile\n }\n const until = Date.now() + CANCEL_WAIT_MS;\n while (pidAlive(pid) && Date.now() < until)\n await new Promise((r) => setTimeout(r, CANCEL_POLL_MS));\n}\n\n/**\n * After a stop or delete on this checkout: every running start lease of it none of whose apps is online in `procs` is\n * freed, unless its starter is still alive (another process is still starting it); an exec lease belongs to its own\n * process and ends with it. Returns the freed ids.\n */\nexport async function freeAfter(\n store: LeaseStore,\n ctx: Context,\n procs: Pm2Process[]\n): Promise<string[]> {\n const m = ctx.manifest;\n const online = (app: string) => {\n const p = findProcess(procs, m.project, app);\n return Boolean(p && isRunning(p.status));\n };\n const freed: string[] = [];\n if (liveLeasesOf(store, ctx).length === 0) return freed;\n await store.withLock(async () => {\n for (const l of store.list()) {\n if (l.root !== m.root || l.project !== m.project) continue;\n if (\n l.kind === 'start' &&\n l.state === 'running' &&\n !starterAlive(l) &&\n !l.apps.some(online)\n ) {\n await store.transition(l.id, 'freed');\n freed.push(l.id);\n }\n }\n });\n return freed;\n}\n","import { McprocError, describeError } from './errors.js';\nimport type { Dep, Manifest } from './manifest.js';\nimport { assertApp, connect, pickHost, type Context } from './resolve.js';\nimport {\n deleteApps,\n orderWithDeps,\n resolveTargets,\n restartApps,\n startApps,\n stopApps,\n type WaitRecord,\n} from './actions.js';\nimport { waitDependency } from './wait.js';\nimport {\n depView,\n describeApp,\n queuedRow,\n rowsFor,\n snapshot,\n unreachableRow,\n type LsRow,\n type Snapshot,\n type SnapshotOptions,\n} from './list.js';\nimport {\n cancelBefore,\n defaultGateDeps,\n endFastStart,\n finishLeasedStart,\n freeAfter,\n freeOnFailure,\n gateStart,\n liveLeasesOf,\n type GateDeps,\n} from './leases/gate.js';\nimport type { Lease } from './leases/store.js';\nimport type { Spawner } from '../transport/types.js';\nimport type { HereCheck } from './urlcheck.js';\n\n/** Opens a context for `host`; `fallback` is where the unbound apps run for this command (see connect). */\nexport type Connector = (\n m: Manifest,\n host: string,\n fallback: string\n) => Promise<Context>;\nexport interface HostApps {\n host: string;\n apps: string[];\n}\n\nexport const defaultConnector =\n (spawner?: Spawner, hereCheck?: HereCheck): Connector =>\n (m, host, fallback) =>\n connect(\n { manifest: m, host: pickHost(m, host) },\n { spawner, fallback, hereCheck }\n );\n\n/**\n * The hosts one command acts on. An app with `host:` always runs there; an app without one runs on the host the command\n * names (--host), or on local when it names none. Without --host a command reaches every app at its own host; with\n * --host X it reaches only the apps that run on X.\n */\nexport class Fleet {\n /** where the unbound apps run for this command */\n readonly fallback: string;\n private readonly ctxs = new Map<string, Promise<Context>>();\n\n constructor(\n readonly manifest: Manifest,\n readonly requested: string | undefined,\n private readonly connector: Connector = defaultConnector()\n ) {\n if (requested !== undefined) pickHost(manifest, requested); // UNKNOWN_HOST before anything runs\n this.fallback = requested ?? 'local';\n }\n\n hostOf(app: string): string {\n return this.manifest.apps[app].host ?? this.fallback;\n }\n\n /** The host of one app named by the caller (describe, logs): a profile is not an app; an app elsewhere than --host is refused. */\n one(app: string): string {\n assertApp(this.manifest, app);\n this.select([app]);\n return this.hostOf(app);\n }\n\n /** Apps, profiles or \"all\" to app names, each once. With --host, names that run elsewhere are refused or left out. */\n select(targets: string[]): string[] {\n const out = new Set<string>();\n for (const t of targets) {\n const names = resolveTargets(this.manifest, t);\n const here =\n this.requested === undefined\n ? names\n : names.filter((n) => this.hostOf(n) === this.requested);\n const byName = t !== 'all' && !Object.hasOwn(this.manifest.profiles, t);\n if (byName && here.length === 0) {\n throw new McprocError(\n 'WRONG_HOST',\n `\"${t}\" runs on host ${this.hostOf(t)}, not on ${this.requested} (apps.${t}.host in ${this.manifest.path})`,\n {\n hint: `Drop --host to reach every app at its own host, or use --host ${this.hostOf(t)}.`,\n }\n );\n }\n if (names.length > 0 && here.length === 0) {\n throw new McprocError(\n 'WRONG_HOST',\n `no app of \"${t}\" runs on host ${this.requested}`,\n {\n hint: `Its apps run on ${[...new Set(names.map((n) => this.hostOf(n)))].join(', ')}; drop --host to reach each at its own host.`,\n }\n );\n }\n for (const n of here) out.add(n);\n }\n return [...out];\n }\n\n /** `named` with their dependencies, dependencies first: what a start acts on; with --host only the apps that run there. */\n withDeps(named: string[]): string[] {\n return orderWithDeps(this.manifest, named).filter(\n (n) => this.requested === undefined || this.hostOf(n) === this.requested\n );\n }\n\n /** One group per host, each app in it, hosts in first-appearance order: for reads, which may run in parallel. */\n groups(names: string[]): HostApps[] {\n const by = new Map<string, string[]>();\n for (const n of names) {\n const h = this.hostOf(n);\n by.set(h, [...(by.get(h) ?? []), n]);\n }\n return [...by].map(([host, apps]) => ({ host, apps }));\n }\n\n /** Consecutive apps of one host form one run, the given order kept: for changes, where dependency order matters. */\n runs(names: string[]): HostApps[] {\n const out: HostApps[] = [];\n for (const n of names) {\n const h = this.hostOf(n);\n const last = out.at(-1);\n if (last?.host === h) last.apps.push(n);\n else out.push({ host: h, apps: [n] });\n }\n return out;\n }\n\n /** The hosts that a whole-project command reaches. */\n hosts(): string[] {\n return this.groups(this.select(['all'])).map((g) => g.host);\n }\n\n /** One context per host for the life of the command; a failed connect is not kept, so the next call retries. */\n ctx(host: string): Promise<Context> {\n let p = this.ctxs.get(host);\n if (!p) {\n p = this.connector(this.manifest, host, this.fallback);\n this.ctxs.set(host, p);\n p.catch(() => {\n if (this.ctxs.get(host) === p) this.ctxs.delete(host);\n });\n }\n return p;\n }\n}\n\nexport type Act = 'start' | 'restart' | 'stop' | 'delete';\n\n/**\n * Refuse before any host is touched when one of the runs lands on a readonly host. `named` are the apps the caller asked\n * for: an app on that host that was only pulled in as a dependency is named as such, with the way to leave it out.\n */\nexport function assertWritableRuns(\n fleet: Fleet,\n runs: HostApps[],\n named?: string[]\n): void {\n for (const r of runs) {\n const host = pickHost(fleet.manifest, r.host);\n if (!host.readonly) continue;\n const apps = [\n ...new Set(runs.filter((x) => x.host === r.host).flatMap((x) => x.apps)),\n ];\n const askers = (dep: string) =>\n (named ?? []).filter(\n (n) => n !== dep && dependsOn(fleet.manifest, n, dep)\n );\n const label = (a: string) =>\n named && !named.includes(a) && askers(a).length\n ? `\"${a}\" (a dependency of ${askers(a)\n .map((n) => `\"${n}\"`)\n .join(', ')})`\n : `\"${a}\"`;\n const viaDeps =\n named !== undefined && apps.every((a) => !named.includes(a));\n const askHosts = [\n ...new Set(\n (named ?? []).map((n) => fleet.hostOf(n)).filter((h) => h !== r.host)\n ),\n ];\n throw new McprocError(\n 'READONLY_HOST',\n `Host \"${host.name}\" is readonly: no start/stop/restart/delete/flush/init there, and ${apps.map(label).join(', ')} ${apps.length > 1 ? 'run' : 'runs'} there; nothing was changed`,\n {\n hint:\n viaDeps && askHosts.length === 1\n ? `Start with --host ${askHosts[0]} to leave dependencies on other hosts alone.`\n : 'Name the apps, or a profile, that leave those out. Read-only tools (ls, describe, logs, ports, doctor) still work there.',\n }\n );\n }\n}\n\n/**\n * Refuse a start before any host is touched when one of its runs lands on a remote host with an app that declares\n * memory: the lease queue works on the local host only in this version.\n */\nfunction assertLocalBudgets(fleet: Fleet, runs: HostApps[]): void {\n for (const r of runs) {\n if (pickHost(fleet.manifest, r.host).local) continue;\n const budgeted = r.apps.filter(\n (a) => fleet.manifest.apps[a].memory_mib !== null\n );\n if (budgeted.length === 0) continue;\n throw new McprocError(\n 'LEASE_UNSUPPORTED_HOST',\n `${budgeted.join(', ')} declare memory but run on host ${r.host}; the lease queue works on the local host only in this version`,\n { hint: 'Drop memory: from apps bound to remote hosts.' }\n );\n }\n}\n\nfunction dependsOn(\n m: Manifest,\n app: string,\n dep: string,\n seen = new Set<string>()\n): boolean {\n for (const d of m.apps[app]?.depends_on ?? []) {\n if (d.app === dep) return true;\n if (!seen.has(d.app)) {\n seen.add(d.app);\n if (dependsOn(m, d.app, dep, seen)) return true;\n }\n }\n return false;\n}\n\n/** A host that could not be reached, or a change it refused: the apps of that run get rows saying so. */\nfunction failedRows(fleet: Fleet, r: HostApps, e: unknown): LsRow[] {\n const code = (e as { code?: string }).code;\n const status =\n code === 'TRANSPORT_FAILED' || code === 'TIMEOUT'\n ? 'unreachable'\n : 'failed';\n return r.apps.map((a) =>\n unreachableRow(fleet.manifest.apps[a], r.host, describeError(e), status)\n );\n}\n\n/**\n * start/restart/stop/delete of a target across hosts. start adds the dependencies first (with --host only those that\n * run on that host); the apps are then cut into runs of one host each and acted on run by run, in that order. A run that\n * fails leaves rows saying so and the other runs go on — except for start, where the later runs are skipped (they may\n * need what did not start). When nothing happened at all, the first error is thrown. A start that would run an app\n * declaring memory on a remote host is refused before any host is touched; a local start of such apps goes through the\n * lease gate first (a queued run answers queued rows for the apps the gate counted, the real rows of the others, and\n * holds back the dependents of the queued ones in later runs), and a start the watcher admitted ends its lease once,\n * over every local row. A local stop or delete first cancels the checkout's queued and starting leases it overlaps\n * (ending a starting one's child), then acts, then frees the running leases that no longer hold anything.\n */\nexport async function actOn(\n fleet: Fleet,\n target: string,\n act: Act,\n opts: {\n reload?: boolean;\n waits?: WaitRecord[];\n /** ends the dependency waits of a start as `aborted`: the caller's request was cancelled */\n signal?: AbortSignal;\n /** a note kept on the lease (what this start is for) */\n note?: string | null;\n /** the id of a lease the watcher admitted: the start skips the queue and ends the lease as running or failed */\n lease?: string | null;\n /** the lease machinery (tests pass fakes); default the host state directory */\n gate?: GateDeps;\n } = {}\n): Promise<LsRow[]> {\n const named = fleet.select([target]);\n const names = act === 'start' ? fleet.withDeps(named) : named;\n const runs = fleet.runs(names);\n assertWritableRuns(fleet, runs, named);\n if (act === 'start') assertLocalBudgets(fleet, runs);\n const rows: LsRow[] = [];\n let failed: { host: string; error: unknown } | null = null;\n let done = 0;\n const notStarted = new Map<string, string>(); // app -> why it did not start; one map for every run\n /** every dependency of an app from the full manifest; with --host X the ones that run elsewhere are left out (neither started nor waited for) */\n const depsOf = (n: string): Dep[] =>\n fleet.manifest.apps[n].depends_on.filter(\n (d) =>\n fleet.requested === undefined || fleet.hostOf(d.app) === fleet.requested\n );\n /** a dependency is observed on the host it runs on, whatever run the dependent is in */\n const waitDep = async (d: Dep) =>\n waitDependency(await fleet.ctx(fleet.hostOf(d.app)), d, {\n signal: opts.signal,\n });\n const gate = opts.gate ?? defaultGateDeps();\n for (const r of runs) {\n if (failed && act === 'start') {\n rows.push(\n ...r.apps.map((a) =>\n unreachableRow(\n fleet.manifest.apps[a],\n r.host,\n `skipped: the start on ${failed!.host} before it failed`,\n 'skipped'\n )\n )\n );\n continue;\n }\n try {\n const ctx = await fleet.ctx(r.host);\n let admitted: Lease | null = null;\n // only a run with an app that declares memory asks pm2 what runs already: the others never touch the queue\n const budgeted = r.apps.some(\n (a) => fleet.manifest.apps[a].memory_mib !== null\n );\n if (act === 'start' && ctx.host.local && !opts.lease && budgeted) {\n const g = await gateStart(\n ctx,\n r.apps,\n {\n target,\n host: fleet.requested ?? null,\n reload: opts.reload,\n note: opts.note,\n procs: await ctx.pm2.jlist(),\n },\n gate\n );\n if (g.kind === 'queued') {\n // only the apps the gate counted wait: what needs them in a later run (another host) is skipped, not\n // started without them; an app that was online already answers as it is\n const queued = new Set(\n g.lease.apps.filter((a) => r.apps.includes(a))\n );\n for (const a of queued)\n notStarted.set(a, `queued: lease ${g.lease.id}`);\n const up = r.apps.filter((a) => !queued.has(a));\n const real = new Map(\n (up.length\n ? rowsFor(ctx, await snapshot(ctx, { urls: up }), up)\n : []\n ).map((x) => [x.app, x])\n );\n rows.push(\n ...r.apps.map(\n (a) =>\n real.get(a) ??\n queuedRow(fleet.manifest.apps[a], r.host, g.lease, g.position)\n )\n );\n done++;\n continue;\n }\n admitted = g.lease;\n }\n // a stop must not race a start it overlaps: the queued and starting leases go first, their children with them;\n // the leases are bookkeeping, so a lock that fails never holds back a stop: its rows say so instead\n const stopping = (act === 'stop' || act === 'delete') && ctx.host.local;\n const leaseNotes: string[] = [];\n const unrecorded = (e: unknown) => {\n leaseNotes.push(`leases not updated: ${describeError(e)}`);\n };\n if (stopping)\n await cancelBefore(gate.store, ctx, r.apps).catch(unrecorded);\n let runRows: LsRow[];\n try {\n runRows = await (act === 'start'\n ? startApps(ctx, r.apps, {\n reload: opts.reload,\n waitDep,\n depsOf,\n waits: opts.waits,\n failed: notStarted,\n signal: opts.signal,\n })\n : act === 'restart'\n ? restartApps(ctx, r.apps)\n : act === 'stop'\n ? stopApps(ctx, r.apps)\n : deleteApps(ctx, r.apps));\n } catch (e) {\n if (admitted) await freeOnFailure(gate.store, admitted, e);\n throw e;\n }\n // the start went through: from now on the watcher may judge the lease by its apps\n if (admitted)\n await endFastStart(gate.store, admitted).catch(() => {\n /* bookkeeping only: the apps run; the lease still names this process as its starter, which is trusted for at\n most ten minutes from its start (starterAlive), so until then a stop leaves it running, and after that a\n stop or the watcher frees it */\n });\n // a checkout with no live lease skips pm2's list and the lock\n if (stopping)\n try {\n if (liveLeasesOf(gate.store, ctx).length > 0)\n await freeAfter(gate.store, ctx, await ctx.pm2.jlist());\n } catch (e) {\n unrecorded(e);\n }\n const note = leaseNotes[0];\n rows.push(...(note ? runRows.map((x) => ({ ...x, note })) : runRows));\n done++;\n } catch (e) {\n failed ??= { host: r.host, error: e };\n rows.push(...failedRows(fleet, r, e));\n }\n }\n if (failed && done === 0) throw failed.error;\n // the watcher's start ends its lease once, over every local row (two local runs around a remote one included)\n const local = rows.filter((r) => pickHost(fleet.manifest, r.host).local);\n if (act === 'start' && opts.lease && local.length > 0)\n await finishLeasedStart(gate.store, opts.lease, local);\n return rows;\n}\n\nexport interface HostProbe extends HostApps {\n ctx?: Context;\n snap?: Snapshot;\n error?: unknown;\n}\nexport interface HostError {\n host: string;\n apps: string[];\n message: string;\n}\n\n/** One probe per host, all hosts in parallel; a host that fails carries its error instead of a snapshot. */\nexport function probeFleet(\n fleet: Fleet,\n names: string[],\n take: (ctx: Context) => Promise<Snapshot>\n): Promise<HostProbe[]> {\n return Promise.all(\n fleet.groups(names).map(async (g): Promise<HostProbe> => {\n try {\n const ctx = await fleet.ctx(g.host);\n return { ...g, ctx, snap: await take(ctx) };\n } catch (e) {\n return { ...g, error: e };\n }\n })\n );\n}\n\n/**\n * Rows of the named apps in their order, each from its own host. A host that does not answer leaves unreachable rows,\n * unless none answers. Only the named apps' urls are asked, unless `opts.urls` says otherwise.\n */\nexport async function listFleet(\n fleet: Fleet,\n names: string[],\n opts: SnapshotOptions = {}\n): Promise<{ rows: LsRow[]; errors: HostError[]; probes: HostProbe[] }> {\n const probes = await probeFleet(fleet, names, (ctx) =>\n snapshot(ctx, { urls: names, ...opts })\n );\n const failed = probes.filter((p) => p.error !== undefined);\n if (failed.length === probes.length && failed.length > 0)\n throw failed[0].error;\n const byApp = new Map<string, LsRow>();\n for (const p of probes) {\n const rows = p.snap\n ? rowsFor(p.ctx!, p.snap, p.apps)\n : p.apps.map((a) =>\n unreachableRow(fleet.manifest.apps[a], p.host, describeError(p.error))\n );\n for (const r of rows) byApp.set(r.app, r);\n }\n return {\n rows: names.map((n) => byApp.get(n)!),\n errors: failed.map((p) => ({\n host: p.host,\n apps: p.apps,\n message: describeError(p.error),\n })),\n probes,\n };\n}\n\n/**\n * One app in detail, read on its host. The manifest entry is the full one (the host's view drops dependencies that run\n * elsewhere), with its dependencies in the shape the project summary uses.\n */\nexport async function describeFleetApp(fleet: Fleet, app: string) {\n const host = fleet.one(app);\n const d = await describeApp(await fleet.ctx(host), app);\n const full = fleet.manifest.apps[app];\n return {\n ...d,\n app: { ...full, depends_on: full.depends_on.map(depView) },\n host,\n };\n}\n","import { spawn } from 'node:child_process';\nimport { describeError, McprocError } from './errors.js';\nimport { admit, needOf, rampingMib, reserveMib } from './leases/admission.js';\nimport { ensureWatcher } from './leases/ensure.js';\nimport { LeaseStore, type Lease, type NewLease } from './leases/store.js';\nimport type { Host } from './manifest.js';\nimport { readHostMemory, type HostMemory } from './memory.js';\nimport type { Context } from './resolve.js';\nimport { stateDir } from './state.js';\nimport { abortableSleep } from './wait.js';\n\n/** How long an exec waits in the queue when the caller names no timeout, in milliseconds: ten minutes. */\nexport const EXEC_TIMEOUT_DEFAULT_MS = 600_000;\n/** The longest an exec may wait in the queue, in milliseconds: an hour. */\nexport const EXEC_TIMEOUT_MAX_MS = 3_600_000;\nconst POLL_MS = 1000;\nconst OUTPUT_LINES = 200;\n/** How long the captured pipes are read after the command exited, in milliseconds: something it left behind may hold them. */\nconst DRAIN_MS = 1000;\n\n/** What an exec reads and runs: the lease store, the host's memory, the watcher, the command itself, its sleep and clock. */\nexport interface ExecDeps {\n store: LeaseStore;\n /** the host's memory reading, or null where it has none */\n memory(ctx: Context): Promise<HostMemory | null>;\n /** makes sure the watcher runs once the exec's lease is pending */\n ensureWatcher(ctx: Context): Promise<unknown>;\n /** runs the command to its end and answers its exit code and, when captured, its last lines */\n run(\n command: string[],\n opts: {\n cwd: string;\n env: Record<string, string>;\n capture: boolean;\n signal?: AbortSignal;\n }\n ): Promise<{ code: number; output: string }>;\n sleep(ms: number, signal?: AbortSignal): Promise<void>;\n now(): number;\n /** the requester's pid kept on the lease; default this process */\n pid?: number;\n}\n/** One exec: the command as argv, what it needs in memory (no lease without it), a note, the queue timeout and the abort. */\nexport interface ExecOptions {\n command: string[];\n memoryMib?: number;\n note?: string;\n timeoutMs?: number;\n /** capture the last lines for the answer (MCP); false inherits the terminal (CLI) */\n capture: boolean;\n signal?: AbortSignal;\n}\n/** What an exec ended with: the exit code, the captured tail, its lease as it ended, how long it queued and the env it added. */\nexport interface ExecResult {\n code: number;\n output: string;\n lease: Lease | null;\n waited_ms: number;\n env: Record<string, string>;\n}\n\n/** Refuses a host exec cannot run on: another machine (BAD_ARGUMENT), or a local host marked readonly (READONLY_HOST). */\nexport function assertExecHost(host: Host): void {\n if (!host.local)\n throw new McprocError(\n 'BAD_ARGUMENT',\n `exec runs on the local host only, not on ${host.name}`,\n { hint: 'Drop --host; the command runs where mcproc runs.' }\n );\n if (host.readonly)\n throw new McprocError(\n 'READONLY_HOST',\n 'the local host is marked readonly: exec is refused'\n );\n}\n\n/** Keeps the last OUTPUT_LINES whole lines of a child's streams, each stream's unfinished line held apart until it ends. */\nclass Tail {\n private readonly lines: string[] = [];\n private readonly open = new Map<string, string>();\n /** Takes a chunk of one stream: its finished lines join the tail, its unfinished end waits for the next chunk. */\n take(stream: string, chunk: Buffer): void {\n const parts = ((this.open.get(stream) ?? '') + chunk.toString()).split(\n '\\n'\n );\n this.open.set(stream, parts.pop() ?? '');\n this.lines.push(...parts);\n if (this.lines.length > OUTPUT_LINES * 2)\n this.lines.splice(0, this.lines.length - OUTPUT_LINES);\n }\n /** The last lines, the unfinished end of each stream counted as a line of its own. */\n text(): string {\n const ends = [...this.open.values()].filter((s) => s !== '');\n return [...this.lines, ...ends].slice(-OUTPUT_LINES).join('\\n');\n }\n}\n\n/**\n * The command as a child with the shell left out: argv as given, cwd the project root; captured output keeps its last\n * lines. Not captured, it inherits the terminal; `stdoutToStderr` puts its stdout on the terminal's stderr too. It\n * answers once the command exited and its pipes closed, or DRAIN_MS after the exit when a process it left behind (a\n * server in the background) still holds them: the pipes are then closed and the tail is what was read by then.\n */\nexport function spawnRun(\n command: string[],\n opts: {\n cwd: string;\n env: Record<string, string>;\n capture: boolean;\n stdoutToStderr?: boolean;\n signal?: AbortSignal;\n }\n): Promise<{ code: number; output: string }> {\n return new Promise((resolve, reject) => {\n const child = spawn(command[0], command.slice(1), {\n cwd: opts.cwd,\n env: { ...process.env, ...opts.env },\n stdio: opts.capture\n ? ['ignore', 'pipe', 'pipe']\n : opts.stdoutToStderr\n ? ['inherit', 2, 2]\n : 'inherit',\n });\n const tail = new Tail();\n child.stdout?.on('data', (c: Buffer) => tail.take('out', c));\n child.stderr?.on('data', (c: Buffer) => tail.take('err', c));\n const onAbort = () => child.kill('SIGTERM');\n if (opts.signal?.aborted) onAbort();\n else opts.signal?.addEventListener('abort', onAbort, { once: true });\n let exit: { code: number | null; signal: NodeJS.Signals | null } | null =\n null;\n let drain: NodeJS.Timeout | undefined;\n let settled = false;\n const settle = () => {\n settled = true;\n clearTimeout(drain);\n opts.signal?.removeEventListener('abort', onAbort);\n };\n const finish = () => {\n if (settled || !exit) return;\n settle();\n // stop reading: whatever still holds the pipes keeps them without us\n child.stdout?.destroy();\n child.stderr?.destroy();\n resolve({\n code: exit.code ?? (exit.signal ? 128 : 1),\n output: tail.text(),\n });\n };\n child.on('error', (e) => {\n if (settled) return;\n settle();\n reject(\n new McprocError(\n 'BAD_ARGUMENT',\n `exec cannot run ${command[0]}: ${e.message}`,\n {\n hint: 'The command is run as argv without a shell: name a program on PATH or give its path.',\n }\n )\n );\n });\n // the exit, then the pipes read to their end (close), for at most DRAIN_MS\n child.on('exit', (code, signal) => {\n if (settled) return;\n exit = { code, signal };\n drain = setTimeout(finish, DRAIN_MS);\n });\n child.on('close', finish);\n });\n}\n\n/** The real deps: the host state directory's leases, the host's meminfo, the pm2 watcher, a child without a shell, the real clock. */\nexport function defaultExecDeps(dir = stateDir()): ExecDeps {\n return {\n store: new LeaseStore(dir),\n memory: (ctx) => readHostMemory(ctx.transport, ctx.host),\n ensureWatcher: (ctx) => ensureWatcher(ctx, dir),\n run: spawnRun,\n sleep: abortableSleep,\n now: () => Date.now(),\n };\n}\n\n/** Under the lock, cancels the lease while it still waits (pending or starting); one that ended meanwhile is left as it is. */\nasync function cancelWaiting(\n store: LeaseStore,\n id: string,\n error: string\n): Promise<void> {\n await store\n .withLock(async () => {\n const cur = store.get(id);\n if (cur?.state === 'pending' || cur?.state === 'starting')\n await store.transition(id, 'cancelled', { error });\n })\n .catch(() => undefined);\n}\n\n/**\n * Polls the queued lease until the watcher marks it starting, then takes it to running; a lease that was cancelled or\n * failed meanwhile ends the exec (NOT_STARTED), as do the deadline (TIMEOUT) and the signal (NOT_STARTED).\n */\nasync function waitTurn(\n id: string,\n t0: number,\n opts: ExecOptions,\n deps: ExecDeps\n): Promise<Lease> {\n const timeoutMs = Math.min(\n opts.timeoutMs ?? EXEC_TIMEOUT_DEFAULT_MS,\n EXEC_TIMEOUT_MAX_MS\n );\n const deadline = t0 + timeoutMs;\n for (;;) {\n const cur = deps.store.get(id);\n if (!cur || cur.state === 'cancelled' || cur.state === 'failed')\n throw new McprocError(\n 'NOT_STARTED',\n `exec: the lease was ${cur?.state ?? 'removed'}${cur?.error ? ` (${cur.error})` : ''}`\n );\n if (cur.state === 'starting')\n return deps.store.withLock(() => deps.store.transition(id, 'running'));\n if (deps.now() >= deadline)\n throw new McprocError(\n 'TIMEOUT',\n `exec waited ${timeoutMs / 1000} s in the queue (${cur.waiting_for ?? 'pending'})`,\n {\n hint: 'leases shows the queue; raise --timeout, or free memory by stopping a stand.',\n }\n );\n if (opts.signal?.aborted)\n throw new McprocError('NOT_STARTED', 'exec aborted while queued');\n await deps.sleep(POLL_MS, opts.signal);\n }\n}\n\n/**\n * One-off work in the stand's environment (`exec.env`, interpolated, plus MCPROC_PROJECT) from the project root, on\n * the local host only. With a memory size it is a lease like a start: run at once when the queue is empty and the\n * host has room (the running leases that have not settled yet charged on top of the reading), else queued behind the\n * others until the watcher marks it starting; the lease is freed with the exit code. A wait that ends without a turn\n * (the timeout, the signal, a watcher that cannot be launched) cancels the lease and fails.\n */\nexport async function runExec(\n ctx: Context,\n opts: ExecOptions,\n deps: ExecDeps\n): Promise<ExecResult> {\n const m = ctx.manifest;\n assertExecHost(ctx.host);\n if (opts.command.length === 0)\n throw new McprocError('BAD_ARGUMENT', 'exec needs a command after --');\n const env = { ...m.exec.env, MCPROC_PROJECT: m.root };\n const t0 = deps.now();\n let lease: Lease | null = null;\n if (opts.memoryMib !== undefined) {\n const memory = await deps.memory(ctx);\n const need_mib = needOf(opts.memoryMib, m.resources.margin);\n const reserve_mib = reserveMib(m.resources.reserve, memory);\n const input: NewLease = {\n kind: 'exec',\n project: m.project,\n root: m.root,\n slot: m.slot,\n repo: m.repo,\n target: opts.command.join(' '),\n host: null,\n apps: [],\n reload: false,\n estimate_mib: opts.memoryMib,\n need_mib,\n margin: m.resources.margin,\n reserve_mib,\n sources: {},\n note: opts.note ?? null,\n requester_pid: deps.pid ?? process.pid,\n };\n const taken = await deps.store.withLock(async () => {\n const all = deps.store.list();\n const ahead = all.filter(\n (l) => l.state === 'pending' || l.state === 'starting'\n ).length;\n // a stand admitted seconds ago is not in the reading yet: an exec must not be admitted on what it will take\n const ramping_mib = rampingMib(\n all,\n deps.now(),\n m.resources.settle * 1000\n );\n const d = admit({ ahead, memory, need_mib, reserve_mib, ramping_mib });\n if (!d.ok && d.reason === 'never')\n throw new McprocError('NEVER_FITS', `exec: ${d.waiting_for}`, {\n hint: 'Lower --memory or the resources.reserve.',\n });\n // the exec process itself is the requester: no child pid, the watcher's stuck rule reads requester_pid\n if (d.ok) return deps.store.create(input, 'running');\n const l = await deps.store.create(input, 'pending');\n return deps.store.patch(l.id, { waiting_for: d.waiting_for });\n });\n lease = taken;\n if (taken.state === 'pending') {\n // outside the lock: the launch takes the lock itself\n try {\n await deps.ensureWatcher(ctx);\n lease = await waitTurn(taken.id, t0, opts, deps);\n } catch (e) {\n await cancelWaiting(deps.store, taken.id, describeError(e));\n throw e;\n }\n }\n }\n const waited_ms = deps.now() - t0;\n const id = lease?.id;\n try {\n const r = await deps.run(opts.command, {\n cwd: m.root,\n env,\n capture: opts.capture,\n signal: opts.signal,\n });\n if (id)\n await deps.store\n .withLock(() =>\n deps.store.transition(id, 'freed', { exit_code: r.code })\n )\n .catch(() => undefined);\n return {\n ...r,\n lease: id ? deps.store.get(id) : null,\n waited_ms,\n env,\n };\n } catch (e) {\n if (id)\n await deps.store\n .withLock(() =>\n deps.store.transition(id, 'freed', { error: describeError(e) })\n )\n .catch(() => undefined);\n throw e;\n }\n}\n","import { execFile } from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { describeError, describeErrorWithHint, McprocError } from './errors.js';\nimport { spawnRun } from './exec.js';\nimport { actOn, Fleet, type Connector } from './fleet.js';\nimport { ownsManifest } from './leases/siblings.js';\nimport { LeaseStore } from './leases/store.js';\nimport {\n loadManifest,\n MANIFEST_REL,\n type Manifest,\n type VarInfo,\n} from './manifest.js';\nimport { NAME_RE } from './names.js';\nimport { loadOverride, writeOverride } from './override.js';\nimport { isRunning, type Pm2Process } from './pm2.js';\nimport type { Context } from './resolve.js';\nimport {\n claimSlot,\n emptyRegistry,\n readRegistry,\n realOf,\n reclaimGone,\n registryPath,\n releaseSlot,\n withMain,\n writeRegistry,\n type Registry,\n} from './slots.js';\nimport { stateDir } from './state.js';\nimport { shq } from '../transport/quote.js';\n\n/** Runs git with these arguments in `cwd` and answers its exit code and output; it never throws. */\nexport type GitRunner = (\n args: string[],\n cwd: string\n) => Promise<{ code: number; stdout: string; stderr: string }>;\n\n/** git as a child process, never through a shell. */\nexport const gitRunner: GitRunner = (args, cwd) =>\n new Promise((resolve) => {\n execFile(\n 'git',\n args,\n { cwd, maxBuffer: 8 * 1024 * 1024 },\n (err, stdout, stderr) =>\n resolve({\n // execFile puts the exit status in err.code; a git that cannot be spawned has a string code there\n code: err ? (typeof err.code === 'number' ? err.code : 1) : 0,\n stdout: String(stdout),\n stderr: String(stderr) || (err ? err.message : ''),\n })\n );\n });\n\nconst gitOk = async (\n git: GitRunner,\n args: string[],\n cwd: string\n): Promise<string> => {\n const r = await git(args, cwd);\n if (r.code !== 0)\n throw new McprocError(\n 'TRANSPORT_FAILED',\n `git ${args[0]} failed: ${r.stderr.trim() || r.stdout.trim()}`\n );\n return r.stdout;\n};\n\n/** Whether anything is at `p`, a dangling symlink included. */\nconst present = (p: string): boolean => {\n try {\n fs.lstatSync(p);\n return true;\n } catch {\n return false;\n }\n};\n\n/** The main checkout of the repository `root` belongs to: the parent of git's common dir, real path. */\nexport async function mainCheckout(\n root: string,\n git: GitRunner\n): Promise<string> {\n const common = (\n await gitOk(git, ['rev-parse', '--git-common-dir'], root)\n ).trim();\n return fs.realpathSync(path.dirname(path.resolve(root, common)));\n}\n\n/** Where worktrees go: the manifest's `worktree.dir` resolved from the main checkout, else `<main>.worktrees`. */\nexport function worktreeDir(m: Manifest, main: string): string {\n return m.worktree.dir\n ? path.resolve(main, m.worktree.dir)\n : `${main}.worktrees`;\n}\n\n/** The install command of a fresh worktree: as declared, none when `false`, else by the lockfile; null when there is none to detect. */\nexport function installCommand(m: Manifest, root: string): string | null {\n if (m.worktree.install === false) return null;\n if (typeof m.worktree.install === 'string') return m.worktree.install;\n const has = (f: string) => fs.existsSync(path.join(root, f));\n if (has('bun.lock') || has('bun.lockb')) return 'bun install';\n if (has('yarn.lock')) return 'yarn install';\n if (has('pnpm-lock.yaml')) return 'pnpm install';\n if (has('package-lock.json')) return 'npm install';\n return null;\n}\n\n/** What `copy` and `link` mean for one target: each entry a path or a glob relative to the main checkout. */\nexport function planCopies(\n main: string,\n target: string,\n copy: string[],\n link: string[],\n fsDeps: {\n exists?: (p: string) => boolean;\n glob?: (pattern: string, cwd: string) => string[];\n } = {}\n): {\n copies: { from: string; to: string }[];\n links: { from: string; to: string }[];\n missing: string[];\n} {\n const exists = fsDeps.exists ?? ((p) => fs.existsSync(p));\n const glob = fsDeps.glob ?? ((pattern, cwd) => fs.globSync(pattern, { cwd }));\n const copies: { from: string; to: string }[] = [];\n const missing: string[] = [];\n for (const entry of copy) {\n const hits = /[*?[]/.test(entry)\n ? glob(entry, main).sort()\n : exists(path.join(main, entry))\n ? [entry]\n : [];\n if (hits.length === 0) {\n missing.push(entry);\n continue;\n }\n for (const h of hits)\n copies.push({ from: path.join(main, h), to: path.join(target, h) });\n }\n const links = link.map((l) => ({\n from: path.join(main, l),\n to: path.join(target, l),\n }));\n return { copies, links, missing };\n}\n\n/** What the worktree commands reach outside their arguments: git, the state directory, the install, pm2; tests pass fakes. */\nexport interface WorktreeDeps {\n git: GitRunner;\n stateDir: string;\n /** runs the install command in the worktree; its exit code */\n run(cmd: string, cwd: string): Promise<number>;\n log(line: string): void;\n jlist(): Promise<Pm2Process[]>;\n /** stops and deletes every app of a checkout; the names it stopped; with `force` a manifest that does not load is noted, not refused */\n stopAll(root: string, opts: { force: boolean }): Promise<string[]>;\n exists?(p: string): boolean;\n glob?(pattern: string, cwd: string): string[];\n}\n/** What `worktree add` made: the checkout, its branch, slot and project slug, what it copied, linked and installed, its vars and how to go on. */\nexport interface WorktreeAdded {\n path: string;\n branch: string;\n created_branch: boolean;\n slot: number;\n project: string;\n repo: string;\n /** whose manifest decided the slot var, the copies and the install: the new worktree's own, or the main checkout's when the worktree has none that loads */\n manifest: 'worktree' | 'main';\n copied: string[];\n linked: string[];\n /** the copy and link entries that came from the main checkout's override, not from a manifest */\n from_override: string[];\n /** the links as root-anchored patterns written to git's exclude file of the repository */\n excluded: string[];\n missing: string[];\n installed: string | null;\n vars: VarInfo[];\n next: string;\n}\n\n/** The new worktree's own manifest, or null when it has none of its own or it does not load (logged, with what the main checkout's decides instead). */\nfunction ownManifest(\n target: string,\n log: (line: string) => void,\n instead: string\n): Manifest | null {\n if (!ownsManifest(target)) return null;\n try {\n return loadManifest(target);\n } catch (e) {\n log(\n `the manifest of ${target} does not load (${describeErrorWithHint(e)}): the main checkout's decides ${instead}`\n );\n return null;\n }\n}\n\n/**\n * A path relative to the checkout root as a gitignore pattern that matches exactly it: root-anchored, forward slashes,\n * `./` and doubled slashes folded, the wildcard characters and a trailing space escaped. Null for a path outside the root.\n */\nexport function excludePattern(rel: string): string | null {\n // a trailing slash would make the pattern match directories only, and a symlink is not one to git\n const p = path.posix\n .normalize(rel.split(path.sep).join('/'))\n .replace(/\\/+$/, '');\n if (\n p === '.' ||\n p === '' ||\n p === '..' ||\n p.startsWith('../') ||\n p.startsWith('/')\n )\n return null;\n return `/${p.replace(/[\\\\*?[\\]]/g, (c) => `\\\\${c}`).replace(/ $/, '\\\\ ')}`;\n}\n\n/**\n * Writes each link as a root-anchored pattern into git's exclude file of the repository (`git rev-parse --git-path\n * info/exclude`: shared by its worktrees, never tracked), once each; answers the patterns. A git that cannot name the file\n * is logged, and the links stay visible to `git status`.\n */\nasync function excludeLinks(\n target: string,\n links: string[],\n git: GitRunner,\n log: (line: string) => void\n): Promise<string[]> {\n if (!links.length) return [];\n const patterns: string[] = [];\n for (const l of links) {\n const p = excludePattern(l);\n if (p === null)\n log(\n `link ${l} is outside the checkout: not written to git's exclude file`\n );\n else if (!patterns.includes(p)) patterns.push(p);\n }\n if (!patterns.length) return [];\n const r = await git(['rev-parse', '--git-path', 'info/exclude'], target);\n if (r.code !== 0) {\n log(\n `git names no exclude file for ${target} (${r.stderr.trim()}): the links stay visible to git status`\n );\n return [];\n }\n const file = path.resolve(target, r.stdout.trim());\n fs.mkdirSync(path.dirname(file), { recursive: true });\n const had = fs.existsSync(file) ? fs.readFileSync(file, 'utf8') : '';\n const lines = new Set(had.split('\\n'));\n const add = patterns.filter((p) => !lines.has(p));\n if (add.length)\n fs.appendFileSync(\n file,\n `${had.length && !had.endsWith('\\n') ? '\\n' : ''}${add.join('\\n')}\\n`\n );\n return patterns;\n}\n\n/**\n * The registry of the repository as it stands: slot 0 set to the main checkout, the slots whose checkout is gone\n * dropped (each one logged). Called under the host's lease lock whenever the result is written back.\n */\nfunction registryFor(\n m: Manifest,\n main: string,\n mainBranch: string | null,\n deps: WorktreeDeps\n): { file: string; registry: Registry } {\n const file = registryPath(deps.stateDir, m.base_project, main);\n const read = withMain(readRegistry(file) ?? emptyRegistry(main), {\n path: main,\n branch: mainBranch,\n project: m.base_project,\n });\n const { registry, freed } = reclaimGone(\n read,\n deps.exists ?? ((p) => fs.existsSync(p))\n );\n for (const s of freed) deps.log(`slot ${s} reclaimed: its checkout is gone`);\n return { file, registry };\n}\n\n/** The registry as it stands, written back under the host's lease lock: slot 0 and the reclaimed slots persist. */\nfunction settleRegistry(\n m: Manifest,\n main: string,\n mainBranch: string | null,\n deps: WorktreeDeps\n): Promise<Registry> {\n return new LeaseStore(deps.stateDir).withLock(() => {\n const { file, registry } = registryFor(m, main, mainBranch, deps);\n writeRegistry(file, registry);\n return registry;\n });\n}\n\n/** The branch checked out at `root`, or null when its HEAD is detached. */\nasync function currentBranch(\n root: string,\n git: GitRunner\n): Promise<string | null> {\n const r = await git(['branch', '--show-current'], root);\n return r.code === 0 ? r.stdout.trim() || null : null;\n}\n\n/** `git worktree list --porcelain` as real path → branch (null when detached). */\nasync function worktreeList(\n main: string,\n git: GitRunner\n): Promise<Map<string, string | null>> {\n const out = new Map<string, string | null>();\n let cur: string | null = null;\n for (const line of (\n await gitOk(git, ['worktree', 'list', '--porcelain'], main)\n ).split('\\n')) {\n if (line.startsWith('worktree ')) {\n cur = realOf(line.slice(9));\n out.set(cur, null);\n } else if (line.startsWith('branch ') && cur)\n out.set(cur, line.slice(7).replace(/^refs\\/heads\\//, ''));\n }\n return out;\n}\n\n/** The real path of `p` as far as it exists, the rest joined as given: a folder about to be made gets its real path. */\nfunction realAhead(p: string): string {\n const rest: string[] = [];\n let d = path.resolve(p);\n while (!present(d) && path.dirname(d) !== d) {\n rest.unshift(path.basename(d));\n d = path.dirname(d);\n }\n return path.join(realOf(d), ...rest);\n}\n\n/** A path as a shell word: bare when it needs no quoting. */\nconst shPath = (p: string): string => (/^[\\w./@%+:-]+$/.test(p) ? p : shq(p));\n\n/**\n * A worktree of this repository on `branch` (made from `from`, default the main checkout's HEAD, when the branch is\n * new) in the sibling folder, with the declared copies and links, the override that gives it its slot and project\n * slug, the install, and its slot in the registry. The slot is claimed and the folder made under the host's lease\n * lock, so parallel runs never share a slot; when git then fails, the slot is given back.\n */\nexport async function worktreeAdd(\n m: Manifest,\n opts: {\n branch: string;\n from?: string;\n slot?: number;\n project?: string;\n install: boolean;\n },\n deps: WorktreeDeps\n): Promise<WorktreeAdded> {\n if (opts.slot !== undefined && !Number.isInteger(opts.slot))\n throw new McprocError(\n 'BAD_ARGUMENT',\n `slot must be a whole number, not ${opts.slot}`\n );\n if (opts.project !== undefined && !NAME_RE.test(opts.project))\n throw new McprocError(\n 'BAD_ARGUMENT',\n `project slug \"${opts.project}\" must match ${NAME_RE.source}`\n );\n // the branch names the folder: a name git refuses never reaches the filesystem. No `--` here: check-ref-format\n // refuses one, and `--branch` takes the next argument as the name whatever it looks like (`-x` is refused as a name)\n if (\n (await deps.git(['check-ref-format', '--branch', opts.branch], m.root))\n .code !== 0\n )\n throw new McprocError(\n 'BAD_ARGUMENT',\n `\"${opts.branch}\" is not a valid branch name`\n );\n const main = await mainCheckout(m.root, deps.git);\n // the main checkout's own override may add copy and link entries for every new worktree; a bad one refuses here,\n // before anything is made\n const extras = loadOverride(main)?.worktree ?? { copy: [], link: [] };\n const prefix = (\n await gitOk(deps.git, ['rev-parse', '--show-prefix'], m.root)\n ).trim();\n if (prefix)\n throw new McprocError(\n 'BAD_ARGUMENT',\n `worktree add needs the manifest at the top of its checkout; ${m.root} is ${prefix} inside it`\n );\n for (const [p, b] of await worktreeList(main, deps.git))\n if (b === opts.branch)\n throw new McprocError(\n 'WORKTREE_EXISTS',\n `branch ${opts.branch} is already checked out at ${p}`,\n {\n hint: present(p)\n ? 'Use that checkout, or remove it with worktree remove.'\n : 'That folder is gone: `git worktree prune` makes git forget it.',\n }\n );\n const target = realAhead(\n path.join(worktreeDir(m, main), ...opts.branch.split('/'))\n );\n const taken = () =>\n new McprocError('WORKTREE_EXISTS', `${target} exists already`, {\n hint: 'Remove it, or pick another branch name.',\n });\n if (present(target)) throw taken();\n const mainBranch = await currentBranch(main, deps.git);\n const store = new LeaseStore(deps.stateDir);\n const { file, slot, project } = await store.withLock(() => {\n const { file, registry } = registryFor(m, main, mainBranch, deps);\n const claimed = claimSlot(registry, {\n max: m.worktree.slots,\n want: opts.slot,\n entry: { path: target, branch: opts.branch, project: '' },\n });\n const project = opts.project ?? `${m.base_project}-w${claimed.slot}`;\n for (const [k, e] of Object.entries(registry.slots))\n if (e.project === project)\n throw new McprocError(\n 'BAD_ARGUMENT',\n `project slug ${project} is the slug of slot ${k} (${e.path})`,\n { hint: 'Pass another project slug.' }\n );\n // the folder is made here: a parallel add sees it, and a reclaim never takes a slot whose folder is still empty\n fs.mkdirSync(path.dirname(target), { recursive: true });\n try {\n fs.mkdirSync(target);\n } catch (e) {\n if ((e as NodeJS.ErrnoException).code === 'EEXIST') throw taken();\n throw e;\n }\n writeRegistry(file, {\n ...claimed.registry,\n slots: {\n ...claimed.registry.slots,\n [claimed.slot]: { path: target, branch: opts.branch, project },\n },\n });\n return { file, slot: claimed.slot, project };\n });\n const exists =\n (\n await deps.git(\n ['show-ref', '--verify', '--quiet', '--', `refs/heads/${opts.branch}`],\n main\n )\n ).code === 0;\n try {\n await gitOk(\n deps.git,\n // `--` before the positionals: a `from` such as `--no-checkout` is a ref git refuses, never an option\n exists\n ? ['worktree', 'add', '--', target, opts.branch]\n : [\n 'worktree',\n 'add',\n '-b',\n opts.branch,\n '--',\n target,\n opts.from ?? 'HEAD',\n ],\n main\n );\n } catch (e) {\n try {\n fs.rmdirSync(target); // only while empty: whatever git left stays for a look\n } catch {}\n await store.withLock(() => {\n const r = readRegistry(file);\n if (r?.slots[String(slot)]?.path === target)\n writeRegistry(file, releaseSlot(r, slot));\n });\n throw e;\n }\n // the new worktree's own manifest says what it gets (a branch that introduces the slot scheme gets it from its first\n // worktree); the main checkout's only when the worktree has none that loads. It is read first without the override,\n // only to learn whether it declares `slot`, and again once the override is in place, so that its templates (an\n // install command, a copy entry) see this checkout's slug and slot, as every later command does\n const probe = ownManifest(\n target,\n deps.log,\n 'the slot var, the copies and the install'\n );\n // the override first: whatever fails after it, the registered checkout never runs under the main's slug and vars\n writeOverride(target, {\n project,\n repo: main,\n vars: (probe ?? m).slot !== null ? { slot } : undefined,\n });\n // a .mcproc/.gitignore of the branch (a whitelist) already hides the override; else one that hides everything here\n const gi = path.join(target, '.mcproc', '.gitignore');\n if (!present(gi)) fs.writeFileSync(gi, '*\\n');\n const own = probe\n ? ownManifest(target, deps.log, 'the copies and the install')\n : null;\n const dm = own ?? m;\n // the override's extras come after the manifest's entries; what both name counts as the manifest's\n const only = (xs: string[], not: string[]) =>\n [...new Set(xs)].filter((e) => !not.includes(e));\n const ownPlan = planCopies(\n main,\n target,\n dm.worktree.copy,\n dm.worktree.link,\n deps\n );\n const extraPlan = planCopies(\n main,\n target,\n only(extras.copy, dm.worktree.copy),\n only(extras.link, dm.worktree.link),\n deps\n );\n // what the override adds beyond the manifest's plan, by target: the rest is the manifest's, whatever named it\n const addedCopies = extraPlan.copies.filter(\n (c) => !ownPlan.copies.some((o) => o.to === c.to)\n );\n const addedLinks = extraPlan.links.filter(\n (l) => !ownPlan.links.some((o) => o.to === l.to)\n );\n const plan = {\n copies: [...ownPlan.copies, ...addedCopies],\n links: [...ownPlan.links, ...addedLinks],\n missing: [...ownPlan.missing, ...extraPlan.missing],\n };\n // provenance after the globs are expanded: the entries the override added, as the copied and linked lists name them\n const fromOverride = [\n ...addedCopies.map((c) => path.relative(main, c.from)),\n ...addedLinks.map((l) => path.relative(main, l.from)),\n ];\n let step = '';\n try {\n for (const c of plan.copies) {\n step = `copying ${c.from}`;\n fs.mkdirSync(path.dirname(c.to), { recursive: true });\n fs.cpSync(c.from, c.to, {\n recursive: true,\n force: false,\n errorOnExist: false,\n });\n }\n for (const l of plan.links) {\n step = `linking ${l.from}`;\n fs.mkdirSync(path.dirname(l.to), { recursive: true });\n if (!present(l.to)) fs.symlinkSync(l.from, l.to);\n }\n } catch (e) {\n throw new McprocError(\n 'BAD_ARGUMENT',\n `worktree ${target} is made (slot ${slot}, project ${project}, its override in place), but ${step} failed: ${(e as Error).message}`,\n {\n hint: \"Clear what is in the way or fix the manifest's worktree: section, then copy it by hand or remove the worktree.\",\n }\n );\n }\n for (const miss of plan.missing)\n deps.log(`copy: ${miss} is not in ${main}, skipped`);\n const excluded = await excludeLinks(\n target,\n plan.links.map((l) => path.relative(target, l.to)),\n deps.git,\n deps.log\n );\n const install = opts.install ? installCommand(dm, target) : null;\n if (install) {\n const code = await deps.run(install, target);\n if (code !== 0)\n deps.log(`${install} exited ${code} in ${target}; run it by hand`);\n }\n let vars: VarInfo[] = [];\n let next = `cd ${shPath(target)}`;\n // the manifest search walks up: without a manifest of its own the checkout would read an enclosing one (the main's)\n if (!ownsManifest(target))\n deps.log(\n `${target} has no manifest of its own (${MANIFEST_REL}): no vars, nothing to start`\n );\n else if (own) {\n // the manifest as read with its override: the vars carry the slot\n vars = own.vars;\n const first = Object.keys(own.profiles)[0] ?? Object.keys(own.apps)[0];\n if (first) next += ` && mcproc start ${first}`;\n }\n return {\n path: target,\n branch: opts.branch,\n created_branch: !exists,\n slot,\n project,\n repo: main,\n manifest: own ? 'worktree' : 'main',\n copied: plan.copies.map((c) => path.relative(main, c.from)),\n linked: plan.links.map((l) => path.relative(main, l.from)),\n from_override: fromOverride,\n excluded,\n missing: plan.missing,\n installed: install,\n vars,\n next,\n };\n}\n\n/** One checkout in the `worktree ls` table: its slot, project slug, path, branch, apps online and lease state. */\nexport interface WorktreeRow {\n slot: number;\n project: string;\n path: string;\n branch: string | null;\n online: number;\n lease: string | null;\n main: boolean;\n}\n\n/**\n * The registry as a table: every checkout with its branch, how many of its apps are online, and its lease state. A read\n * only: a slot whose folder is gone shows `(gone)` as its branch and stays until add or remove reclaims it, and slot 0\n * is shown from the main checkout without being recorded.\n */\nexport async function worktreeLs(\n m: Manifest,\n deps: WorktreeDeps\n): Promise<WorktreeRow[]> {\n const main = await mainCheckout(m.root, deps.git);\n const file = registryPath(deps.stateDir, m.base_project, main);\n // a write is a rename: the file reads whole without the lock\n const registry = withMain(readRegistry(file) ?? emptyRegistry(main), {\n path: main,\n branch: await currentBranch(main, deps.git),\n project: m.base_project,\n });\n const exists = deps.exists ?? ((p: string) => fs.existsSync(p));\n const branches = await worktreeList(main, deps.git);\n const procs = await deps.jlist();\n const leases = new LeaseStore(deps.stateDir).list();\n return Object.entries(registry.slots)\n .map(([k, e]) => ({\n slot: Number(k),\n project: e.project,\n path: e.path,\n branch:\n k !== '0' && !exists(realOf(e.path))\n ? '(gone)'\n : (branches.get(realOf(e.path)) ?? e.branch),\n online: procs.filter(\n (p) => p.namespace === e.project && isRunning(p.status)\n ).length,\n lease:\n leases.find(\n (l) =>\n realOf(l.root) === realOf(e.path) &&\n (l.state === 'pending' ||\n l.state === 'starting' ||\n l.state === 'running')\n )?.state ?? null,\n main: k === '0',\n }))\n .sort((a, b) => a.slot - b.slot);\n}\n\n/** What `worktree remove` did: the checkout it removed, the slot it freed, its branch (kept) and the apps it stopped. */\nexport interface WorktreeRemoved {\n path: string;\n slot: number;\n branch: string | null;\n stopped: string[];\n}\n\n/**\n * Stops the checkout's apps (freeing its leases), removes the worktree and frees its slot; the branch stays. `ref` is\n * a slot number, a path or a branch. Without `force` a checkout with uncommitted or untracked changes is refused.\n */\nexport async function worktreeRemove(\n m: Manifest,\n ref: string,\n opts: { force: boolean },\n deps: WorktreeDeps\n): Promise<WorktreeRemoved> {\n const main = await mainCheckout(m.root, deps.git);\n const registry = await settleRegistry(\n m,\n main,\n await currentBranch(main, deps.git),\n deps\n );\n const hit = Object.entries(registry.slots).find(\n ([k, e]) => k === ref || realOf(e.path) === realOf(ref) || e.branch === ref\n );\n if (!hit)\n throw new McprocError(\n 'NOT_A_WORKTREE',\n `${ref} is no slot, path or branch of ${main}`,\n { hint: 'worktree ls lists them.' }\n );\n const [k, e] = hit;\n if (k === '0')\n throw new McprocError(\n 'BAD_ARGUMENT',\n 'slot 0 is the main checkout; it cannot be removed'\n );\n const file = registryPath(deps.stateDir, m.base_project, main);\n /** frees the slot under the lock, read afresh: only while it still names this checkout */\n const free = () =>\n new LeaseStore(deps.stateDir).withLock(() => {\n const now = readRegistry(file);\n if (now?.slots[k]?.path === e.path)\n writeRegistry(file, releaseSlot(now, Number(k)));\n });\n if (!(await worktreeList(main, deps.git)).has(realOf(e.path))) {\n // an add that ended between its claim and git leaves an empty folder: nothing in it to stop or keep\n let empty = false;\n try {\n empty = fs.readdirSync(e.path).length === 0;\n } catch {}\n if (!empty)\n throw new McprocError(\n 'NOT_A_WORKTREE',\n `${e.path} (slot ${k}) is no git worktree of ${main}`,\n { hint: 'Look at what is in it, remove it by hand, then worktree ls.' }\n );\n fs.rmdirSync(e.path);\n deps.log(`${e.path} was an empty folder git never filled: removed`);\n await free();\n return { path: e.path, slot: Number(k), branch: e.branch, stopped: [] };\n }\n if (!opts.force) {\n const st = await gitOk(deps.git, ['status', '--porcelain'], e.path);\n if (st.trim())\n throw new McprocError(\n 'WORKTREE_DIRTY',\n `${e.path} has uncommitted or untracked changes`,\n { hint: 'Commit or stash them, or pass --force to discard them.' }\n );\n }\n const stopped = await deps.stopAll(e.path, { force: opts.force });\n await gitOk(\n deps.git,\n ['worktree', 'remove', ...(opts.force ? ['--force'] : []), '--', e.path],\n main\n );\n // the folders a branch with slashes made (`feat/` of feat/x) go when they are left empty\n const top = realOf(worktreeDir(m, main));\n for (\n let d = path.dirname(e.path);\n d.startsWith(`${top}${path.sep}`);\n d = path.dirname(d)\n ) {\n try {\n fs.rmdirSync(d);\n } catch {\n break; // not empty\n }\n }\n await free();\n return { path: e.path, slot: Number(k), branch: e.branch, stopped };\n}\n\n/**\n * Stops and deletes the apps of the checkout at `root` that run on writable hosts, and answers their names. A path\n * without a manifest of its own has none: the manifest search walks up, so it would stand for an enclosing project, the\n * main checkout among them. A manifest that does not load is refused, or noted with `force`; an app bound to a readonly\n * host is left alone with a note.\n */\nexport async function stopCheckout(\n root: string,\n opts: { force: boolean; log: (line: string) => void; connector?: Connector }\n): Promise<string[]> {\n if (!ownsManifest(root)) {\n opts.log(`${root} has no manifest of its own: no apps to stop`);\n return [];\n }\n let m: Manifest;\n try {\n m = loadManifest(root);\n } catch (e) {\n if (!opts.force) throw e;\n opts.log(\n `the manifest of ${root} does not load (${describeErrorWithHint(e)}): its apps are not stopped`\n );\n return [];\n }\n const fleet = new Fleet(m, undefined, opts.connector);\n const stopped: string[] = [];\n for (const app of fleet.select(['all'])) {\n const host = fleet.hostOf(app);\n if (m.hosts[host]?.readonly) {\n opts.log(`${app} runs on readonly host ${host}: left alone`);\n continue;\n }\n for (const r of await actOn(fleet, app, 'delete')) stopped.push(r.app);\n }\n return stopped;\n}\n\n/**\n * The deps of the CLI and MCP: real git, the host state directory, the install run through the host's shell, pm2 of\n * this checkout, stop-and-delete of a checkout through stopCheckout. `capture` keeps the install off the terminal (MCP,\n * whose stdin and stdout carry the protocol) and logs its last lines when it fails; without it the install writes to\n * the terminal's stderr (CLI), so stdout carries only mcproc's own answer.\n */\nexport async function defaultWorktreeDeps(\n ctx: Context,\n io: { out: (s: string) => void },\n opts: { capture?: boolean } = {}\n): Promise<WorktreeDeps> {\n return {\n git: gitRunner,\n stateDir: stateDir(),\n run: async (cmd, cwd) => {\n try {\n const r = await spawnRun(\n [ctx.host.shell.bin, ...ctx.host.shell.flags, cmd],\n {\n cwd,\n env: {},\n capture: opts.capture ?? false,\n stdoutToStderr: true,\n }\n );\n if (r.code !== 0 && r.output)\n for (const line of r.output.split('\\n').slice(-20)) io.out(line);\n return r.code;\n } catch (e) {\n io.out(describeError(e));\n return 127;\n }\n },\n log: (line) => io.out(line),\n jlist: () => ctx.pm2.jlist(),\n stopAll: (root, o) =>\n stopCheckout(root, { force: o.force, log: (line) => io.out(line) }),\n };\n}\n","import fs from 'node:fs';\nimport { createHash, randomUUID } from 'node:crypto';\nimport net from 'node:net';\nimport path from 'node:path';\nimport { McprocError } from '../errors.js';\nimport { flushLogs } from '../logs.js';\nimport { assertWritableRuns, type Fleet } from '../fleet.js';\nimport {\n markKey,\n mergeCursor,\n type CursorState,\n type FileMark,\n} from './cursor.js';\nimport {\n pollIncidents,\n type IncidentsAnswer,\n type PollOptions,\n} from './poll.js';\n\n/**\n * The pick-up point of a project, shared by every session, agent and CLI call on this machine: per `host/app` where\n * incidents were last taken (the marks of a poll), when each app's logs were last cleared, and how many clears emptied a\n * file of it (a screen that shows the logs starts over whenever that count moves, even twice within one second).\n */\nexport interface Store extends CursorState {\n cleared: Record<string, string>;\n /**\n * how many clears emptied a file of each host/app, and, under `fileClearKey` keys, how many emptied each file itself:\n * a reader with its own position (the monit incidents view) restarts a file exactly when its count moves, whatever the\n * shared point has done since. Every writer copies this map as it found it, so the counts only ever grow.\n */\n clears: Record<string, number>;\n}\n\n/** The key under which `clears` counts the clears that emptied one file of an app: host/app, stream and path, NUL-separated. */\nexport const fileClearKey = (\n key: string,\n stream: 'out' | 'err',\n path: string\n): string => `${key}\\u0000${stream}\\u0000${path}`;\n\n/**\n * The key under which `clears` counts the clears of an app that also counted its files: an app count that grew more than\n * this one was cleared by an mcproc that counts no files, which could have emptied either of them.\n */\nexport const countedClearKey = (key: string): string => `${key}\\u0000counted`;\n\n/** An app's own count in `clears` (host/app), as opposed to one of the counts kept beside it. */\nexport const isAppClearKey = (k: string): boolean => !k.includes('\\u0000');\n\n/** A `fileClearKey` read back, or null for any other key. */\nexport function parseFileClearKey(\n k: string\n): { key: string; stream: 'out' | 'err'; path: string } | null {\n const [key, stream, ...rest] = k.split('\\u0000');\n if (rest.length === 0 || (stream !== 'out' && stream !== 'err')) return null;\n return { key, stream, path: rest.join('\\u0000') };\n}\nexport interface TakenAnswer extends IncidentsAnswer {\n taken: boolean;\n cleared_at: string | null;\n}\nexport interface Cleared {\n app: string;\n host: string;\n out_bytes: number;\n err_bytes: number;\n failed?: string[];\n}\n\nconst LOCK_WAIT_MS = 30_000;\n\n/** `.mcproc/incidents.json`, next to the manifest. */\nexport const storePath = (manifestPath: string): string =>\n path.join(path.dirname(manifestPath), 'incidents.json');\n\nconst pad = (n: number) => String(n).padStart(2, '0');\n/** Local time of this machine in the shape of pm2's stamps: `YYYY-MM-DDTHH:MM:SS`. */\nexport const localStamp = (d: Date): string =>\n `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;\n\n/** The stored point; a missing, unreadable or foreign file is a fresh start. */\nexport function readStore(file: string): Store {\n try {\n const s = JSON.parse(\n fs.readFileSync(file, 'utf8')\n ) as Partial<Store> | null;\n const obj = <V>(o: Record<string, V> | undefined): Record<string, V> =>\n typeof o === 'object' && o !== null ? o : {};\n if (s && s.v === 1 && typeof s.apps === 'object' && s.apps !== null)\n return {\n v: 1,\n apps: s.apps,\n cleared: obj(s.cleared),\n clears: obj(s.clears),\n };\n } catch {\n /* a fresh start */\n }\n return { v: 1, apps: {}, cleared: {}, clears: {} };\n}\n\n/**\n * The store's lock is a listening socket, which the kernel lets one process hold and frees when that process ends,\n * however it ends: nothing is ever taken over from a holder, so a slow or suspended one never sees a successor write\n * under it. Linux: an abstract socket named after the store; elsewhere a loopback port derived from its path.\n */\nexport function lockAddress(file: string): net.ListenOptions {\n let dir = path.dirname(path.resolve(file));\n try {\n dir = fs.realpathSync(dir);\n } catch {\n /* not there yet: the path as given */\n } // a symlinked project path is the same store\n const id = createHash('sha256')\n .update(path.join(dir, path.basename(file)))\n .digest();\n return process.platform === 'linux'\n ? { path: `\\0mcproc-incidents-${id.toString('hex').slice(0, 32)}` }\n : { host: '127.0.0.1', port: 40000 + (id.readUInt16BE(0) % 9000) };\n}\nfunction tryLock(addr: net.ListenOptions): Promise<net.Server | null> {\n return new Promise((resolve, reject) => {\n const srv = net.createServer((c) => c.destroy()); // the lock is the bound address; a program that connects is let go at once\n srv.once('error', (e: NodeJS.ErrnoException) =>\n e.code === 'EADDRINUSE' ? resolve(null) : reject(e)\n );\n srv.listen(addr, () => {\n srv.unref();\n resolve(srv);\n });\n });\n}\n\n/**\n * Read, change and write back the store while holding its lock, so two callers never take the same incidents: the\n * second waits (up to `waitMs`, then TIMEOUT). The new store replaces the old one in one rename.\n */\nexport async function withStore<T>(\n file: string,\n fn: (s: Store) => Promise<{ result: T; next: Store }>,\n waitMs = LOCK_WAIT_MS\n): Promise<T> {\n const addr = lockAddress(file);\n const until = Date.now() + waitMs;\n let lock = await tryLock(addr);\n while (!lock) {\n if (Date.now() >= until) {\n throw new McprocError(\n 'TIMEOUT',\n 'another mcproc call is taking incidents of this project right now',\n {\n hint: addr.port\n ? `Retry in a moment. The lock is the loopback port ${addr.port}: if a program other than mcproc listens there, stop it.`\n : 'Retry in a moment.',\n }\n );\n }\n await new Promise((r) => setTimeout(r, 100));\n lock = await tryLock(addr);\n }\n try {\n const { result, next } = await fn(readStore(file));\n const tmp = `${file}.${randomUUID()}.tmp`;\n fs.writeFileSync(tmp, JSON.stringify(next));\n fs.renameSync(tmp, file);\n return result;\n } finally {\n await new Promise((r) => lock!.close(r));\n }\n}\n\n/**\n * The new incidents of the named apps. Taking (the default) moves the pick-up point past what it returns, for every\n * caller; `peek` looks without moving it, from `cursor` (a peeking follower's own position) or else the stored point.\n * `next` is the position after this call.\n */\nexport async function takeIncidents(\n fleet: Fleet,\n names: string[],\n opts: PollOptions & { peek?: boolean } = {},\n file = storePath(fleet.manifest.path)\n): Promise<{ answer: TakenAnswer; next: CursorState }> {\n if (opts.peek) {\n const s = readStore(file);\n const base = opts.cursor ?? s;\n const { answer, next } = await pollIncidents(fleet, names, {\n ...opts,\n cursor: base,\n });\n return {\n answer: {\n ...answer,\n taken: false,\n cleared_at: lastClear(fleet, names, s),\n },\n next: mergeCursor(base, next),\n };\n }\n return withStore(file, async (s) => {\n const { answer, next } = await pollIncidents(fleet, names, {\n ...opts,\n cursor: s,\n });\n const stored: Store = {\n ...mergeCursor(s, next),\n cleared: s.cleared,\n clears: s.clears,\n };\n return {\n result: {\n answer: {\n ...answer,\n taken: true,\n cleared_at: lastClear(fleet, names, s),\n },\n next: stored,\n },\n next: stored,\n };\n });\n}\n\n/** The latest clear among the named apps, each at the host it runs on. */\nfunction lastClear(fleet: Fleet, names: string[], s: Store): string | null {\n return (\n fleet\n .groups(names)\n .flatMap((g) => g.apps.map((a) => s.cleared[markKey(g.host, a)] ?? ''))\n .filter(Boolean)\n .sort()\n .at(-1) ?? null\n );\n}\n\n/**\n * Truncate the logs of the named apps (each on the host it runs on; readonly hosts are refused before anything) and\n * start their incidents there: the pick-up point moves to the start of each file the host confirmed empty, with pm2's\n * restart count and status as they are now, and the time of the clear is kept for an app whose files all emptied.\n * Nothing logged before the clear comes up again, and nothing written right after it is missed. A file that could not\n * be truncated keeps its point and is named in `failed`. When a host drops mid-way, what it did is unknown: its apps keep\n * their points, and a file found shorter than its point is read from the start anyway.\n */\nexport async function clearLogs(\n fleet: Fleet,\n names: string[],\n file = storePath(fleet.manifest.path),\n now = new Date()\n): Promise<Cleared[]> {\n const groups = fleet.groups(names);\n assertWritableRuns(fleet, groups);\n let failure: unknown = null;\n const done = await withStore(file, async (s) => {\n const at = localStamp(now);\n const next: Store = {\n v: 1,\n apps: { ...s.apps },\n cleared: { ...s.cleared },\n clears: { ...s.clears },\n };\n const out: Cleared[] = [];\n for (const g of groups) {\n try {\n for (const f of await flushLogs(await fleet.ctx(g.host), g.apps)) {\n const key = markKey(g.host, f.app);\n const prev = s.apps[key];\n // what was taken before the clear stays taken: the stamp goes on with the fresh file\n const mark = (path: string, was: FileMark | undefined) =>\n f.failed.includes(path)\n ? was\n : {\n path,\n offset: 0,\n ...(was?.stamp ? { stamp: was.stamp } : {}),\n };\n next.apps[key] = {\n restarts: f.proc.restarts,\n status: f.proc.status,\n out: mark(f.proc.out_log, prev?.out),\n err: mark(f.proc.err_log, prev?.err),\n ...(prev && 'start' in prev\n ? { start: prev.start, boot: prev.boot }\n : {}), // a clear ends no run: the boot state stays with the start it was taken for\n };\n if (f.failed.length === 0) next.cleared[key] = at;\n if (f.failed.length < 2) {\n next.clears[key] = (s.clears[key] ?? 0) + 1; // a file of it was emptied\n const ck = countedClearKey(key);\n next.clears[ck] = (s.clears[ck] ?? 0) + 1; // ... and this clear says which\n }\n for (const [stream, path] of [\n ['out', f.proc.out_log],\n ['err', f.proc.err_log],\n ] as const) {\n if (f.failed.includes(path)) continue; // this file was not emptied\n const fk = fileClearKey(key, stream, path);\n next.clears[fk] = (s.clears[fk] ?? 0) + 1;\n }\n const freed = (path: string, bytes: number) =>\n f.failed.includes(path) ? 0 : bytes;\n out.push({\n app: f.app,\n host: g.host,\n out_bytes: freed(f.proc.out_log, f.out_bytes),\n err_bytes: freed(f.proc.err_log, f.err_bytes),\n ...(f.failed.length ? { failed: f.failed } : {}),\n });\n }\n } catch (e) {\n failure = e; // what was cleared before stays recorded\n break;\n }\n }\n return { result: out, next };\n });\n if (failure) throw failure;\n return done;\n}\n","import { msStamp } from '../logsince.js';\nimport { markKey, type CursorState } from './cursor.js';\nimport type { Incident, Stream } from './detect.js';\n\n/** How far the takes have read one file: the latest pm2 stamp read (ms), and the file and offset the last take reached. */\nexport interface TakenPoint {\n stamp: string;\n path: string;\n offset: number;\n}\n/**\n * Per `host/app` and stream, how far the takes have read: an incident stamped before the point has been taken. A take\n * records it with the file's position; a peek leaves it as it was, and a clear carries the stamp into the fresh file.\n */\nexport type TakenPoints = Record<string, Partial<Record<Stream, TakenPoint>>>;\n/** Where the read that found an incident ended in its file: what a reader with its own position (monit) knows of it. */\nexport interface ReadEnd {\n path: string;\n offset: number;\n}\n\n/** The taken points of a stored pick-up point; a malformed entry gives none. */\nexport function takenPoints(s: CursorState): TakenPoints {\n const out: TakenPoints = {};\n for (const [key, m] of Object.entries(s.apps ?? {})) {\n const p: Partial<Record<Stream, TakenPoint>> = {};\n for (const stream of ['out', 'err'] as const) {\n const f = (m as unknown as Record<string, unknown> | null)?.[stream] as\n | { stamp?: unknown; path?: unknown; offset?: unknown }\n | undefined;\n if (\n typeof f?.stamp === 'string' &&\n typeof f.path === 'string' &&\n typeof f.offset === 'number'\n )\n p[stream] = { stamp: f.stamp, path: f.path, offset: f.offset };\n }\n if (p.out || p.err) out[key] = p;\n }\n return out;\n}\n\n/**\n * Whether a take has passed the incident. Stamped before the last line a take read in its file: taken (a line written\n * after the take is stamped no earlier). Stamped the same: a line written right after the take can carry that stamp\n * too, so only a read that ended where the take had read up to, in the same file, proves it (`end`). An unstamped\n * incident or a reload never counts as taken.\n */\nexport function isTaken(\n i: Incident,\n points: TakenPoints,\n end?: ReadEnd\n): boolean {\n if (i.kind === 'reloaded' || !i.time) return false;\n const p = points[markKey(i.host, i.app)]?.[i.stream];\n if (!p) return false;\n const t = msStamp(i.time);\n const s = msStamp(p.stamp);\n if (t !== s) return t < s;\n return !!end && end.path === p.path && end.offset <= p.offset;\n}\n\n/** The later of two stamps, normalised to milliseconds; undefined when neither is there. */\nexport function laterStamp(\n a: string | null | undefined,\n b: string | null | undefined\n): string | undefined {\n const x = a ? msStamp(a) : undefined;\n const y = b ? msStamp(b) : undefined;\n if (!x) return y;\n if (!y) return x;\n return x >= y ? x : y;\n}\n","import { describeError, isMcprocError } from '../errors.js';\nimport { findProcess, type Pm2Process } from '../pm2.js';\nimport type { Fleet, HostError } from '../fleet.js';\nimport { ensureOk } from '../../transport/index.js';\nimport { CLOCK_SNIPPET, hostClock, hostStamp } from '../logsince.js';\nimport { laterStamp } from './taken.js';\nimport {\n beforeStart,\n compileReloadRules,\n ReloadTracker,\n type Reload,\n type ReloadInput,\n} from '../reloads.js';\nimport {\n collapse,\n cutContext,\n compileRules,\n detect,\n stampOf,\n type Incident,\n type Stream,\n} from './detect.js';\nimport {\n NOW_SNIPPET,\n hostNow,\n markKey,\n type Anchor,\n parseRead,\n readSnippet,\n windowStart,\n type AppMark,\n type CursorState,\n} from './cursor.js';\n\nexport interface IncidentsAnswer {\n incidents: Incident[];\n skipped: { app: string; host: string; stream: Stream; bytes: number }[];\n errors: HostError[];\n more: number;\n /** why `more` incidents were left out, when any were: past `max`, or past the answer's size budget */\n more_by?: 'max' | 'size';\n apps: number;\n hosts: number;\n latest: string | null;\n /**\n * Only for a caller that passed `restart`: per host/app, the files this poll positioned (read, or left to read again\n * from where it began). A restart of any other file was not applied (its host failed, its app stalled or is not\n * running), so the caller keeps it for its next poll.\n */\n positioned?: Record<string, Stream[]>;\n}\n/**\n * `budgetMs`: how long an app's own patterns may take on one file (default MATCH_BUDGET_MS). `includeReloads`: also\n * report each app's in-process reloads since the last poll, as one `reloaded` incident per app (apps with `reloads`).\n */\nexport interface PollOptions {\n cursor?: CursorState;\n sinceMin?: number;\n max?: number;\n /** the size budget of the answer's incidents, in characters (default ANSWER_CHARS; Infinity for none) */\n chars?: number;\n context?: [number, number];\n budgetMs?: number;\n includeReloads?: boolean;\n /**\n * Files a caller with its own position knows were emptied since it last read them, per host/app and stream: their\n * paths, or `*` for whichever file the stream writes now. The file pm2 writes is read from its start when it is one of\n * them, whatever the cursor says (an old offset would skip a file that regrew past it, and a new path would read only\n * the last minutes).\n */\n restart?: Record<string, Partial<Record<Stream, string[]>>>;\n}\n\n/** How far back a first call looks, in minutes, when it names no window of its own. */\nexport const DEFAULT_SINCE_MIN = 15;\n/**\n * How many characters of incident text an answer carries, newest first: the rest are counted in `more` (and taken\n * with the others), so one burst of huge lines never overflows a client's tool-result limit. One incident always shows.\n */\nexport const ANSWER_CHARS = 20_000;\nconst EVENT_TAIL = 10;\nconst STREAMS: Stream[] = ['out', 'err'];\n\n/** New incidents of the named apps since `cursor`, each app read on its own host (hosts in parallel). */\nexport async function pollIncidents(\n fleet: Fleet,\n names: string[],\n opts: PollOptions = {}\n): Promise<{ answer: IncidentsAnswer; next: CursorState }> {\n const sinceMin = opts.sinceMin ?? DEFAULT_SINCE_MIN;\n const groups = fleet.groups(names);\n const next: CursorState = { v: 1, apps: {} };\n const skipped: IncidentsAnswer['skipped'] = [];\n const results = await Promise.all(\n groups.map(async (g) => {\n try {\n const ctx = await fleet.ctx(g.host);\n const procs = await ctx.pm2.jlist();\n const targets = g.apps.flatMap((app) => {\n const settings = fleet.manifest.apps[app].errors;\n const reloads = opts.includeReloads\n ? fleet.manifest.apps[app].reloads\n : null; // an app takes part for its errors, its reloads, or both\n const p = findProcess(procs, fleet.manifest.project, app);\n return p && (settings || reloads)\n ? [\n {\n app,\n p,\n settings,\n reloads,\n prev: opts.cursor?.apps[markKey(g.host, app)],\n },\n ]\n : [];\n });\n if (targets.length === 0)\n return {\n incidents: [] as Incident[],\n latest: null as string | null,\n stalled: [] as HostError[],\n };\n const files = targets.flatMap((t) =>\n STREAMS.map((stream) => {\n const path = stream === 'out' ? t.p.out_log : t.p.err_log;\n const mark = t.prev?.[stream];\n const same = mark && mark.path === path;\n const emptied = opts.restart?.[markKey(g.host, t.app)]?.[stream];\n const restarted =\n !!emptied && (emptied.includes(path) || emptied.includes('*'));\n const anchor: Anchor | null =\n !restarted &&\n same &&\n mark.at !== undefined &&\n mark.anchor !== undefined\n ? { at: mark.at, hex: mark.anchor }\n : null;\n return {\n t,\n stream,\n path,\n offset: restarted ? 0 : same ? mark.offset : null,\n anchor,\n restarted,\n };\n })\n );\n const res = ensureOk(\n await ctx.transport.exec(\n [\n NOW_SNIPPET,\n ...(opts.includeReloads ? [CLOCK_SNIPPET] : []), // the host's zone puts pm2's start in the stamps' wall time\n ...files.map((f, i) =>\n readSnippet(i, f.path, f.offset, f.anchor)\n ),\n ].join('; ')\n ),\n ctx.host,\n 'read logs for incidents'\n );\n const now = hostNow(res.stdout); // one cutoff for every file of this host: a first call looks back from the host's clock\n const zone = opts.includeReloads\n ? (hostClock(res.stdout)?.zone ?? null)\n : null;\n const incidents: Incident[] = [];\n let latest: string | null = null;\n const perApp = new Map<\n string,\n {\n mark: AppMark;\n errLines: string[];\n newLines: ReloadInput[];\n ctxStamps: string[];\n }\n >();\n const stalled = new Map<string, string>();\n files.forEach((f, i) => {\n const r = parseRead(res.stdout, i, f.offset);\n const entry = perApp.get(f.t.app) ?? {\n mark: { restarts: f.t.p.restarts, status: f.t.p.status },\n errLines: [],\n newLines: [],\n ctxStamps: [],\n };\n perApp.set(f.t.app, entry);\n if (!r) return;\n const was = f.t.prev?.[f.stream]?.stamp; // what earlier takes have read here stays read\n if (r.short) {\n if (f.restarted)\n entry.mark[f.stream] = {\n path: f.path,\n offset: 0,\n ...(was ? { stamp: was } : {}),\n };\n else if (f.t.prev?.[f.stream])\n entry.mark[f.stream] = f.t.prev[f.stream];\n return;\n } // read again next poll from where this one began: nothing analysed, nothing taken\n const stamp = laterStamp(was, lastStamp(r.lines));\n entry.mark[f.stream] = {\n path: f.path,\n offset: r.nextOffset,\n ...(r.anchor ? { at: r.anchor.at, anchor: r.anchor.hex } : {}),\n ...(stamp ? { stamp } : {}),\n };\n if (f.stream === 'err') entry.errLines = r.lines;\n if (r.skipped > 0)\n skipped.push({\n app: f.t.app,\n host: g.host,\n stream: f.stream,\n bytes: r.skipped,\n });\n for (let k = r.lines.length - 1; k >= r.contextOnly; k--) {\n const t = stampOf(r.lines[k]);\n if (t) {\n if (!latest || t > latest) latest = t;\n break;\n }\n }\n const from =\n f.offset === null ? windowStart(r.lines, sinceMin, now) : null; // a first call: only the last minutes, by the host's clock\n const contextOnly = from\n ? Math.max(r.contextOnly, insideFrom(r.lines, from))\n : r.contextOnly;\n if (f.t.reloads) {\n const before = lastStampBefore(r.lines, contextOnly);\n if (before) entry.ctxStamps.push(before);\n for (const text of r.lines.slice(contextOnly))\n entry.newLines.push({ stream: f.stream, text });\n }\n if (!f.t.settings) return; // errors: false, here for its reloads only\n try {\n incidents.push(\n ...detect(\n { stream: f.stream, lines: r.lines, contextOnly },\n compileRules(f.t.settings, opts.context, opts.budgetMs),\n { app: f.t.app, host: g.host }\n )\n );\n } catch (e) {\n if (!isMcprocError(e) || e.code !== 'TIMEOUT') throw e;\n stalled.set(f.t.app, describeError(e)); // its own patterns ran away: this app waits, the others go on\n }\n });\n for (const t of targets) {\n const entry = perApp.get(t.app)!;\n if (t.reloads && !stalled.has(t.app)) {\n const start =\n t.p.started_at !== null && zone\n ? hostStamp(t.p.started_at, zone)\n : null;\n try {\n const tracker = new ReloadTracker(\n compileReloadRules(t.reloads, opts.budgetMs),\n {\n app: t.app,\n start,\n coversStart: bootAhead(start, t.prev, entry.ctxStamps),\n }\n );\n const found = [\n ...tracker.push(entry.newLines, 0),\n ...tracker.flush(),\n ];\n entry.mark.start = start;\n entry.mark.boot = tracker.awaitingBoot; // no burst closed: the boot is still to come\n if (found.length) incidents.push(reloaded(t.app, g.host, found));\n } catch (e) {\n if (!isMcprocError(e) || e.code !== 'TIMEOUT') throw e;\n stalled.set(t.app, describeError(e));\n }\n }\n if (stalled.has(t.app)) continue; // not analysed: its point stays, the next poll reads the same lines again\n next.apps[markKey(g.host, t.app)] = entry.mark;\n if (t.settings)\n incidents.push(\n ...processEvents(t.app, g.host, t.p, t.prev, entry.errLines)\n );\n }\n return {\n incidents: incidents.filter((i) => !stalled.has(i.app)),\n latest,\n stalled: [...stalled].map(([app, message]) => ({\n host: g.host,\n apps: [app],\n message,\n })),\n };\n } catch (e) {\n return {\n error: { host: g.host, apps: g.apps, message: describeError(e) },\n cause: e,\n };\n }\n })\n );\n const failed = results.filter(\n (r): r is { error: HostError; cause: unknown } => 'error' in r\n );\n if (failed.length === results.length && failed.length > 0)\n throw failed[0].cause;\n const ok = results.filter(\n (\n r\n ): r is {\n incidents: Incident[];\n latest: string | null;\n stalled: HostError[];\n } => !('error' in r)\n );\n const all = collapse(ok.flatMap((r) => r.incidents)).sort((a, b) =>\n (b.time ?? '').localeCompare(a.time ?? '')\n );\n const max = opts.max ?? 20;\n const capped = all.slice(0, max);\n const shown = withinBudget(capped, opts.chars ?? ANSWER_CHARS);\n const more = all.length - shown.length;\n const latest =\n ok\n .map((r) => r.latest)\n .filter((t): t is string => t !== null)\n .sort()\n .at(-1) ?? null;\n return {\n answer: {\n incidents: shown,\n skipped,\n errors: [...failed.map((f) => f.error), ...ok.flatMap((r) => r.stalled)],\n more,\n ...(more > 0\n ? { more_by: shown.length < capped.length ? 'size' : 'max' }\n : {}),\n apps: names.length,\n hosts: groups.length,\n latest,\n ...(opts.restart\n ? {\n positioned: Object.fromEntries(\n Object.entries(next.apps).map(([k, m]) => [\n k,\n STREAMS.filter((st) => m[st] !== undefined),\n ])\n ),\n }\n : {}),\n },\n next,\n };\n}\n\n/** The newest incidents whose text fits in `chars`, in order; the first always fits. */\nfunction withinBudget(incidents: Incident[], chars: number): Incident[] {\n const out: Incident[] = [];\n let used = 0;\n for (const i of incidents) {\n const size =\n i.line.length +\n i.before.reduce((n, l) => n + l.length, 0) +\n i.after.reduce((n, l) => n + l.length, 0);\n if (out.length > 0 && used + size > chars) break;\n out.push(i);\n used += size;\n }\n return out;\n}\n\n/** The stamp of the last stamped line read (pm2's, as the file has it); null when none is stamped. */\nfunction lastStamp(lines: string[]): string | null {\n for (let k = lines.length - 1; k >= 0; k--) {\n const t = stampOf(lines[k]);\n if (t) return t;\n }\n return null;\n}\n\n/** Index of the first line inside a first call's window; the lines before it are context only (an unstamped line goes with the one before it). */\nfunction insideFrom(lines: string[], from: string): number {\n let t: string | null = null;\n for (let i = 0; i < lines.length; i++) {\n t = stampOf(lines[i]) ?? t;\n if (t !== null && t >= from) return i;\n }\n return lines.length;\n}\n\n/** The stamp of the last stamped line before index `end`; null when none is. */\nfunction lastStampBefore(lines: string[], end: number): string | null {\n for (let k = end - 1; k >= 0; k--) {\n const t = stampOf(lines[k]);\n if (t) return t;\n }\n return null;\n}\n\n/**\n * Whether the run's boot may still come in the lines this poll analyses. A run looked at before keeps the state that\n * poll left; a new run since then has its boot ahead. A run not looked at yet (a first poll, or polls without reloads):\n * its boot is behind the point when a line before the analysed ones (`ctxStamps`, the last stamp of each stream's\n * context) is of this run. Without a start nothing is taken for the boot.\n */\nfunction bootAhead(\n start: string | null,\n prev: AppMark | undefined,\n ctxStamps: string[]\n): boolean {\n if (start === null) return false;\n if (prev?.start === start) return prev.boot === true;\n if (typeof prev?.start === 'string') return true;\n return ctxStamps.every((s) => beforeStart(s, start));\n}\n\n/**\n * An app's reloads of one poll as one incident: how many, the first and the last one's time, the last one's line (its\n * first restart or rebuild line, else its first line). Times are the stamps as pm2 wrote them on those lines, like the other incidents' (an unstamped marker line keeps\n * the stamp it inherited).\n */\nconst reloaded = (app: string, host: string, rs: Reload[]): Incident => ({\n app,\n host,\n kind: 'reloaded',\n stream: 'out',\n time: stampOf(rs[rs.length - 1].line) ?? rs[rs.length - 1].time,\n first_time: stampOf(rs[0].line) ?? rs[0].time,\n count: rs.length,\n line: rs[rs.length - 1].line,\n before: [],\n after: [],\n fingerprint: 'reloaded',\n});\n\n/** pm2's view of an app since the last poll: gave up (errored, reported once) or restarted (with how many times). */\nfunction processEvents(\n app: string,\n host: string,\n p: Pm2Process,\n prev: AppMark | undefined,\n errLines: string[]\n): Incident[] {\n const last = errLines.slice(-EVENT_TAIL);\n const time =\n [...last]\n .reverse()\n .map(stampOf)\n .find((t) => t !== null) ?? null;\n const tail = last.map(cutContext); // context, cut like any other incident's\n const event = (\n kind: 'crashed' | 'restarted',\n count: number,\n line: string\n ): Incident => ({\n app,\n host,\n kind,\n stream: 'err',\n time,\n first_time: time,\n count,\n line,\n before: tail,\n after: [],\n fingerprint: `pm2:${kind}`,\n });\n const out: Incident[] = [];\n if (p.status === 'errored' && prev?.status !== 'errored')\n out.push(event('crashed', 1, `pm2: ${app} crashed (status errored)`));\n if (prev && p.restarts > prev.restarts)\n out.push(\n event(\n 'restarted',\n p.restarts - prev.restarts,\n `pm2: ${app} restarted ${p.restarts - prev.restarts} time(s)`\n )\n );\n return out;\n}\n","import { McprocError } from './errors.js';\nimport { watcherIn } from './leases/view.js';\nimport { type Host, type Manifest, scopeManifest } from './manifest.js';\nimport { type HostMemory, parseMeminfo } from './memory.js';\nimport { Pm2Client, resolvePm2Bin, runtimeDir } from './pm2.js';\nimport { parseUrlProbe } from './ports.js';\nimport { pickHost } from './resolve.js';\nimport { stateDir } from './state.js';\nimport {\n checkHere,\n type HereCheck,\n type HostEnv,\n isItself,\n settleUrls,\n type UrlResult,\n} from './urlcheck.js';\nimport {\n MARK,\n MEM_SNIPPET,\n urlBudgetMs,\n urlName,\n urlSection,\n} from '../shell/snippets.js';\nimport { shq } from '../transport/quote.js';\nimport { createTransport, ensureOk } from '../transport/index.js';\nimport type { Spawner, Transport } from '../transport/types.js';\nimport { LOCK_MARK } from '../runtime/probe.js';\n\n/** One url of the host's apps: its name and the address it resolves to there, and where it answers. */\nexport interface DoctorUrl {\n app: string;\n url: string;\n name: string | null;\n /** the name's first address on that host; null when it does not resolve there or getent is missing */\n addr: string | null;\n /** the name resolves there to the host itself (see isItself) */\n itself: boolean;\n /** where it answers, decided as url_check: auto decides it */\n check: UrlResult;\n}\n\n/** What doctor found on one host: whether it answers, its Node, pm2 and tools, the daemon, the urls, and what to fix. */\nexport interface DoctorReport {\n host: string;\n transport: string;\n reachable: boolean;\n error: string | null;\n node: string | null;\n pm2: {\n source: string;\n bin: string;\n version: string | null;\n reason: string;\n } | null;\n tools: { ps: boolean; ss: boolean; tar: boolean };\n pm2_home: string | null;\n runtime_dir: string;\n runtime_present: boolean;\n runtime_pm2: string | null;\n runtime_node: string | null;\n daemon: 'answers' | 'error' | 'unknown';\n processes: number;\n in_namespace: number;\n /** the state directory that holds this machine's leases; null on another host */\n state_dir: string | null;\n /** the lease watcher's pm2 process; null on another host, or when pm2's list did not answer */\n watcher: { online: boolean; pid: number | null } | null;\n /** the host's memory from its probe; null on another host, or where there is no /proc/meminfo */\n memory: HostMemory | null;\n recommendations: string[];\n /** the host's own account of itself (container, hostname, own addresses); null when not read */\n environment: HostEnv | null;\n urls: DoctorUrl[];\n}\n\nconst MARKER = '__MCPROC_DOCTOR__';\n\n/** Diagnoses one host: its shell, Node, pm2 and tools, the daemon, the urls of its apps, and on this machine the lease state. */\nexport async function doctorHost(\n m: Manifest,\n host: Host,\n spawner?: Spawner,\n hereCheck: HereCheck = checkHere\n): Promise<DoctorReport> {\n const transport = createTransport(host, spawner);\n const rt = runtimeDir(host);\n const r: DoctorReport = {\n host: host.name,\n transport: transport.describe(),\n reachable: false,\n error: null,\n node: null,\n pm2: null,\n tools: { ps: false, ss: false, tar: false },\n pm2_home: host.pm2_home ?? null,\n runtime_dir: rt,\n runtime_present: false,\n runtime_pm2: null,\n runtime_node: null,\n daemon: 'unknown',\n processes: 0,\n in_namespace: 0,\n // the leases live on this machine only\n state_dir: host.local ? stateDir() : null,\n watcher: null,\n memory: null,\n recommendations: [],\n environment: null,\n urls: [],\n };\n const probe = [\n `echo ${MARKER}`,\n `node -v 2>/dev/null || echo NODE_NONE`,\n `for t in ps ss tar; do if command -v $t >/dev/null 2>&1; then echo \"tool $t yes\"; else echo \"tool $t no\"; fi; done`,\n `echo \"pm2home \\${PM2_HOME:-}\"`,\n `if [ -x ${shq(`${rt}/bin/pm2`)} ]; then echo RUNTIME yes; else echo RUNTIME no; fi`,\n // before the lock section, which runs to the end of the output\n ...(host.local ? [MEM_SNIPPET] : []),\n `echo ${LOCK_MARK}; cat ${shq(`${rt}/lock.json`)} 2>/dev/null || true`,\n ].join('; ');\n try {\n const res = ensureOk(\n await transport.exec(probe, {\n env: host.pm2_home ? { PM2_HOME: host.pm2_home } : undefined,\n timeoutMs: 15_000,\n }),\n host,\n 'doctor probe'\n );\n if (!res.stdout.includes(MARKER))\n throw new McprocError(\n 'TRANSPORT_FAILED',\n `unexpected probe output: ${(res.stderr || res.stdout).trim().slice(0, 200)}`\n );\n r.reachable = true;\n const lockAt = res.stdout.indexOf(LOCK_MARK);\n const head = lockAt < 0 ? res.stdout : res.stdout.slice(0, lockAt);\n const memAt = head.indexOf(MARK.MEM);\n if (host.local && memAt >= 0)\n r.memory = parseMeminfo(head.slice(memAt + MARK.MEM.length));\n if (lockAt >= 0) {\n try {\n const lock = JSON.parse(\n res.stdout.slice(lockAt + LOCK_MARK.length).trim() || 'null'\n ) as { pm2?: string; node?: string | null } | null;\n r.runtime_pm2 = lock?.pm2 ?? null;\n r.runtime_node = lock?.node ?? null;\n } catch {\n /* unreadable lock: versions stay unknown */\n }\n }\n for (const line of head.split('\\n')) {\n const l = line.trim();\n if (/^v\\d+\\./.test(l)) r.node = l;\n const t = /^tool (ps|ss|tar) (yes|no)$/.exec(l);\n if (t) r.tools[t[1] as 'ps' | 'ss' | 'tar'] = t[2] === 'yes';\n const h = /^pm2home (.+)$/.exec(l);\n if (h) r.pm2_home = h[1].trim();\n if (l === 'RUNTIME yes') r.runtime_present = true;\n }\n } catch (e) {\n r.error = (e as Error).message;\n r.recommendations.push(\n host.ssh\n ? `ssh ${host.ssh} does not answer non-interactively: check the alias in ~/.ssh/config, the key, and that no prompt is needed (BatchMode)`\n : host.docker\n ? `docker exec into ${host.docker.container} failed: is the container running and the user allowed?`\n : 'the local shell probe failed'\n );\n return r;\n }\n try {\n const res = await resolvePm2Bin(host, transport);\n r.pm2 = {\n source: res.source,\n bin: res.bin,\n version: res.pm2Version,\n reason: res.reason,\n };\n } catch (e) {\n r.recommendations.push(\n `no usable pm2: ${(e as Error).message}. Run unpack for this host (brings pm2 along), or set hosts.${host.name}.pm2`\n );\n }\n if (r.pm2) {\n try {\n const procs = await new Pm2Client(\n transport,\n host,\n r.pm2.bin,\n host.pm2_home\n ).jlist();\n r.daemon = 'answers';\n r.processes = procs.length;\n r.in_namespace = procs.filter((p) => p.namespace === m.project).length;\n if (host.local) r.watcher = watcherIn(procs);\n if (procs.length === 0)\n r.recommendations.push(\n `pm2 daemon is empty here: if ${m.project} should already run on this host under another user or PM2_HOME, set hosts.${host.name}.pm2_home`\n );\n } catch (e) {\n r.daemon = 'error';\n r.recommendations.push(`pm2 jlist failed: ${(e as Error).message}`);\n }\n }\n const major = Number(/^v(\\d+)/.exec(r.node ?? '')?.[1] ?? 0);\n if (major < 18)\n r.recommendations.push(\n `Node ${r.node ?? 'missing'} in the login shell: pm2 7 needs Node >= 18 (unpack with with_node: auto brings an official build)`\n );\n if (!r.tools.ss)\n r.recommendations.push(\n 'no ss: port detection falls back to /proc (slower, same result)'\n );\n if (!r.tools.tar)\n r.recommendations.push(\n 'no tar: unpack cannot deliver a runtime bundle to this host'\n );\n await checkUrlsOf(m, host, transport, r, hereCheck);\n return r;\n}\n\n/**\n * The bound on doctor's url round trip: its base, plus the bounds of the environment section and of each url, so a\n * host whose resolver hangs, which is what doctor is there to show, still answers; never more than two minutes.\n */\nconst urlStepMs = (urls: number): number => urlBudgetMs(15_000, urls, true);\n\n/**\n * The host's environment and where the urls of its apps answer: those bound to it, plus on local the unbound ones,\n * which run there by default. Each url is decided as url_check: auto decides it, whatever the app declares: doctor says\n * where a url works, and recommends auto for an app with url_check: host whose url answers only from this machine. Its\n * own round trip, judged by the exit status and the markers, never by stderr: BusyBox timeout prints \"Terminated\"\n * there each time it cuts a hung lookup, and the answer is still whole.\n */\nasync function checkUrlsOf(\n m: Manifest,\n host: Host,\n transport: Transport,\n r: DoctorReport,\n here: HereCheck\n): Promise<void> {\n const apps = Object.values(scopeManifest(m, host.name, 'local').apps).flatMap(\n (a) => (a.url === null ? [] : [{ app: a, url: a.url }])\n );\n const urls = [...new Set(apps.map((x) => x.url))];\n try {\n const res = ensureOk(\n await transport.exec(urlSection(urls, true).join('\\n'), {\n timeoutMs: urlStepMs(urls.length),\n }),\n host,\n 'doctor url check'\n );\n const lines = res.stdout.split('\\n').map((l) => l.trim());\n if (\n res.code !== 0 ||\n !lines.includes(MARK.ENV) ||\n !lines.includes(MARK.URL)\n )\n throw new McprocError(\n 'TRANSPORT_FAILED',\n `unexpected output (exit ${res.code}): ${(res.stderr || res.stdout).trim().slice(0, 200)}`\n );\n const probe = parseUrlProbe(res.stdout);\n r.environment = probe.env;\n const checks = await settleUrls(\n apps.map((x) => ({\n name: x.app.name,\n url: x.url,\n url_check: 'auto' as const,\n })),\n { host: host.name, local: host.local },\n probe,\n here\n );\n for (const { app, url } of apps) {\n const name = urlName(url);\n const addr = probe.urls.get(url)?.addr ?? null;\n const check = checks[app.name];\n r.urls.push({\n app: app.name,\n url,\n name,\n addr,\n itself: !host.local && isItself(name, addr, probe.env),\n check,\n });\n if (\n app.url_check === 'host' &&\n check.from === 'here' &&\n check.status !== 'down'\n )\n r.recommendations.push(\n probe.urls.get(url)?.code === null\n ? `apps.${app.name}.url_check is host, but ${host.name} cannot check its url (no curl or wget) and it answers from this machine: set url_check: auto (or drop the line)`\n : `apps.${app.name}.url_check is host, but its url answers only from this machine: set url_check: auto (or drop the line)`\n );\n }\n } catch (e) {\n r.recommendations.push(\n `the environment and url checks failed: ${(e as Error).message}`\n );\n }\n}\n\n/** Diagnoses the named host, or every host of the manifest (local first), each report on its own: one that fails never stops the rest. */\nexport async function doctor(\n m: Manifest,\n hostName?: string,\n spawner?: Spawner,\n hereCheck?: HereCheck\n): Promise<DoctorReport[]> {\n const names = hostName\n ? [hostName]\n : ['local', ...Object.keys(m.hosts).filter((n) => n !== 'local')];\n const out: DoctorReport[] = [];\n for (const n of names) {\n try {\n out.push(await doctorHost(m, pickHost(m, n), spawner, hereCheck));\n } catch (e) {\n out.push({\n host: n,\n transport: '?',\n reachable: false,\n error: (e as Error).message,\n node: null,\n pm2: null,\n tools: { ps: false, ss: false, tar: false },\n pm2_home: null,\n runtime_dir: '',\n runtime_present: false,\n runtime_pm2: null,\n runtime_node: null,\n daemon: 'unknown',\n processes: 0,\n in_namespace: 0,\n state_dir: null,\n watcher: null,\n memory: null,\n recommendations: [],\n environment: null,\n urls: [],\n });\n }\n }\n return out;\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport { McprocError } from './errors.js';\nimport { VERSION } from '../version.js';\nimport {\n DEP_TIMEOUT_MAX_S,\n defaultProject,\n MANIFEST_REL,\n type AppKind,\n} from './manifest.js';\nimport {\n dependsOnDistLib,\n libsFilters,\n loadWorkspace,\n readJson,\n readTurbo,\n turboBin,\n type WsPackage,\n} from './turbo.js';\n\nexport interface Candidate {\n name: string;\n source: string;\n run: string;\n cwd: string;\n kind: AppKind | 'unknown';\n port?: number;\n /** Written uncommented: part of the dev stack the draft starts with. */\n live?: boolean;\n /** Live apps: the placeholder; libs/libs-watch: their own text. */\n description?: string;\n depends_on?: { app: string; condition: 'completed'; timeout: number }[];\n /** One comment line written under the candidate. */\n note?: string;\n}\n/** A profile of the draft; a live one is written uncommented. */\nexport interface DraftProfile {\n name: string;\n apps: string[];\n live: boolean;\n}\nexport interface Discovery {\n candidates: Candidate[];\n notes: string[];\n profiles: DraftProfile[];\n /** The package names folded into the libs builders ([] when none). */\n libs: string[];\n}\n/** A live app needs a description to load; this one tells the human to write the real one. */\nexport const LIVE_DESCRIPTION = 'TODO: what this app does';\nexport interface InitResult {\n path: string;\n created: string[];\n candidates: number;\n by_source: Record<string, number>;\n /** The apps written uncommented. */\n live: string[];\n /** The live profiles, e.g. dev. */\n profiles: string[];\n /** The packages folded into the libs builders. */\n libs: string[];\n next: string;\n}\n\nconst SCRIPT_RE =\n /dev|start|serve|watch|build|worker|queue|cron|preview|migrate|seed|once/i;\n/** A command that keeps running and rebuilds on change. */\nconst WATCH_RE = /(--watch|\\bwatch\\b|\\s-w\\b|tsc -b -w)/i;\nconst SERVERISH_RE = /\\b(dev|serve|start|preview)\\b/i;\n/** Script names of one-shot jobs: a build, a migration, a seed. */\nconst ONCE_RE = /\\b(build|migrate|seed|once)\\b/i;\nconst SKIP_DIRS = new Set([\n 'node_modules',\n 'dist',\n 'build',\n 'coverage',\n 'out',\n 'target',\n 'vendor',\n]);\n\nexport function sanitizeName(s: string): string {\n const n = s\n .toLowerCase()\n .replace(/[^a-z0-9._-]+/g, '-')\n .replace(/^[^a-z0-9]+/, '')\n .replace(/-+$/, '');\n return n || 'app';\n}\n\nfunction pmFor(root: string): string {\n if (fs.existsSync(path.join(root, 'yarn.lock'))) return 'yarn';\n if (fs.existsSync(path.join(root, 'pnpm-lock.yaml'))) return 'pnpm';\n if (\n fs.existsSync(path.join(root, 'bun.lock')) ||\n fs.existsSync(path.join(root, 'bun.lockb'))\n )\n return 'bun run';\n return 'npm run';\n}\n\nexport function walk(dir: string, maxDepth: number, depth = 0): string[] {\n const out: string[] = [];\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch {\n return out;\n }\n for (const e of entries) {\n const p = path.join(dir, e.name);\n if (e.isDirectory()) {\n if (SKIP_DIRS.has(e.name) || e.name.startsWith('.')) continue;\n if (depth < maxDepth) out.push(...walk(p, maxDepth, depth + 1));\n } else out.push(p);\n }\n return out;\n}\n\nexport function guessKind(name: string, cmd: string): AppKind | 'unknown' {\n const s = `${name} ${cmd}`;\n if (/worker|queue|cron|consumer/i.test(s)) return 'worker';\n const serverish = SERVERISH_RE.test(name);\n if (WATCH_RE.test(s) && !serverish) return 'build';\n if (ONCE_RE.test(name) && !serverish) return 'task';\n if (SERVERISH_RE.test(s)) return 'server';\n return 'unknown';\n}\n\n/** `next dev` / `next start` listen on 3000 unless a flag says otherwise. */\nconst NEXT_RE = /\\bnext\\s+(dev|start)\\b/;\n/**\n * `vite` and its subcommand; the lookahead keeps `vitest`, `vite-node` and a\n * `vite.config.ts` argument out. Global: a script may chain\n * `vite build && vite preview`, where the server is the second call.\n */\nconst VITE_RE = /(?:^|[\\s&;])vite(?![\\w.-])(?:\\s+(\\w+))?/g;\nconst VITE_CONFIGS = ['ts', 'js', 'mts', 'mjs', 'cts', 'cjs'].map(\n (e) => `vite.config.${e}`\n);\n/** A port literal, quoted or not. */\nconst PORT_LITERAL = /^([\"'`]?)(\\d{2,5})\\1$/;\n/** `process.env.X`, or `env.X` of the object Vite's loadEnv returns. */\nconst ENV_READ = /^(?:process\\.)?env\\.[A-Za-z_$][\\w$]*$/;\n/** The argument of `Number(…)` or `parseInt(…)` / `parseInt(…, 10)` around the whole expression; else the expression. */\nconst unwrap = (e: string): string => {\n const m = /^(?:Number|parseInt)\\(([\\s\\S]*)\\)$/.exec(e);\n return m ? m[1].replace(/,\\s*10\\s*$/, '').trim() : e;\n};\n\n/**\n * The port an expression gives when the environment sets nothing: a literal, or the fallback of an env read\n * (`process.env.X ?? N`, `env.X || 'N'`), either one whole or the env read alone wrapped in `Number(…)` or\n * `parseInt(…, 10)`. Anything else is not read.\n */\nfunction portValue(expr: string): number | undefined {\n const e = unwrap(expr.trim());\n const lit = PORT_LITERAL.exec(e);\n if (lit) return Number(lit[2]);\n const fb = /^([\\s\\S]+?)\\s*(?:\\?\\?|\\|\\|)\\s*(\\S+)$/.exec(e);\n const n = fb && PORT_LITERAL.exec(fb[2]);\n return n && ENV_READ.test(unwrap(fb[1].trim())) ? Number(n[2]) : undefined;\n}\n\n/**\n * The expression that starts at `at`: up to the first `,`, `;` or line end outside brackets and quotes, or the bracket\n * that closes an enclosing one.\n */\nfunction exprAt(text: string, at: number): string {\n let depth = 0;\n let quote = '';\n let i = at;\n for (; i < text.length; i++) {\n const ch = text[i];\n if (quote) {\n if (ch === '\\\\') i++;\n else if (ch === quote) quote = '';\n } else if (ch === '\"' || ch === \"'\" || ch === '`') quote = ch;\n else if ('([{'.includes(ch)) depth++;\n else if (')]}'.includes(ch)) {\n if (depth-- === 0) break;\n } else if (depth === 0 && ',;\\n'.includes(ch)) break;\n }\n return text.slice(at, i).trim();\n}\n\n/**\n * The value of the block's own `port` key: the expression after `port:`, or `port` for the shorthand\n * (`{ port, host }`); undefined when the block has no such key.\n */\nfunction portKey(block: string): string | undefined {\n for (const m of block.matchAll(/([\"']?)\\bport(?![\\w$])\\1\\s*(:)?/g)) {\n // a key follows the block's brace or a comma\n if (!/[{,]$/.test(block.slice(0, m.index).trimEnd())) continue;\n const rest = m.index + m[0].length;\n if (m[2]) return exprAt(block, rest);\n if (/^\\s*(?:[,}]|$)/.test(block.slice(rest))) return 'port';\n }\n return undefined;\n}\n\n/** A port expression read as `portValue` does; an identifier is first resolved through its `const`/`let`/`var` in `text`. */\nfunction readPort(expr: string, text: string): number | undefined {\n if (!/^[A-Za-z_$][\\w$]*$/.test(expr)) return portValue(expr);\n const decl = new RegExp(\n `\\\\b(?:const|let|var)\\\\s+${expr.replace(/\\$/g, '\\\\$')}\\\\s*(?::[^=;]+)?=(?!=)`\n ).exec(text);\n return decl\n ? portValue(exprAt(text, decl.index + decl[0].length))\n : undefined;\n}\n\n/**\n * The config a Vite call names with `--config <path>`, `--config=<path>` or `-c <path>`, read from the call's own\n * arguments (up to the next `;`, `&` or `|`): the path, quotes removed; null when the shell would compute it (`$X`,\n * `~`, a glob); undefined when the call names none.\n */\nfunction viteConfigFlag(args: string): string | null | undefined {\n const own = /^[^;&|\\n]*/.exec(args)![0];\n const m = /(?:^|\\s)(?:--config(?:=|\\s+)|-c\\s+)(\\S+)/.exec(own);\n if (!m) return undefined;\n const p = /^([\"'])(.*)\\1$/.exec(m[1])?.[2] ?? m[1];\n return /[$`~*?{}\"']/.test(p) ? null : p;\n}\n\n/**\n * Vite's port from its config: the `server` or `preview` block's `port`, as `readPort` reads it. Every\n * `<section>: {` is tried in order, since a block of that name without a port can come first (vitest's\n * `test: { server: { deps } }`). `config` is the file the command names (see `viteConfigFlag`); without one the\n * standard `vite.config.*` is read. null when the block has a `port` that cannot be read, or when the named config\n * cannot be read: Vite then reads no other file, so the default would be a confident wrong guess. undefined when no\n * block has a port, or there is no standard config.\n */\nfunction vitePort(\n dir: string,\n section: 'server' | 'preview',\n config?: string | null\n): number | null | undefined {\n if (config === null) return null;\n let raw: string | undefined;\n for (const f of config ? [config] : VITE_CONFIGS) {\n try {\n raw = fs.readFileSync(path.resolve(dir, f), 'utf8');\n break;\n } catch {\n /* not there, or not a file */\n }\n }\n if (raw === undefined) return config ? null : undefined;\n // comments out, so a word \"port\" in one is no key; only those after a blank or at a line start, which keeps\n // `http://…` and `src/**/*` in strings\n const text = raw\n .replace(/(^|\\s)\\/\\*[\\s\\S]*?\\*\\//g, '$1')\n .replace(/(^|\\s)\\/\\/[^\\n]*/g, '$1');\n for (const h of text.matchAll(new RegExp(`\\\\b${section}\\\\s*:\\\\s*\\\\{`, 'g'))) {\n const at = h.index;\n // the block's text up to its closing brace, nested braces (proxy maps) counted\n let depth = 0;\n let end = at + h[0].length - 1;\n for (; end < text.length; end++) {\n if (text[end] === '{') depth++;\n else if (text[end] === '}' && --depth === 0) break;\n }\n // a `port` of the block itself, not of a nested map such as `hmr: { port }`:\n // one pass drops every brace pair with no brace inside (the block's own pair\n // is never one: its closing brace is not in the slice); what deeper maps\n // such as proxy entries leave behind holds no `port` key in practice\n const value = portKey(text.slice(at, end).replace(/\\{[^{}]*\\}/g, ''));\n if (value !== undefined) return readPort(value, text) ?? null;\n }\n return undefined;\n}\n\nexport function guessPort(cmd: string, dir: string): number | undefined {\n const m = /(?:\\bPORT=|--port[= ]|\\s-p\\s)(\\d{2,5})\\b/.exec(cmd);\n if (m) return Number(m[1]);\n for (const f of ['.env', '.env.local', '.env.development']) {\n const p = path.join(dir, f);\n if (!fs.existsSync(p)) continue;\n const e = /^\\s*PORT=[\"']?(\\d{2,5})/m.exec(fs.readFileSync(p, 'utf8'));\n if (e) return Number(e[1]);\n }\n if (NEXT_RE.test(cmd)) return 3000;\n const vite = [...cmd.matchAll(VITE_RE)].find((v) => v[1] !== 'build');\n if (vite) {\n const section = vite[1] === 'preview' ? 'preview' : 'server';\n const config = viteConfigFlag(cmd.slice(vite.index + vite[0].length));\n const p = vitePort(dir, section, config);\n // the defaults only when the config names no port: one it names but cannot be read, or a named config that\n // cannot be read, gets no guess\n return p === null ? undefined : (p ?? (section === 'server' ? 5173 : 4173));\n }\n const src = path.join(dir, 'src');\n if (fs.existsSync(src)) {\n for (const f of walk(src, 3)\n .filter((x) => /\\.(ts|js|mjs|cjs|tsx|jsx)$/.test(x))\n .slice(0, 200)) {\n const text = fs.readFileSync(f, 'utf8');\n // `PORT\\b` keeps names such as PORTAL out\n const l =\n /\\.listen\\(\\s*(\\d{2,5})\\b/.exec(text) ??\n /\\b(?:DEFAULT_)?PORT\\b\\s*(?::\\s*number)?\\s*=\\s*(\\d{2,5})\\b/.exec(\n text\n ) ??\n /\\bPORT\\s*\\)?\\s*(?:\\?\\?|\\|\\|)\\s*[\"']?(\\d{2,5})\\b/.exec(text);\n if (l) return Number(l[1]);\n }\n }\n return undefined;\n}\n\n/** A one-shot job (build, task) declares no port, so none is guessed for it. */\nfunction portFor(\n kind: AppKind | 'unknown',\n cmd: string,\n dir: string\n): number | undefined {\n return kind === 'build' || kind === 'task' ? undefined : guessPort(cmd, dir);\n}\n\n/** The app name of a package: its name without the npm scope. */\nconst pkgAppName = (name: string): string =>\n sanitizeName(name.split('/').pop()!);\n\n/** How a workspace package takes part in turbo's live dev task. */\ninterface PkgTurbo {\n liveTask: string;\n /** A dist library live through its own dev task: a build app, no port. */\n isLib: boolean;\n /** Depends on a library folded into libs: waits for its first build. */\n waitsForLibs: boolean;\n /** Live dist libraries it depends on: their first build is not awaited. */\n liveLibDeps: string[];\n /** Its build script is folded into libs. */\n dropBuild: boolean;\n}\n\n/**\n * The wait on libs' first build: up to the manifest's cap, since a cold build of many libraries outlasts the default\n * and every app waiting on it would be skipped; a failed build still ends the wait at once.\n */\nconst LIBS_DEP = {\n app: 'libs',\n condition: 'completed',\n timeout: DEP_TIMEOUT_MAX_S,\n} as const;\n\nconst notAwaited = (lib: string): string => {\n const app = pkgAppName(lib);\n return `${app}'s first build is not awaited; uncomment ${app}-build and add { app: ${app}-build, condition: completed } to its depends_on to wait for it`;\n};\n\nfunction packageCandidates(\n root: string,\n pkgDir: string,\n pm: string,\n turbo?: PkgTurbo\n): Candidate[] {\n const pkg = readJson(path.join(pkgDir, 'package.json'));\n if (!pkg?.scripts) return [];\n const rel = path.relative(root, pkgDir) || '.';\n const appName = pkgAppName(String(pkg.name ?? path.basename(pkgDir)));\n const prefix = rel === '.' ? '' : `${appName}-`;\n const file = `${rel === '.' ? '' : `${rel}/`}package.json`;\n const out: Candidate[] = [];\n for (const [n, cmd] of Object.entries(\n pkg.scripts as Record<string, string>\n )) {\n if (!SCRIPT_RE.test(n)) continue;\n const kind = guessKind(n, cmd);\n if (turbo?.dropBuild && n === 'build') continue;\n if (turbo && n === turbo.liveTask) {\n out.push({\n name: appName,\n source: `${file}:${n}`,\n run: `${pm} ${n}`,\n cwd: rel,\n kind: turbo.isLib ? 'build' : kind,\n port: turbo.isLib ? undefined : portFor(kind, cmd, pkgDir),\n live: true,\n description: LIVE_DESCRIPTION,\n ...(turbo.waitsForLibs ? { depends_on: [{ ...LIBS_DEP }] } : {}),\n ...(turbo.liveLibDeps.length\n ? { note: turbo.liveLibDeps.map(notAwaited).join('; ') }\n : {}),\n });\n continue;\n }\n out.push({\n name: sanitizeName(prefix + n),\n source: `${file}:${n}`,\n run: `${pm} ${n}`,\n cwd: rel,\n kind,\n port: portFor(kind, cmd, pkgDir),\n });\n }\n return out;\n}\n\n/** Supports \"dir/*\", \"dir/**\" and exact-directory workspace patterns; anything else is reported, not guessed. */\nfunction expandWorkspaces(\n root: string,\n patterns: string[]\n): { dirs: string[]; unsupported: string[]; globParents: string[] } {\n const dirs = new Set<string>();\n const unsupported: string[] = [];\n const globParents: string[] = [];\n for (const pat of patterns) {\n const glob = /^(.*?)\\/\\*\\*?$/.exec(pat);\n if (glob) {\n const base = path.join(root, glob[1]);\n // relative to the root, so `./packages/*` and `packages/*` name one folder\n globParents.push(path.relative(root, base));\n let names: string[] = [];\n try {\n names = fs.readdirSync(base);\n } catch {\n /* no such dir */\n }\n names.sort();\n for (const d of names)\n if (fs.existsSync(path.join(base, d, 'package.json')))\n dirs.add(path.join(base, d));\n } else if (pat.includes('*')) {\n unsupported.push(pat);\n } else if (fs.existsSync(path.join(root, pat, 'package.json'))) {\n dirs.add(path.join(root, pat));\n }\n }\n return { dirs: [...dirs], unsupported, globParents };\n}\n\n/**\n * The builders that stand for every dist library without a dev script of its\n * own: a one-shot build the live apps wait for, then a watch that keeps dist/\n * fresh. `turbo watch` came with turbo 2, so turbo 1 gets the build alone.\n */\nfunction libsBuilders(\n folded: WsPackage[],\n all: WsPackage[],\n globParents: string[],\n pm: string,\n version: 1 | 2\n): Candidate[] {\n const bin = turboBin(pm);\n // turbo 2's interactive UI would hold the terminal; turbo 1 has no --ui flag\n const ui = version === 2 ? ' --ui=stream' : '';\n const filters = libsFilters(folded, globParents, all).join(' ');\n const parents = [...new Set(folded.map((p) => path.dirname(p.dir)))].join(\n ', '\n );\n const libs: Candidate = {\n name: 'libs',\n source: 'turbo.json:build',\n run: `${bin} run build ${filters}${ui}`,\n cwd: '.',\n kind: 'task',\n live: true,\n description: `one-shot build of the libraries consumed from dist/ (${parents}); the apps import these builds`,\n };\n if (version === 1) return [libs];\n return [\n libs,\n {\n name: 'libs-watch',\n source: 'turbo.json:build',\n run: `${bin} watch build ${filters}${ui}`,\n cwd: '.',\n kind: 'build',\n live: true,\n description:\n \"rebuilds a changed library's dist/ (and its dependents) while you work\",\n depends_on: [{ ...LIBS_DEP }],\n },\n ];\n}\n\n/** `base`, else `base-apps`, `base-apps-2`, …: the first name not taken. */\nfunction freeName(base: string, taken: Set<string>): string {\n if (!taken.has(base)) return base;\n let n = `${base}-apps`;\n for (let i = 2; taken.has(n); i++) n = `${base}-apps-${i}`;\n return n;\n}\n\n/**\n * The live profile of the dev task's apps, and a commented one per other\n * persistent task. A profile may not share an app's name (the loader refuses\n * it), so each steps aside: the live one from the live apps, a commented one\n * from every candidate, since uncommenting both would clash.\n */\nfunction draftProfiles(\n candidates: Candidate[],\n persistent: string[]\n): DraftProfile[] {\n const live = candidates.filter((c) => c.live).map((c) => c.name);\n const taken = new Set(['all', ...candidates.map((c) => c.name)]);\n const out: DraftProfile[] = [\n {\n name: freeName('dev', new Set(['all', ...live])),\n apps: live,\n live: true,\n },\n ];\n taken.add(out[0].name);\n for (const t of persistent.filter((t) => t !== 'dev')) {\n // a package's own script: the root one runs the task over every package\n const apps = candidates\n .filter(\n (c) =>\n !c.live &&\n /\\/package\\.json:/.test(c.source) &&\n c.source.endsWith(`:${t}`)\n )\n .map((c) => c.name);\n if (!apps.length) continue;\n const name = freeName(t, taken);\n taken.add(name);\n out.push({ name, apps, live: false });\n }\n return out;\n}\n\nexport function discover(root: string): Discovery {\n const candidates: Candidate[] = [];\n const notes: string[] = [];\n const pm = pmFor(root);\n\n const pkg = readJson(path.join(root, 'package.json'));\n const ws: string[] = Array.isArray(pkg?.workspaces)\n ? [...pkg.workspaces]\n : Array.isArray(pkg?.workspaces?.packages)\n ? [...pkg.workspaces.packages]\n : [];\n const pnpmWs = path.join(root, 'pnpm-workspace.yaml');\n if (fs.existsSync(pnpmWs)) {\n try {\n const y = parseYaml(fs.readFileSync(pnpmWs, 'utf8'));\n if (Array.isArray(y?.packages)) ws.push(...y.packages);\n } catch {\n notes.push('pnpm-workspace.yaml could not be parsed');\n }\n }\n const expanded = expandWorkspaces(root, ws);\n\n const turbo = readTurbo(root);\n const turboFile = path.join(root, 'turbo.json');\n if (!turbo && fs.existsSync(turboFile) && readJson(turboFile) === null)\n notes.push(\n \"turbo.json could not be parsed (comments are not read); drafted without turbo's tasks\"\n );\n // only the bare task: a package-scoped key (`web#dev`) configures one package, not the stack\n const pkgs = turbo?.persistent.includes('dev')\n ? loadWorkspace(root, expanded.dirs)\n : [];\n // the live stack is the packages implementing the task; with none there is nothing to start\n const liveTask = pkgs.some((p) => p.scripts.dev) ? 'dev' : null;\n // a dist library with a dev script of its own is live through it; the rest are built by libs\n const folded = liveTask\n ? pkgs.filter((p) => p.distLib && !p.scripts[liveTask])\n : [];\n const foldedNames = new Set(folded.map((p) => p.name));\n const liveLibs = liveTask\n ? pkgs.filter((p) => p.distLib && p.scripts[liveTask])\n : [];\n const liveLibNames = new Set(liveLibs.map((p) => p.name));\n if (turbo && folded.length) {\n candidates.push(\n ...libsBuilders(folded, pkgs, expanded.globParents, pm, turbo.version)\n );\n const one = folded.length === 1;\n const apps = turbo.version === 1 ? 'libs' : 'libs and libs-watch';\n notes.push(\n `${folded.length} librar${one ? 'y' : 'ies'} built into dist/ ${one ? 'is' : 'are'} drafted as ${apps}: ${folded.map((p) => p.name).join(', ')}`\n );\n if (turbo.version === 1)\n notes.push(\n 'turbo 1 has no turbo watch: libs-watch is not drafted; run libs again after changing a library, or move to turbo 2'\n );\n }\n\n candidates.push(...packageCandidates(root, root, pm));\n for (const dir of expanded.dirs) {\n const p = liveTask\n ? pkgs.find((x) => x.dir === path.relative(root, dir))\n : undefined;\n candidates.push(\n ...packageCandidates(\n root,\n dir,\n pm,\n liveTask && p\n ? {\n liveTask,\n isLib: p.distLib,\n waitsForLibs: dependsOnDistLib(p, pkgs, foldedNames).length > 0,\n liveLibDeps: dependsOnDistLib(p, pkgs, liveLibNames),\n dropBuild: foldedNames.has(p.name),\n }\n : undefined\n )\n );\n }\n for (const pat of expanded.unsupported)\n notes.push(\n `workspace pattern \"${pat}\" is not expanded by init; add its packages' scripts by hand`\n );\n\n for (const f of walk(root, 4).filter(\n (p) => path.basename(p) === 'project.json'\n )) {\n const pj = readJson(f);\n if (!pj?.targets) continue;\n const name = String(pj.name ?? path.basename(path.dirname(f)));\n for (const t of ['serve', 'dev', 'build'] as const) {\n if (!pj.targets[t]) continue;\n candidates.push({\n name: sanitizeName(`${name}-${t}`),\n source: `${path.relative(root, f)}:${t}`,\n run: `npx nx run ${name}:${t}${t === 'build' ? ' --watch' : ''}`,\n cwd: '.',\n kind: t === 'build' ? 'build' : 'server',\n port: t === 'build' ? undefined : guessPort('', path.dirname(f)),\n });\n }\n }\n\n for (const t of turbo?.tasks ?? []) {\n if (\n !SCRIPT_RE.test(t) ||\n candidates.some((c) => c.source.endsWith(`package.json:${t}`))\n )\n continue;\n candidates.push({\n name: sanitizeName(`turbo-${t}`),\n source: `turbo.json:${t}`,\n run: `npx turbo run ${t}`,\n cwd: '.',\n kind: guessKind(t, ''),\n });\n }\n\n const eco = readJson(path.join(root, 'ecosystem.json'));\n if (Array.isArray(eco?.apps)) {\n for (const a of eco.apps) {\n if (!a?.name) continue;\n const args = Array.isArray(a.args)\n ? a.args.join(' ')\n : String(a.args ?? '');\n const interp =\n a.interpreter && a.interpreter !== 'node' && a.interpreter !== 'none'\n ? `${a.interpreter} `\n : /\\.(c|m)?js$/.test(String(a.script ?? ''))\n ? 'node '\n : '';\n candidates.push({\n name: sanitizeName(String(a.name)),\n source: `ecosystem.json:${a.name}`,\n run: `${interp}${a.script ?? ''} ${args}`.trim(),\n cwd: String(a.cwd ?? '.'),\n kind: 'server',\n port: Number(a.env?.PORT) || undefined,\n });\n }\n }\n for (const f of [\n 'ecosystem.config.js',\n 'ecosystem.config.cjs',\n 'ecosystem.config.mjs',\n ]) {\n if (fs.existsSync(path.join(root, f)))\n notes.push(\n `${f} found: JavaScript ecosystem files are not executed by init; port its apps by hand`\n );\n }\n\n const procfile = path.join(root, 'Procfile');\n if (fs.existsSync(procfile)) {\n for (const line of fs.readFileSync(procfile, 'utf8').split('\\n')) {\n const m = /^\\s*([A-Za-z0-9_-]+):\\s*(.+)$/.exec(line);\n if (m) {\n const kind = guessKind(m[1], m[2]);\n candidates.push({\n name: sanitizeName(m[1]),\n source: `Procfile:${m[1]}`,\n run: m[2].trim(),\n cwd: '.',\n kind,\n port: portFor(kind, m[2], root),\n });\n }\n }\n }\n\n // all is the loader's built-in profile of every app, so no app may take it. The live apps are named first, so a\n // commented candidate never takes a package's name; libs comes first among them, so it is never renamed and\n // depends_on: libs holds\n const taken = new Set(['all']);\n for (const c of [\n ...candidates.filter((x) => x.live),\n ...candidates.filter((x) => !x.live),\n ]) {\n let name = c.name;\n for (let i = 2; taken.has(name); i++) name = `${c.name}-${i}`;\n taken.add(name);\n c.name = name;\n }\n const profiles =\n turbo && liveTask ? draftProfiles(candidates, turbo.persistent) : [];\n for (const c of candidates)\n if (liveTask && c.source === 'package.json:dev')\n c.note = `the ${profiles[0].name} profile replaces this: turbo would start every package as one process`;\n return {\n candidates,\n notes,\n profiles,\n libs: folded.map((p) => p.name),\n };\n}\n\n/**\n * A scalar of the draft as YAML text: bare only when it holds no YAML punctuation and the yaml library reads it back\n * as the same string, so `true`, `123`, `1e3`, `null` or `~` (a boolean, numbers, null) are double-quoted; JSON's\n * escapes are valid in a YAML double-quoted string.\n */\nfunction yamlStr(s: string): string {\n if (!/[:#'\"{}[\\],&*?|<>=!%@`]/.test(s) && !/^\\s|\\s$/.test(s))\n try {\n if ((parseYaml(`k: ${s}`) as { k?: unknown } | null)?.k === s) return s;\n } catch {\n /* not a plain scalar: quoted below */\n }\n return JSON.stringify(s);\n}\n\nexport function renderDraft(\n root: string,\n project: string,\n d: Discovery\n): string {\n const live = d.candidates.filter((c) => c.live);\n const rest = d.candidates.filter((c) => !c.live);\n const liveProfile = d.profiles.find((p) => p.live);\n const L: string[] = [\n `# mcproc manifest draft, generated on ${new Date().toISOString().slice(0, 10)} from ${root}`,\n '#',\n ...(liveProfile\n ? [\n `# Live apps below come from turbo's persistent dev task and form the ${liveProfile.name} profile: start ${liveProfile.name} runs them.`,\n '# The other candidates are commented out. Uncomment the ones your dev stack needs,',\n ]\n : [\n '# Candidates below are commented out. Uncomment the ones your dev stack needs,',\n ]),\n '# write a description for each app, then run start + ls to confirm the ports; fix; repeat.',\n '# Fields: kind build|server|worker|task (task = runs once, e.g. a build or a migration; ls shows done/failed); run = shell command; cwd relative to the project root;',\n '# port/ports = declared listening ports; watch = pm2 watch paths (restart a server when its',\n '# build output changes); depends_on = start order; profiles = named groups of apps;',\n '# url = the address to open in a browser; ls/describe show it with the HTTP answer, monit shows it;',\n '# hosts = where this project also runs (ssh alias from ~/.ssh/config and/or docker container);',\n '# host = the one host an app always runs on (e.g. a dev container); without it the app runs where --host points.',\n ];\n for (const n of d.notes) L.push(`# note: ${n}`);\n L.push(\n 'version: 1',\n `mcproc: ${VERSION} # the mcproc that wrote this draft`,\n `project: ${yamlStr(project)}`,\n 'apps:'\n );\n if (d.candidates.length === 0)\n L.push(\n ' # no launch candidates found; add apps by hand, e.g.',\n ' # api:',\n ' # description: HTTP API',\n ' # run: npm run dev',\n ' # port: 3000'\n );\n const trailer = (c: Candidate) =>\n `# source: ${c.source}; kind? ${c.kind}${c.port ? `; port? ${c.port}` : ''}`;\n /** The field lines of a candidate under prefix p; its note goes last, as a comment. */\n const body = (c: Candidate, p: string): string[] => {\n // an empty description still has to read as a YAML string once uncommented\n const out = [`${p}description: ${yamlStr(c.description ?? '')}`];\n if (c.kind !== 'unknown') out.push(`${p}kind: ${c.kind}`);\n out.push(`${p}run: ${yamlStr(c.run)}`);\n if (c.cwd !== '.') out.push(`${p}cwd: ${yamlStr(c.cwd)}`);\n if (c.port) out.push(`${p}port: ${c.port}`);\n if (c.port && c.kind !== 'worker')\n out.push(`${p}url: http://localhost:${c.port}`);\n if (c.depends_on?.length)\n out.push(\n `${p}depends_on: [${c.depends_on.map((x) => `{ app: ${yamlStr(x.app)}, condition: ${x.condition}, timeout: ${x.timeout} }`).join(', ')}]`\n );\n if (c.note) out.push(`${p}# ${c.note}`);\n return out;\n };\n for (const c of live)\n L.push(` ${yamlStr(c.name)}: ${trailer(c)}`, ...body(c, ' '));\n if (live.length && rest.length)\n L.push(' # --- other scripts (commented out) ---');\n // a commented candidate's description is left for the human to write\n for (const c of rest)\n L.push(\n ` # ${yamlStr(c.name)}: ${trailer(c)}`,\n ...body({ ...c, description: '' }, ' # ')\n );\n L.push('profiles:');\n for (const p of d.profiles)\n L.push(\n ` ${p.live ? '' : '# '}${yamlStr(p.name)}: [${p.apps.map(yamlStr).join(', ')}]`\n );\n if (!liveProfile) L.push(' # base: [api-build, api]');\n L.push(\n 'hosts:',\n ' # stand: { ssh: my-alias, cwd: /srv/project }',\n ' # prod: { ssh: prod-alias, cwd: /srv/project, readonly: true }',\n ''\n );\n return L.join('\\n');\n}\n\nexport const README_TEMPLATE = `# .mcproc notes\n\nFree-form notes about running this project: what the apps are, how they fit together,\nwhich services are external (databases, queues), what to check after a start.\nmcproc returns this file from describe (called without an app).\n`;\n\n/** Whether a manifest's text marks the local host readonly — read from the YAML itself, so a manifest that does not validate still counts. */\nfunction localReadonly(text: string): boolean {\n try {\n const raw = parseYaml(text) as {\n hosts?: { local?: { readonly?: unknown } };\n } | null;\n return raw?.hosts?.local?.readonly === true;\n } catch {\n return false;\n }\n}\n\nexport function initProject(\n rootIn: string,\n opts: { force?: boolean } = {}\n): InitResult {\n const root = path.resolve(rootIn);\n if (!fs.existsSync(root))\n throw new McprocError(\n 'MANIFEST_NOT_FOUND',\n `Project directory does not exist: ${root}`\n );\n const dir = path.join(root, '.mcproc');\n const file = path.join(root, MANIFEST_REL);\n if (fs.existsSync(file) && !opts.force) {\n throw new McprocError('ALREADY_EXISTS', `${file} already exists`, {\n hint: \"Overwrite the draft with force (README and .gitignore are kept), or keep it and adopt the running apps' ports into it.\",\n });\n }\n if (fs.existsSync(file) && localReadonly(fs.readFileSync(file, 'utf8'))) {\n throw new McprocError(\n 'READONLY_HOST',\n `${file} declares the local host readonly; init does not replace it, not even with force`,\n {\n hint: 'Edit the manifest by hand, or remove hosts.local.readonly first if replacing it is really meant.',\n }\n );\n }\n fs.mkdirSync(dir, { recursive: true });\n const created: string[] = [];\n const gi = path.join(dir, '.gitignore');\n if (!fs.existsSync(gi) || fs.readFileSync(gi, 'utf8').trim() !== '*') {\n fs.writeFileSync(gi, '*\\n');\n created.push(gi);\n }\n const readme = path.join(dir, 'README.md');\n if (!fs.existsSync(readme)) {\n fs.writeFileSync(readme, README_TEMPLATE);\n created.push(readme);\n }\n const d = discover(root);\n fs.writeFileSync(file, renderDraft(root, defaultProject(root), d));\n created.push(file);\n const by_source: Record<string, number> = {};\n for (const c of d.candidates) {\n const k = c.source.split(':')[0].replace(/^.*\\//, '');\n by_source[k] = (by_source[k] ?? 0) + 1;\n }\n const live = d.candidates.filter((c) => c.live).map((c) => c.name);\n const profiles = d.profiles.filter((p) => p.live).map((p) => p.name);\n return {\n path: file,\n created,\n candidates: d.candidates.length,\n by_source,\n live,\n profiles,\n libs: d.libs,\n next: profiles.length\n ? `Edit ${file}: replace each TODO description, then run start ${profiles[0]} and ls to confirm the ports; the other scripts are commented out below.`\n : `Edit ${file}: uncomment the apps your dev stack needs, write a description for each, then run start <app|profile> and ls to confirm the ports.`,\n };\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\n// biome-ignore lint/suspicious/noExplicitAny: package.json, turbo.json and the like are untyped data, probed field by field\nexport function readJson(p: string): any | null {\n try {\n return JSON.parse(fs.readFileSync(p, 'utf8'));\n } catch {\n return null;\n }\n}\n\n/** turbo.json: turbo 2 writes `tasks`, turbo 1 `pipeline`; a persistent task is one that keeps running (a dev server). */\nexport interface TurboConfig {\n version: 1 | 2;\n tasks: string[];\n persistent: string[];\n}\nexport function readTurbo(root: string): TurboConfig | null {\n const raw = readJson(path.join(root, 'turbo.json'));\n const tasks = raw?.tasks ?? raw?.pipeline;\n if (!tasks || typeof tasks !== 'object' || Array.isArray(tasks)) return null;\n const names = Object.keys(tasks);\n return {\n version: raw.tasks ? 2 : 1,\n tasks: names,\n persistent: names.filter((t) => tasks[t]?.persistent === true),\n };\n}\n\n/** A workspace package as init sees it: its scripts, the workspace packages it depends on, whether it is consumed from dist/. */\nexport interface WsPackage {\n name: string;\n dir: string;\n scripts: Record<string, string>;\n deps: string[];\n distLib: boolean;\n}\n\nconst DIST = /^\\.?\\/?dist\\//;\nconst strings = (v: unknown): string[] =>\n typeof v === 'string'\n ? [v]\n : v && typeof v === 'object'\n ? Object.values(v as Record<string, unknown>).flatMap(strings)\n : [];\n/** A library built into dist/: it has a build script and an entry point (main, module, types or any exports target) under dist/. */\nexport function isDistLib(pkg: {\n scripts?: Record<string, string>;\n main?: unknown;\n module?: unknown;\n types?: unknown;\n exports?: unknown;\n}): boolean {\n if (!pkg.scripts?.build) return false;\n return [pkg.main, pkg.module, pkg.types, ...strings(pkg.exports)].some(\n (s) => typeof s === 'string' && DIST.test(s)\n );\n}\n\nexport function loadWorkspace(root: string, dirs: string[]): WsPackage[] {\n const out: WsPackage[] = [];\n for (const dir of dirs) {\n const pkg = readJson(path.join(dir, 'package.json'));\n if (!pkg) continue;\n const deps = new Set<string>();\n for (const k of ['dependencies', 'devDependencies', 'peerDependencies'])\n for (const d of Object.keys(pkg[k] ?? {})) deps.add(d);\n out.push({\n name: String(pkg.name ?? path.basename(dir)),\n dir: path.relative(root, dir) || '.',\n scripts: { ...(pkg.scripts ?? {}) },\n deps: [...deps],\n distLib: isDistLib(pkg),\n });\n }\n return out;\n}\n\n/** The dist libraries a package reaches through workspace dependencies, itself excluded; cycles are walked once. */\nexport function dependsOnDistLib(\n pkg: WsPackage,\n all: WsPackage[],\n libs: Set<string>\n): string[] {\n const byName = new Map(all.map((p) => [p.name, p]));\n const seen = new Set<string>([pkg.name]);\n const found: string[] = [];\n const queue = [...pkg.deps];\n while (queue.length) {\n const n = queue.shift()!;\n if (seen.has(n)) continue;\n seen.add(n);\n const p = byName.get(n);\n if (!p) continue;\n if (libs.has(n)) found.push(n);\n queue.push(...p.deps);\n }\n return found;\n}\n\n/** How turbo is invoked for the package manager `pmFor` detected. */\nexport function turboBin(pm: string): string {\n if (pm === 'yarn') return 'yarn turbo';\n if (pm === 'pnpm') return 'pnpm exec turbo';\n if (pm === 'bun run') return 'bunx turbo';\n return 'npx turbo';\n}\n\n/**\n * One folder filter per globbed workspace folder whose packages with a build script are all folded libraries. A\n * library elsewhere, or in a folder that also holds another package with a build script (an app, a library live\n * through its own dev task, a package not built into dist/), is filtered by name: the folder filter would build and\n * watch that package too, a build nobody asked for, or a second writer beside its own dev task (`next build` under\n * `next dev`, which share `.next/`). `all` is every workspace package, the folded ones included.\n */\nexport function libsFilters(\n libs: WsPackage[],\n globParents: string[],\n all: WsPackage[] = []\n): string[] {\n const folded = new Set(libs.map((l) => l.name));\n const shared = new Set(\n all\n .filter((p) => p.scripts.build && !folded.has(p.name))\n .map((p) => path.dirname(p.dir))\n );\n const out: string[] = [];\n for (const l of libs) {\n const parent = path.dirname(l.dir);\n const f =\n globParents.includes(parent) && !shared.has(parent)\n ? `--filter='./${parent}/*'`\n : `--filter=${l.name}`;\n if (!out.includes(f)) out.push(f);\n }\n return out;\n}\n","import fs from 'node:fs';\nimport { isMap, isScalar, isSeq, parse, parseDocument } from 'yaml';\nimport { McprocError } from './errors.js';\nimport { type Fleet, type HostError, listFleet } from './fleet.js';\nimport type { LsRow } from './list.js';\nimport { type Manifest, parseManifest } from './manifest.js';\nimport { loadOverride } from './override.js';\nimport { pickHost } from './resolve.js';\n\n/** Linux hands out ports from here for outgoing connections: a listener there is almost always transient. */\nexport const EPHEMERAL_FROM = 32768;\nexport interface Adopted {\n app: string;\n host: string;\n ports: number[];\n}\nexport interface Skipped {\n app: string;\n host: string;\n ports: number[];\n reason: string;\n}\n\n/**\n * Which undeclared ports each running app may take: not ephemeral, not declared by another app. A port taken earlier in\n * the same run counts as declared by the app that took it, so two apps never adopt one port; a port `m` declares for\n * the app itself is left out.\n */\nexport function planAdoption(\n rows: LsRow[],\n m: Manifest\n): { adopted: Adopted[]; skipped: Skipped[] } {\n const declaredBy = new Map<number, string>();\n for (const [n, a] of Object.entries(m.apps))\n for (const p of a.ports) declaredBy.set(p, n);\n const adopted: Adopted[] = [];\n const skipped: Skipped[] = [];\n for (const r of rows) {\n const take: number[] = [];\n const eph: number[] = [];\n for (const p of r.ports.undeclared) {\n const by = declaredBy.get(p);\n // the plan's manifest may be newer than the one the row was read against: what the app declares there is not undeclared\n if (by === r.app) continue;\n if (p >= EPHEMERAL_FROM) eph.push(p);\n else if (by)\n skipped.push({\n app: r.app,\n host: r.host,\n ports: [p],\n reason: `declared by ${by}`,\n });\n else take.push(p);\n }\n for (const p of take) declaredBy.set(p, r.app);\n if (take.length) adopted.push({ app: r.app, host: r.host, ports: take });\n if (eph.length)\n skipped.push({\n app: r.app,\n host: r.host,\n ports: eph,\n reason: 'ephemeral',\n });\n }\n return { adopted, skipped };\n}\n\n/** [start, end of the node's own text, end including what trails it] as the yaml library records it */\ntype Range = [number, number, number];\nconst rangeOf = (n: unknown): Range | undefined =>\n (n as { range?: Range } | null)?.range;\nconst lineStart = (t: string, at: number) => t.lastIndexOf('\\n', at - 1) + 1;\nconst lineEnd = (t: string, at: number) => {\n const i = t.indexOf('\\n', at);\n return i < 0 ? t.length : i;\n};\n/** Step back to the last non-blank character: a block node's range runs past its closing newline. */\nconst contentEnd = (t: string, at: number) => {\n let e = at;\n while (e > 0 && /\\s/.test(t[e - 1])) e--;\n return e;\n};\n/**\n * The end of the line holding `at`, carried over the comment lines right below it indented at least `min` columns: a\n * block's commented-out tail (` # - db`). A blank line, or any line left of `min` (the next key, the next app's\n * header comment, a top-level section comment), ends it. The yaml library's range[2] does not stop there: it runs\n * through every blank line and comment up to the next key.\n */\nconst tailEnd = (t: string, at: number, min: number) => {\n let end = lineEnd(t, at);\n while (end < t.length) {\n const next = lineEnd(t, end + 1);\n const line = t.slice(end + 1, next);\n const body = line.trimStart();\n if (!body.startsWith('#') || line.length - body.length < min) break;\n end = next;\n }\n return end;\n};\n\n/** A line's lead-in without the anchors and tags in it: a node's range starts after them. */\nconst noProps = (lead: string) => lead.replace(/[&!][^\\s]*\\s+/g, '');\n\nconst NOT_EDITABLE = 'not editable in place (alias or unusual key)';\nconst ALREADY_DECLARED = 'already declared in the file';\nconst ANCHORED = 'its edit would change another value through a YAML anchor';\n\nexport interface Splice {\n text: string;\n /** the apps whose ports were written in */\n edited: string[];\n /** the apps left as they were, and why */\n unedited: { app: string; reason: string }[];\n}\n\n/**\n * The manifest text with the adopted ports written in. Edits are spliced at the YAML nodes' own byte offsets, from the\n * end of the text backwards, so every other byte (comments, spacing, key order) stays as it was; re-serialising the\n * document instead would move comments.\n * - `port: N` becomes `ports: [N, …]` in place; a one-line flow `ports` list is rewritten, sorted, between its brackets;\n * a flow list over several lines (which may hold comments) gets `, N` after its last item.\n * - A block `ports` list gets a `- N` line in front of the first larger item, or after the list and the commented-out\n * items that trail it.\n * - An app with no port yet gets `port: N` (one port) or `ports: […]` as a new field after its last one: a line of its\n * own in a block map, after any commented-out entries that close the last field's block; `, field` before the\n * closing brace of a flow map.\n * An app that is an alias, or whose ports are all in the text already, is left alone and listed in `unedited`; so is\n * one whose edit would reach another value through a YAML anchor (see `spliceManifest`).\n */\nfunction spliceRaw(\n text: string,\n adopted: Adopted[]\n): Splice & { added: Map<string, number[]> } {\n const doc = parseDocument(text);\n // declared ports as the loader reads them, aliases resolved\n const js = doc.toJS() as {\n apps?: Record<string, { port?: number; ports?: number[] }>;\n };\n const appsNode = doc.get('apps', true);\n const byApp = new Map<string, number[]>();\n for (const a of adopted)\n byApp.set(a.app, [...(byApp.get(a.app) ?? []), ...a.ports]);\n const edits: { start: number; end: number; insert: string }[] = [];\n const insertAt = (at: number, insert: string) =>\n edits.push({ start: at, end: at, insert });\n const edited: string[] = [];\n const unedited: Splice['unedited'] = [];\n const addedBy = new Map<string, number[]>();\n for (const [name, ports] of byApp) {\n // the loader names an app by its key read as a string, so `1:` is app \"1\" here too\n const app = isMap(appsNode)\n ? appsNode.items.find(\n (p) => isScalar(p.key) && String(p.key.value) === name\n )?.value\n : undefined;\n if (!isMap(app) || app.items.length === 0) {\n unedited.push({ app: name, reason: NOT_EDITABLE });\n continue;\n }\n const own = js.apps?.[name] ?? {};\n const declared = own.ports ?? (own.port === undefined ? [] : [own.port]);\n const added = [...new Set(ports)]\n .filter((p) => !declared.includes(p))\n .sort((x, y) => x - y);\n if (added.length === 0) {\n unedited.push({ app: name, reason: ALREADY_DECLARED });\n continue;\n }\n edited.push(name);\n addedBy.set(name, added);\n const all = [...declared, ...added].sort((x, y) => x - y);\n const list = `[${all.join(', ')}]`;\n const pairOf = (k: string) =>\n app.items.find((p) => isScalar(p.key) && p.key.value === k);\n const target = pairOf('ports') ?? pairOf('port');\n if (target) {\n const kr = rangeOf(target.key)!;\n const v = target.value;\n const vr = rangeOf(v)!; // every value node has one, `ports: []` and a value on the next line included\n if (isSeq(v) && v.items.length > 0 && !v.flow) {\n const items = v.items.map((i) => ({\n r: rangeOf(i)!,\n n: isScalar(i) ? Number(i.value) : Number.NaN,\n }));\n // \" - \": the item's indent and dash, without an anchor or tag of its own (`- &main 3310`), which a new item\n // must not copy: a second `&main` would move every `*main` after it to the new port\n const prefix = (r: Range) =>\n noProps(text.slice(lineStart(text, r[0]), r[0]));\n const before = new Map<number, number[]>();\n const after: number[] = [];\n for (const p of added) {\n const k = items.findIndex((i) => i.n > p);\n if (k < 0) after.push(p);\n else before.set(k, [...(before.get(k) ?? []), p]);\n }\n for (const [k, ps] of before) {\n const r = items[k].r;\n insertAt(\n lineStart(text, r[0]),\n ps.map((p) => `${prefix(r)}${p}\\n`).join('')\n );\n }\n if (after.length) {\n const pre = prefix(items[items.length - 1].r);\n const dash = pre.length - pre.trimStart().length; // commented-out items sit at the items' own indent\n insertAt(\n tailEnd(text, contentEnd(text, vr[1]), dash),\n after.map((p) => `\\n${pre}${p}`).join('')\n );\n }\n } else if (\n isSeq(v) &&\n v.items.length > 0 &&\n text.slice(vr[0], vr[1]).includes('\\n')\n ) {\n const last = rangeOf(v.items[v.items.length - 1])!;\n insertAt(last[1], added.map((p) => `, ${p}`).join(''));\n } else {\n edits.push({ start: vr[0], end: vr[1], insert: list });\n if (isScalar(target.key) && target.key.value === 'port')\n edits.push({ start: kr[0], end: kr[1], insert: 'ports' });\n }\n continue;\n }\n const field =\n declared.length === 0 && all.length === 1\n ? `port: ${all[0]}`\n : `ports: ${list}`;\n const last = app.items[app.items.length - 1];\n const lr = rangeOf(last.value) ?? rangeOf(last.key)!;\n if (app.flow) {\n // the value's own end: with what trails it, a flow map over several lines would put the field in a comment\n insertAt(contentEnd(text, lr[1]), `, ${field}`);\n continue;\n }\n const kr = rangeOf(app.items[0].key)!;\n // the first key's column, without its anchor or tag (`&k description:`): a new `&k port:` would move every `*k`\n const indent = noProps(text.slice(lineStart(text, kr[0]), kr[0]));\n // under the last value's line and the commented-out entries that close its block, which sit deeper than the keys\n insertAt(\n tailEnd(text, contentEnd(text, lr[1]), indent.length + 1),\n `\\n${indent}${field}`\n );\n }\n let out = text;\n for (const e of edits.sort((x, y) => y.start - x.start))\n out = `${out.slice(0, e.start)}${e.insert}${out.slice(e.end)}`;\n return { text: out, edited, unedited, added: addedBy };\n}\n\n/** The text as the loader reads it, aliases resolved; undefined when it does not parse. */\nfunction readDoc(text: string): { value: unknown } | undefined {\n try {\n return { value: parse(text) };\n } catch {\n return undefined; // e.g. an alias whose anchor the splice rewrote away\n }\n}\n\nconst isRecord = (v: unknown): v is Record<string, unknown> =>\n typeof v === 'object' && v !== null && !Array.isArray(v);\n\n/** An app's ports as the loader reads them, `port` as a one-item list. */\nfunction portsOf(app: unknown): unknown[] {\n const o = isRecord(app) ? app : {};\n const v = o.ports ?? o.port;\n return v === undefined || v === null ? [] : Array.isArray(v) ? v : [v];\n}\n\n/** The document without the `port` and `ports` fields of the named apps. */\nfunction withoutPorts(doc: unknown, names: string[]): unknown {\n if (!isRecord(doc) || !isRecord(doc.apps)) return doc;\n const apps = { ...doc.apps };\n for (const n of names) {\n const a = apps[n];\n if (!isRecord(a)) continue;\n const { port: _port, ports: _ports, ...rest } = a;\n apps[n] = rest;\n }\n return { ...doc, apps };\n}\n\n/** Deep equality of parsed YAML; `seen` pairs the nodes already being compared, since an alias can make a cycle. */\nfunction sameValue(\n a: unknown,\n b: unknown,\n seen = new Map<object, object>()\n): boolean {\n if (Object.is(a, b)) return true;\n if (typeof a !== 'object' || typeof b !== 'object' || !a || !b) return false;\n if (Array.isArray(a) !== Array.isArray(b)) return false;\n if (seen.get(a) === b) return true;\n seen.set(a, b);\n const ka = Object.keys(a);\n const ra = a as Record<string, unknown>;\n const rb = b as Record<string, unknown>;\n return (\n ka.length === Object.keys(b).length &&\n ka.every((k) => Object.hasOwn(b, k) && sameValue(ra[k], rb[k], seen))\n );\n}\n\n/**\n * Whether a raw splice changed exactly what it meant to: every edited app now has its old ports plus the added ones,\n * and the rest of the document, every other field of every app included, reads as it did.\n */\nfunction changesOnlyPorts(\n before: { value: unknown },\n s: ReturnType<typeof spliceRaw>\n): boolean {\n const after = readDoc(s.text);\n if (!after) return false;\n const edited = [...s.added.keys()];\n if (\n !sameValue(\n withoutPorts(before.value, edited),\n withoutPorts(after.value, edited)\n )\n )\n return false;\n const appOf = (doc: unknown, n: string) =>\n isRecord(doc) && isRecord(doc.apps) ? doc.apps[n] : undefined;\n const sorted = (v: unknown[]) => JSON.stringify([...v].map(String).sort());\n return edited.every(\n (n) =>\n sorted(portsOf(appOf(after.value, n))) ===\n sorted([...portsOf(appOf(before.value, n)), ...s.added.get(n)!])\n );\n}\n\n/**\n * `spliceRaw`, checked: a node the splice edits can be read elsewhere through a YAML anchor (`ports: &p [3310]` read\n * by another app as `*p`, `port: &p 3000` read by a `watch_delay: *p`, an anchored app map, an anchored `port` key\n * whose alias reads the key's own text, an anchored list item a rewrite would drop), and editing it in place would\n * change or break every alias of it. The spliced text is parsed again; an app whose edit changes anything but its own\n * ports, or does not give it exactly its old ports plus the added ones, is left alone with that reason, and the rest\n * are spliced again without it until the check holds.\n */\nexport function spliceManifest(text: string, adopted: Adopted[]): Splice {\n const before = readDoc(text);\n if (!before) {\n // nothing to check against; the loader refuses such a text before anything is written\n const { added: _, ...s } = spliceRaw(text, adopted);\n return s;\n }\n const anchored = new Set<string>();\n for (;;) {\n const rest = adopted.filter((a) => !anchored.has(a.app));\n const s = spliceRaw(text, rest);\n if (changesOnlyPorts(before, s)) {\n // in the order the apps were adopted, like the raw splice reports them\n const why = new Map(s.unedited.map((u) => [u.app, u.reason]));\n for (const n of anchored) why.set(n, ANCHORED);\n const unedited = [...new Set(adopted.map((a) => a.app))]\n .filter((n) => why.has(n))\n .map((n) => ({ app: n, reason: why.get(n)! }));\n return { text: s.text, edited: s.edited, unedited };\n }\n // the culprits are the apps whose edit alone breaks the check; if only edits together do, none of them is kept\n const alone = s.edited.filter(\n (n) =>\n !changesOnlyPorts(\n before,\n spliceRaw(\n text,\n rest.filter((a) => a.app === n)\n )\n )\n );\n for (const n of alone.length ? alone : s.edited) anchored.add(n);\n }\n}\n\n/**\n * A line diff with one line of context on each side of a change and a `…` line between hunks that are not next to each\n * other; [] when the texts are equal.\n */\nexport function lineDiff(before: string, after: string): string[] {\n const a = before.split('\\n');\n const b = after.split('\\n');\n const n = a.length;\n const m = b.length;\n const lcs: number[][] = Array.from({ length: n + 1 }, () =>\n new Array<number>(m + 1).fill(0)\n );\n for (let i = n - 1; i >= 0; i--)\n for (let j = m - 1; j >= 0; j--)\n lcs[i][j] =\n a[i] === b[j]\n ? lcs[i + 1][j + 1] + 1\n : Math.max(lcs[i + 1][j], lcs[i][j + 1]);\n const ops: string[] = [];\n let i = 0;\n let j = 0;\n while (i < n || j < m) {\n if (i < n && j < m && a[i] === b[j]) {\n ops.push(` ${a[i]}`);\n i++;\n j++;\n } else if (i < n && (j >= m || lcs[i + 1][j] >= lcs[i][j + 1]))\n ops.push(`-${a[i++]}`); // on a tie the old line goes first, as diff prints a replaced line\n else ops.push(`+${b[j++]}`);\n }\n const changed = (k: number) => k >= 0 && k < ops.length && ops[k][0] !== ' ';\n const out: string[] = [];\n let prev = -1;\n for (let k = 0; k < ops.length; k++) {\n if (!changed(k) && !changed(k - 1) && !changed(k + 1)) continue;\n if (out.length > 0 && k !== prev + 1) out.push('…');\n out.push(ops[k]);\n prev = k;\n }\n return out;\n}\n\nexport interface AdoptResult {\n path: string;\n written: boolean;\n adopted: Adopted[];\n skipped: Skipped[];\n errors: HostError[];\n diff: string[];\n}\n\n/**\n * Write the ports `ls` reports as undeclared into the manifest: the hosts are probed like `ls` (an unreachable host is\n * an error entry; its apps are left alone), the plan is made against the text read before probing and spliced into\n * it, and nothing is written when the file changed meanwhile, when there is nothing to adopt, or when no app could be\n * edited in place.\n */\nexport async function adoptPorts(fleet: Fleet): Promise<AdoptResult> {\n const m = fleet.manifest;\n if (pickHost(m, 'local').readonly)\n throw new McprocError(\n 'READONLY_HOST',\n `${m.path} declares the local host readonly; its ports are not adopted`,\n {\n hint: 'Edit the manifest by hand, or remove hosts.local.readonly first.',\n }\n );\n const before = fs.readFileSync(m.path, 'utf8');\n // the text that will be edited, not the copy the fleet loaded earlier: a port declared in between is seen\n const current = parseManifest(before, m.root, m.path, loadOverride(m.root));\n // ports come from the listener sections, which the light probe keeps: no CPU sample, tree metrics or URL checks\n const { rows, errors } = await listFleet(fleet, fleet.select(['all']), {\n cpu: 'none',\n metrics: 'none',\n urls: 'none',\n });\n const plan = planAdoption(rows, current);\n const splice = spliceManifest(before, plan.adopted);\n const why = new Map(splice.unedited.map((u) => [u.app, u.reason]));\n const adopted = plan.adopted.filter((a) => !why.has(a.app));\n const skipped = [\n ...plan.skipped,\n ...plan.adopted\n .filter((a) => why.has(a.app))\n .map((a) => ({ ...a, reason: why.get(a.app)! })),\n ];\n if (splice.text === before)\n return { path: m.path, written: false, adopted, skipped, errors, diff: [] };\n try {\n parseManifest(splice.text, m.root, m.path, loadOverride(m.root)); // never write a manifest the loader would refuse\n } catch (e) {\n const issues = (e as McprocError).details;\n const reason = Array.isArray(issues)\n ? issues.join('; ')\n : (e as Error).message;\n throw new McprocError(\n 'MANIFEST_INVALID',\n `adopting the ports would make ${m.path} invalid, so nothing was written: ${reason}`,\n {\n hint: 'Add the ports by hand; ls lists them under ports.undeclared.',\n }\n );\n }\n if (fs.readFileSync(m.path, 'utf8') !== before)\n throw new McprocError(\n 'ALREADY_EXISTS',\n `${m.path} changed while the ports were being probed; nothing written`,\n { hint: 'Run the adoption again.' }\n );\n fs.writeFileSync(m.path, splice.text);\n return {\n path: m.path,\n written: true,\n adopted,\n skipped,\n errors,\n diff: lineDiff(before, splice.text),\n };\n}\n","import { describeError, isMcprocError } from './errors.js';\nimport {\n listFleet,\n type Fleet,\n type HostError,\n type HostProbe,\n} from './fleet.js';\nimport type { LsRow } from './list.js';\nimport { findProcess, isRunning } from './pm2.js';\nimport {\n compileReloadRules,\n detectReloads,\n reach,\n reloadCount,\n type ReloadCount,\n type ReloadInput,\n} from './reloads.js';\nimport { CONTEXT_BYTES, parseRead, readSnippet } from './incidents/cursor.js';\nimport { ensureOk } from '../transport/index.js';\nimport { shq } from '../transport/quote.js';\n\nconst STREAMS = ['out', 'err'] as const;\n\n/**\n * A log that exists but the host's user may not read measures as empty, which would count as an exact zero. Before\n * its reads the script names each such log by its read's id, and ends that part with UNREAD_END: never inside a read's\n * output, and after whatever a login shell prints first.\n */\nconst unreadMark = (id: number) => `__MCPROC_RL_UNREAD_${id}__`;\nconst UNREAD_END = '__MCPROC_RL_UNREAD_END__';\nconst unreadChecks = (reads: { id: number; log: string }[]): string[] => [\n ...reads.map(({ id, log }) => {\n const f = shq(log);\n return `[ ! -e ${f} ] || [ -r ${f} ] || echo ${unreadMark(id)}`; // a missing log is no failure: nothing written yet\n }),\n `echo ${UNREAD_END}`,\n];\nfunction unreadIds(stdout: string): Set<number> {\n const end = stdout.indexOf(`${UNREAD_END}\\n`);\n return new Set(\n [\n ...(end < 0 ? '' : stdout.slice(0, end)).matchAll(\n /^__MCPROC_RL_UNREAD_(\\d+)__$/gm\n ),\n ].map((m) => Number(m[1]))\n );\n}\n\n/**\n * Each running app's in-process reloads since pm2 started it (ls --reloads), on top of the rows and probes of listFleet:\n * one read script per host over the out and err logs of its apps that run with reloads on and a known start (at most the\n * last READ_CAP bytes of each), hosts in parallel. The count is partial when a stream's read does not reach back to the\n * start; the first `listening`-only burst is taken for the boot only when one does. Rows of other apps come back as they\n * were; a host whose read fails, an app with a log that exists but may not be read, or an app whose own reloads patterns\n * run away keeps its rows without a count and is named in errors. `budgetMs`: how long an app's own patterns may take\n * (default MATCH_BUDGET_MS).\n */\nexport async function countReloads(\n fleet: Fleet,\n probes: HostProbe[],\n rows: LsRow[],\n opts: { budgetMs?: number } = {}\n): Promise<{ rows: LsRow[]; errors: HostError[] }> {\n const counted = new Map<string, ReloadCount>();\n const perHost = await Promise.all(\n probes.map(async (p): Promise<HostError[]> => {\n const { ctx, snap } = p;\n if (!ctx || !snap) return []; // a host the probe did not reach is already in the errors\n const targets = rows.flatMap((row) => {\n const settings = fleet.manifest.apps[row.app]?.reloads;\n const proc = findProcess(snap.procs, fleet.manifest.project, row.app);\n return row.host === p.host &&\n p.apps.includes(row.app) &&\n settings &&\n proc &&\n row.started !== null &&\n isRunning(row.status)\n ? [\n {\n app: row.app,\n started: row.started,\n settings,\n logs: [proc.out_log, proc.err_log],\n },\n ]\n : [];\n });\n if (targets.length === 0) return [];\n const id = (k: number, s: number) => k * STREAMS.length + s;\n const files = targets.flatMap((t, k) =>\n t.logs.map((log, s) => ({ id: id(k, s), log }))\n );\n let stdout: string;\n try {\n stdout = ensureOk(\n await ctx.transport.exec(\n [\n ...unreadChecks(files),\n ...files.map((f) => readSnippet(f.id, f.log, null, null)),\n ].join('; ')\n ),\n ctx.host,\n 'read logs for reloads'\n ).stdout;\n } catch (e) {\n return [\n {\n host: p.host,\n apps: targets.map((t) => t.app),\n message: `reloads not counted: ${describeError(e)}`,\n },\n ];\n }\n const errors: HostError[] = [];\n const unread = unreadIds(stdout);\n targets.forEach((t, k) => {\n const denied = t.logs.filter((_, s) => unread.has(id(k, s)));\n if (denied.length) {\n errors.push({\n host: p.host,\n apps: [t.app],\n message: `reloads not counted: cannot read ${denied.length > 1 ? `the logs ${denied.join(' and ')}` : `the log ${denied[0]}`} of ${t.app}`,\n });\n return;\n }\n const reads = STREAMS.map((_, s) => parseRead(stdout, id(k, s), null));\n // a read that did not come through whole reaches nowhere; one begins CONTEXT_BYTES before its start, at byte 0 at the earliest\n const reaches = reads.map((r) =>\n r && !r.short\n ? reach(r.lines, t.started, r.start <= CONTEXT_BYTES)\n : 'after'\n );\n const input: ReloadInput[] = reads.flatMap((r, s) =>\n r && !r.short\n ? r.lines.map((text) => ({ stream: STREAMS[s], text }))\n : []\n );\n const rules = compileReloadRules(t.settings, opts.budgetMs);\n try {\n counted.set(\n t.app,\n reloadCount(reaches, (coversStart) =>\n detectReloads(input, rules, {\n app: t.app,\n start: t.started,\n coversStart,\n })\n )\n );\n } catch (e) {\n if (!isMcprocError(e) || e.code !== 'TIMEOUT') throw e;\n errors.push({\n host: p.host,\n apps: [t.app],\n message: `reloads not counted: ${describeError(e)}`,\n }); // its own patterns ran away: this app goes without a count, the others are counted\n }\n });\n return errors;\n })\n );\n return {\n rows: rows.map((r) => {\n const c = counted.get(r.app);\n return c ? { ...r, reloads: c } : r;\n }),\n errors: perHost.flat(),\n };\n}\n\n/**\n * What `ls` answers: the rows of the named apps from listFleet, and with `reloads` each running app's reloads counted\n * on top (countReloads, one more read per host). `errors`: the hosts not probed, then the logs not read or counted;\n * `unread`: those last ones alone, which the table names beside the rows. Without `reloads` it is listFleet as is.\n */\nexport async function listWithReloads(\n fleet: Fleet,\n names: string[],\n reloads: boolean\n): Promise<{ rows: LsRow[]; errors: HostError[]; unread: HostError[] }> {\n const listed = await listFleet(fleet, names, {\n containers: 'probe',\n });\n if (!reloads) return { rows: listed.rows, errors: listed.errors, unread: [] };\n const r = await countReloads(fleet, listed.probes, listed.rows);\n return {\n rows: r.rows,\n errors: [...listed.errors, ...r.errors],\n unread: r.errors,\n };\n}\n","import { fileURLToPath } from 'node:url';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { VERSION } from '../version.js';\nimport type { Spawner } from '../transport/types.js';\nimport type { UnpackDeps } from '../runtime/unpack.js';\nimport type { HereCheck } from '../core/urlcheck.js';\nimport { registerReadTools } from './tools/read.js';\nimport { registerWriteTools } from './tools/write.js';\nimport { registerStandTools } from './tools/stands.js';\n\nexport const INSTRUCTIONS = [\n 'mcproc drives pm2 for the current project from its .mcproc/mcproc.yaml manifest (apps with descriptions, declared ports, profiles, hosts).',\n 'Loop: (1) no manifest → call init, then fill in a description per app in .mcproc/mcproc.yaml and verify with start + ls (ports) + logs; a port ls reports as undeclared is adopted into the manifest with init adopt_ports.',\n '(2) manifest present → call describe first, then act by app or profile name: start, restart, stop, logs. ls answers \"is it up and on which port\"; ports answers \"who holds port N\".',\n 'On long work with running apps, call incidents now and then: it returns only new errors with context, each once, and is nearly free when nothing happened.',\n 'After start, call wait (until listening, url-ok, exited, log:<regex>, idle:<seconds> or reloaded) instead of sleeping or polling ls; for an app that reloads in place, after an edit, wait until reloaded; depends_on conditions wait by themselves.',\n \"start may answer queued with a position when the host cannot hold the stand yet: a watcher brings it up in FIFO order; wait on one of its apps as usual, and leases shows the host's queue, estimates and the watcher.\",\n \"exec runs one-off work (a test run, a build) from the project root in the stand's environment, under a memory lease when it is heavy; worktree_add makes an isolated checkout with its own slot and ports, then every call for it passes project: <its path>.\",\n 'After a change, read logs with since over the profile (since: \"2m\", or \"last\" for everything since your previous logs call) instead of tailing each app.',\n 'Apps with `host:` in the manifest always run on that host; without a host argument every app is reached where it runs (others on local), with one only the apps that run there. Readonly hosts refuse changes. doctor explains why a host cannot be driven; unpack brings pm2 (and Node when missing) to a host that has none.',\n 'Never compose pm2 or shell commands by hand for apps the manifest knows.',\n].join(' ');\n\nexport function createServer(\n deps: {\n spawner?: Spawner;\n unpack?: UnpackDeps;\n project?: string;\n hereCheck?: HereCheck;\n } = {}\n): McpServer {\n const server = new McpServer(\n { name: 'mcproc', version: VERSION },\n { instructions: INSTRUCTIONS }\n );\n const roots = async (): Promise<string[]> => {\n try {\n if (!server.server.getClientCapabilities()?.roots) return [];\n const r = await server.server.listRoots();\n return r.roots.map((x) =>\n x.uri.startsWith('file://') ? fileURLToPath(x.uri) : x.uri\n );\n } catch {\n return [];\n }\n };\n registerReadTools(server, {\n roots,\n spawner: deps.spawner,\n unpack: deps.unpack,\n project: deps.project,\n hereCheck: deps.hereCheck,\n });\n registerWriteTools(server, {\n roots,\n spawner: deps.spawner,\n unpack: deps.unpack,\n project: deps.project,\n hereCheck: deps.hereCheck,\n });\n registerStandTools(server, {\n roots,\n spawner: deps.spawner,\n unpack: deps.unpack,\n project: deps.project,\n hereCheck: deps.hereCheck,\n });\n return server;\n}\n\n/** `project`: what `mcp --project` named; tool calls without a project of their own use it. */\nexport async function serveStdio(project?: string): Promise<void> {\n const server = createServer({ project });\n await server.connect(new StdioServerTransport());\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { commonInput, MUT, RO, runTool, type ToolDeps } from '../common.js';\nimport { prepare, connect, type Context } from '../../core/resolve.js';\nimport { leasesView } from '../../core/leases/view.js';\nimport { portsReport, hostsInfo, describeProject } from '../../core/list.js';\nimport { Fleet, defaultConnector, describeFleetApp } from '../../core/fleet.js';\nimport { readLogs } from '../../core/logs.js';\nimport { listWithReloads } from '../../core/reloadcount.js';\nimport {\n LogMarks,\n parseSince,\n readSince,\n type SinceSpec,\n} from '../../core/logsince.js';\nimport { McprocError } from '../../core/errors.js';\nimport { doctor } from '../../core/doctor.js';\nimport { takeIncidents } from '../../core/incidents/store.js';\nimport { parseUntil, waitFor } from '../../core/wait.js';\nimport {\n renderLs,\n renderPorts,\n renderHosts,\n renderDoctor,\n renderLogs,\n renderLogsSince,\n fmtDeps,\n renderProject,\n renderIncidents,\n renderWait,\n renderLeases,\n hostsOf,\n urlNote,\n} from '../render.js';\n\nexport function registerReadTools(server: McpServer, deps: ToolDeps): void {\n const prep = async (args: { project?: string; host?: string }) =>\n prepare({\n project: args.project ?? deps.project,\n host: args.host,\n roots: await deps.roots(),\n });\n // apps run at their own host (`host:` in the manifest); host narrows a call to the apps that run there\n const fleetOf = async (args: { project?: string; host?: string }) =>\n new Fleet(\n prepare({\n project: args.project ?? deps.project,\n roots: await deps.roots(),\n }).manifest,\n args.host,\n defaultConnector(deps.spawner, deps.hereCheck)\n );\n\n server.registerTool(\n 'hosts',\n {\n title: 'Hosts',\n description:\n 'Hosts declared in the project manifest: transport, project cwd there, readonly flag. No network access.',\n inputSchema: { project: commonInput.project },\n annotations: RO,\n },\n (args) =>\n runTool(async () => {\n const { manifest } = await prep(args);\n const hosts = hostsInfo(manifest);\n return {\n text: renderHosts(hosts),\n data: { project: manifest.project, hosts },\n };\n })\n );\n\n server.registerTool(\n 'doctor',\n {\n title: 'Doctor',\n description:\n \"Check hosts: reachable, Node version, which pm2 would run and why, ps/ss/tar availability, the unpacked runtime, daemon state, the host's environment (container, hostname) and where each app's url answers (on the host or from this machine). Recommends unpack, hosts.<host>.pm2 or pm2_home when pm2 is missing or unusable, and url_check: auto for an app with url_check: host whose url answers only from this machine.\",\n inputSchema: commonInput,\n annotations: RO,\n },\n (args) =>\n runTool(async () => {\n const { manifest } = await prep({ project: args.project });\n const reports = await doctor(\n manifest,\n args.host,\n deps.spawner,\n deps.hereCheck\n );\n return {\n text: renderDoctor(reports),\n data: { project: manifest.project, reports },\n };\n })\n );\n\n server.registerTool(\n 'ls',\n {\n title: 'List apps',\n description:\n \"One row per manifest app, each from the host it runs on: pm2 status, pid, uptime, restarts, memory and CPU of the whole process tree, the runtime command, the ports it really listens on compared with the declared ones, and its URL with the HTTP answer (ok/error/down), requested on the app's host and, when the host gets no answer, from this machine: ✓ 200 (here), or ✗ down (refused) with the reason (url_check in the manifest pins one side). Answers \\\"is it up, on which port, which address do I open\\\". reloads: true also counts each running app's in-process reloads since its pm2 start (tsx/nodemon restarts, Vite/Next rebuilds, a repeated listening line), which pm2's restarts never show: RESTARTS 0 (+3), or 0 (+≥3) when the logs read did not reach back to the start.\",\n inputSchema: {\n ...commonInput,\n app: z.string().optional().describe('Only this app'),\n reloads: z\n .boolean()\n .optional()\n .describe(\n \"Also count each running app's in-process reloads since its pm2 start; costs one log read per host (default false)\"\n ),\n },\n annotations: RO,\n },\n (args) =>\n runTool(async () => {\n const fleet = await fleetOf(args);\n const { rows, errors, unread } = await listWithReloads(\n fleet,\n fleet.select(args.app ? [args.app] : ['all']),\n args.reloads ?? false\n );\n return {\n text: renderLs(rows, fleet.fallback, unread),\n data: {\n ...hostsOf(rows, fleet.fallback),\n project: fleet.manifest.project,\n rows,\n errors,\n },\n };\n })\n );\n\n server.registerTool(\n 'describe',\n {\n title: 'Describe',\n description:\n 'Call this first in a new session. Without app: project summary (apps with descriptions, profiles, hosts) plus .mcproc/README.md. With app: its manifest entry, runtime state, log paths, URL, ports and generated pm2 config. Without app it also lists the resolved vars with their sources and the override file, when the manifest declares vars.',\n inputSchema: { ...commonInput, app: z.string().optional() },\n annotations: RO,\n },\n (args) =>\n runTool(async () => {\n const fleet = await fleetOf(args);\n if (!args.app) {\n const d = describeProject(fleet.manifest);\n return {\n text: renderProject(d),\n data: d as unknown as Record<string, unknown>,\n };\n }\n const d = await describeFleetApp(fleet, args.app);\n const text = [\n `${d.app.name} [${d.app.kind}]: ${d.app.description}`,\n `run: ${d.app.run}`,\n `cwd: ${d.app.cwd}`,\n d.app.depends_on.length\n ? `depends_on: ${fmtDeps(d.app.depends_on)}`\n : '',\n renderLs([d.row], d.host),\n urlNote(d.row),\n `logs: ${d.logs ? `${d.logs.out} | ${d.logs.err}` : 'not started yet'}`,\n `pm2: ${JSON.stringify(d.pm2)}`,\n ]\n .filter(Boolean)\n .join('\\n');\n return { text, data: d as unknown as Record<string, unknown> };\n })\n );\n\n const marks = new LogMarks(); // one per server process: the marks of this client session\n const logsHint =\n 'logs {app: \"api\"} tails one app; logs {targets: [\"stack\"], since: \"2m\"} merges a profile since a time.';\n server.registerTool(\n 'logs',\n {\n title: 'Logs',\n description:\n 'Read pm2 logs. One app, last N lines (default 100, max 2000) as out/err sections: pass app. Several apps since a point in time: pass targets (apps, profiles or [\"all\"]) and since: a span like 2m, a time like 2026-10-14T07:30 (the host\\'s local time; add Z or +02:00 for an absolute instant), or last (everything since your previous logs call over those apps in this session). Lines come merged across apps in time order, each labelled `app | line` (`app ! line` for stderr), ANSI stripped; lines then caps the merged output (most recent kept). targets without since: the latest lines across the apps. After a change, read since over the profile instead of tailing each app.',\n inputSchema: {\n ...commonInput,\n app: z\n .string()\n .optional()\n .describe(\n 'One app (the sectioned tail), or with since the same as targets: [app]'\n ),\n targets: z\n .array(z.string())\n .min(1)\n .optional()\n .describe('Apps and/or profiles, or [\"all\"]'),\n since: z\n .string()\n .optional()\n .describe(\n '2m | 90s | 2h | 2026-10-14T07:30[:00[.000]][Z|+02:00] | last'\n ),\n lines: z.number().int().min(1).max(2000).optional(),\n stream: z.enum(['out', 'err', 'both']).optional(),\n },\n annotations: RO,\n },\n (args) =>\n runTool(async () => {\n // presence, not truthiness: an empty app or since is still passed, and refused as such\n const { app, targets } = args;\n if (targets !== undefined && app !== undefined)\n throw new McprocError(\n 'BAD_ARGUMENT',\n 'pass either app or targets, not both',\n { hint: logsHint }\n );\n // app alone is the sectioned tail, or with since the same as targets: [app]\n const wanted = targets ?? (app === undefined ? null : [app]);\n if (wanted === null)\n throw new McprocError(\n 'BAD_ARGUMENT',\n 'name an app, or targets (with since for a time window)',\n { hint: logsHint }\n );\n if (app !== undefined && args.since === undefined) {\n const fleet = await fleetOf(args);\n const ctx = await fleet.ctx(fleet.one(app));\n const r = await readLogs(ctx, app, {\n lines: args.lines,\n stream: args.stream,\n });\n return {\n text: renderLogs(r),\n data: { host: ctx.host.name, ...r } as unknown as Record<\n string,\n unknown\n >,\n };\n }\n // parsed before the fleet is built, so a bad since never reaches a host\n const since: SinceSpec =\n args.since !== undefined\n ? parseSince(args.since)\n : { kind: 'tail', n: args.lines ?? 100 };\n const fleet = await fleetOf(args);\n const names = fleet.select(wanted);\n const a = await readSince(fleet, names, {\n since,\n lines: args.lines,\n stream: args.stream,\n marks,\n });\n return {\n text: renderLogsSince(a),\n data: a as unknown as Record<string, unknown>,\n };\n })\n );\n\n server.registerTool(\n 'ports',\n {\n title: 'Ports',\n description:\n 'Who listens on which port on the host, including processes pm2 does not manage. With port: the holder of that port.',\n inputSchema: {\n ...commonInput,\n port: z.number().int().min(1).max(65535).optional(),\n },\n annotations: RO,\n },\n (args) =>\n runTool(async () => {\n const ctx = await connect(await prep(args), {\n spawner: deps.spawner,\n hereCheck: deps.hereCheck,\n });\n const r = await portsReport(ctx, args.port);\n return {\n text: renderPorts(r, ctx.host.name),\n data: { host: ctx.host.name, ...r },\n };\n })\n );\n\n server.registerTool(\n 'wait',\n {\n title: 'Wait',\n description:\n \"Block until an app is usable or finished. until: listening (every declared port is bound), url-ok (its url answers 2xx/3xx), exited (the process left online; with autorestart off, kind task included, the answer carries exit_code and done / failed (exit N) / stopped, any other app shows pm2's stopped or errored), log:<regex> (a new line matches; tested without pm2's time stamp, ANSI stripped, the answer keeps the stamp), idle:<seconds> (no log output for that long), reloaded (the next in-process reload: tsx/nodemon restart, Vite/Next rebuild, a repeated listening line; answered once quiet for 2 s with its time, line count and first restart or rebuild line; for a server whose reload restarts it, wait until: listening next). log:, idle: and reloaded see only output written after the call begins, so to know whether the app is up prefer listening or url-ok. Refused (BAD_ARGUMENT): listening with no declared port, url-ok with no url, reloaded with reloads: false. ok false with what was last seen on timeout (default 60 s, max 600) or when the process died meanwhile; a result, not an error. A pm2 restart in progress is waited out. Call it after start instead of sleeping or polling ls.\",\n inputSchema: {\n ...commonInput,\n app: z.string().describe('The app to wait for'),\n until: z\n .string()\n .describe(\n 'listening | url-ok | exited | log:<regex> | idle:<seconds> | reloaded'\n ),\n timeout_s: z\n .number()\n .int()\n .min(1)\n .max(600)\n .optional()\n .describe('Seconds to wait, default 60, max 600'),\n },\n annotations: RO,\n },\n (args, extra) =>\n runTool(async () => {\n const until = parseUntil(args.until); // a bad request is refused before any host is touched\n const fleet = await fleetOf(args);\n const ctx = await fleet.ctx(fleet.one(args.app));\n const r = await waitFor(ctx, args.app, until, {\n timeoutMs:\n args.timeout_s === undefined ? undefined : args.timeout_s * 1000,\n signal: extra.signal, // the client cancelled the call or went away: stop polling the host\n });\n return {\n text: renderWait(args.app, r),\n data: { app: args.app, host: ctx.host.name, ...r },\n };\n })\n );\n\n server.registerTool(\n 'leases',\n {\n title: 'Leases',\n description:\n \"The host's memory lease queue: every lease with its state (pending, starting, running, freed, cancelled, failed), position, project and slot, target, estimate and need, where the estimate came from, what the head waits for; plus the host's memory reading and whether the watcher runs. A start that answered queued shows up here; wait on one of its apps to block until it is up.\",\n inputSchema: { project: commonInput.project },\n annotations: RO,\n },\n (args) =>\n runTool(async () => {\n let ctx: Context | undefined;\n try {\n ctx = await connect(await prep({ project: args.project }), {\n spawner: deps.spawner,\n hereCheck: deps.hereCheck,\n });\n } catch {\n ctx = undefined; // no manifest here: the queue is the host's and still reads\n }\n const v = await leasesView(undefined, ctx);\n return {\n text: renderLeases(v),\n data: v as unknown as Record<string, unknown>,\n };\n })\n );\n\n server.registerTool(\n 'incidents',\n {\n title: 'Incidents',\n description:\n \"Only the errors that are NEW since they were last taken, each with lines of context before and after (a folded stack trace included), plus crashes and restarts. A call takes what it returns: the pick-up point, kept in .mcproc/incidents.json and shared by every session, agent and CLI call, moves past them, so nobody gets them twice; peek: true looks without taking. Take once you have dealt with them: the person's monit incidents screen shows taken ones muted. An answer carries about 20,000 characters of incidents, newest first; older ones past that are counted, not shown. A log clear (flush, or c in monit) starts incidents over from there. Cheap to poll: nothing new is one short line. During long work on running apps call it periodically, with your client's own loop/cron/monitor if it has one; read logs only for an incident worth a closer look. include_reloads: true adds each app's in-process reloads since the last call (tsx/nodemon restarts, Vite/Next rebuilds, a repeated listening line) as one reloaded incident per app with how many and when.\",\n inputSchema: {\n ...commonInput,\n app: z\n .string()\n .optional()\n .describe('An app or a profile; default all apps'),\n peek: z\n .boolean()\n .optional()\n .describe(\n 'Look without taking: the pick-up point stays (default false)'\n ),\n since: z\n .number()\n .int()\n .min(1)\n .max(1440)\n .optional()\n .describe(\n 'First call only: minutes to look back in each log (default 15)'\n ),\n max: z\n .number()\n .int()\n .min(1)\n .max(100)\n .optional()\n .describe('Most incidents returned, newest first (default 20)'),\n context: z\n .tuple([\n z.number().int().min(0).max(50),\n z.number().int().min(0).max(50),\n ])\n .optional()\n .describe('[lines before, lines after] (default per app, 3 and 5)'),\n include_reloads: z\n .boolean()\n .optional()\n .describe(\n \"Also report each app's in-process reloads since the last call, one reloaded incident per app (default false)\"\n ),\n },\n annotations: MUT(false, false), // taking writes the local pick-up point; nothing changes on the hosts\n },\n (args) =>\n runTool(async () => {\n const fleet = await fleetOf(args);\n const names = fleet.select([args.app ?? 'all']);\n const { answer } = await takeIncidents(fleet, names, {\n peek: args.peek,\n sinceMin: args.since,\n max: args.max,\n context: args.context,\n includeReloads: args.include_reloads,\n });\n return {\n text: renderIncidents(answer),\n data: answer as unknown as Record<string, unknown>,\n };\n })\n );\n}\n","import { z } from 'zod';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { isMcprocError, McprocError } from '../core/errors.js';\nimport type { Spawner } from '../transport/types.js';\nimport type { UnpackDeps } from '../runtime/unpack.js';\nimport type { HereCheck } from '../core/urlcheck.js';\n\nexport const commonInput = {\n project: z\n .string()\n .optional()\n .describe(\n 'Project root. Default: MCPROC_PROJECT, then CLAUDE_PROJECT_DIR, then the client roots, then the server cwd; the manifest is searched upward from there.'\n ),\n host: z\n .string()\n .optional()\n .describe(\n 'Host name from the manifest hosts: section. Omitted: every app is reached on the host it runs on (its `host:` in the manifest, local for apps without one). Given: only the apps that run on that host (bound to it, or without a `host:`); naming an app bound elsewhere is refused.'\n ),\n};\n/** `project`: the one the server was started for (`mcp --project`), used when a call names none. */\nexport interface ToolDeps {\n roots: () => Promise<string[]>;\n spawner?: Spawner;\n unpack?: UnpackDeps;\n project?: string;\n /** checks a url from this machine (tests pass a fake) */\n hereCheck?: HereCheck;\n}\n\nexport const RO = {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n} as const;\nexport const MUT = (destructive: boolean, idempotent: boolean) => ({\n readOnlyHint: false,\n destructiveHint: destructive,\n idempotentHint: idempotent,\n openWorldHint: false,\n});\n\n/** `isError` with data: the call did part of its work (a fleet mutation where a host failed); its rows still come back. */\nexport async function runTool(\n fn: () => Promise<{\n text: string;\n data: Record<string, unknown>;\n isError?: boolean;\n }>\n): Promise<CallToolResult> {\n try {\n const { text, data, isError } = await fn();\n return {\n ...(isError ? { isError: true } : {}),\n content: [{ type: 'text', text }],\n structuredContent: data,\n };\n } catch (e) {\n const err = isMcprocError(e)\n ? e\n : new McprocError(\n 'PM2_FAILED',\n e instanceof Error ? e.message : String(e)\n );\n return {\n isError: true,\n content: [\n {\n type: 'text',\n text: `${err.code}: ${err.message}${err.hint ? `\\nHint: ${err.hint}` : ''}`,\n },\n ],\n structuredContent: { error: err.toJSON() },\n };\n }\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { commonInput, MUT, runTool, type ToolDeps } from '../common.js';\nimport {\n prepare,\n assertWritable,\n resolveProjectDir,\n} from '../../core/resolve.js';\nimport { Fleet, defaultConnector, actOn, type Act } from '../../core/fleet.js';\nimport type { WaitRecord } from '../../core/actions.js';\nimport { clearLogs } from '../../core/incidents/store.js';\nimport { initProject } from '../../core/init.js';\nimport { adoptPorts } from '../../core/adopt.js';\nimport { cancelLease } from '../../core/leases/view.js';\nimport type { LsRow } from '../../core/list.js';\nimport { createTransport } from '../../transport/index.js';\nimport { unpack, defaultUnpackDeps } from '../../runtime/unpack.js';\nimport {\n renderUnpack,\n renderFlushed,\n renderMutation,\n renderAdopted,\n hostsOf,\n} from '../render.js';\n\nexport function registerWriteTools(server: McpServer, deps: ToolDeps): void {\n // apps run at their own host (`host:` in the manifest); host narrows a call to the apps that run there. Targets and\n // readonly hosts are checked before any host is contacted.\n const fleetOf = async (args: { project?: string; host?: string }) =>\n new Fleet(\n prepare({\n project: args.project ?? deps.project,\n roots: await deps.roots(),\n }).manifest,\n args.host,\n defaultConnector(deps.spawner, deps.hereCheck)\n );\n const targetInput = {\n ...commonInput,\n target: z.string().describe('App name, profile name, or \"all\"'),\n };\n const act = async (\n args: {\n project?: string;\n host?: string;\n target: string;\n reload?: boolean;\n note?: string;\n },\n what: Act,\n signal?: AbortSignal // the request's: aborted when the client cancels it or goes away\n ) => {\n const fleet = await fleetOf(args);\n const waits: WaitRecord[] = [];\n const rows: LsRow[] = await actOn(fleet, args.target, what, {\n reload: args.reload,\n note: args.note,\n waits,\n signal,\n });\n const { text, failed } = renderMutation(rows, fleet.fallback, what, waits);\n return {\n text,\n data: { ...hostsOf(rows, fleet.fallback), rows, waits } as Record<\n string,\n unknown\n >,\n isError: failed,\n };\n };\n\n server.registerTool(\n 'init',\n {\n title: 'Init manifest draft',\n description:\n 'Create .mcproc/ (gitignored) with a manifest DRAFT discovered from package.json scripts, workspaces, nx project.json, turbo.json, ecosystem.json and Procfile. On a turbo repo with a persistent dev task, the packages implementing it are drafted live (TODO descriptions to replace, a dev profile, libs/libs-watch builders for libraries consumed from dist/); every other candidate is commented out: uncomment, write descriptions, then verify with start + ls. Refuses to overwrite an existing manifest without force. With adopt_ports, instead write the ports ls reports as undeclared for the running apps into the existing manifest (comments kept) and return the diff; it needs that manifest, and force is ignored then.',\n inputSchema: {\n project: commonInput.project,\n force: z.boolean().optional(),\n adopt_ports: z.boolean().optional(),\n },\n annotations: MUT(true, true), // with force it replaces the manifest\n },\n (args) =>\n runTool(async () => {\n if (args.adopt_ports) {\n const r = await adoptPorts(await fleetOf(args));\n const { text, failed } = renderAdopted(r);\n return {\n text,\n data: r as unknown as Record<string, unknown>,\n isError: failed,\n };\n }\n const root = resolveProjectDir(\n args.project ?? deps.project,\n await deps.roots()\n );\n const r = initProject(root, { force: args.force });\n const src =\n Object.entries(r.by_source)\n .map(([k, v]) => `${k}: ${v}`)\n .join(', ') || 'none';\n return {\n text: `Created ${r.path} with ${r.candidates} candidate(s) (${src}).\\n${r.next}`,\n data: r as unknown as Record<string, unknown>,\n };\n })\n );\n\n server.registerTool(\n 'start',\n {\n title: 'Start',\n description:\n 'Start an app or profile via pm2 from the generated ecosystem, each app on the host it runs on, dependencies first. A dependency declared with condition ready or completed is waited for (up to its timeout) before the dependent starts, and a dependent whose dependency failed or timed out is skipped with the reason. Apps already online are left alone unless reload is true.',\n inputSchema: {\n ...targetInput,\n reload: z.boolean().optional(),\n note: z\n .string()\n .max(200)\n .optional()\n .describe('What this start is for, kept on its lease'),\n },\n annotations: MUT(false, true),\n },\n (args, extra) =>\n runTool(async () => {\n return act(args, 'start', extra.signal);\n })\n );\n\n server.registerTool(\n 'restart',\n {\n title: 'Restart',\n description:\n 'Restart the named app(s) with the current manifest config (command, env, watch).',\n inputSchema: targetInput,\n annotations: MUT(false, false),\n },\n (args) =>\n runTool(async () => {\n return act(args, 'restart');\n })\n );\n\n server.registerTool(\n 'stop',\n {\n title: 'Stop',\n description: 'Stop the named app(s); pm2 keeps them listed as stopped.',\n inputSchema: targetInput,\n annotations: MUT(true, true),\n },\n (args) =>\n runTool(async () => {\n return act(args, 'stop');\n })\n );\n\n server.registerTool(\n 'delete',\n {\n title: 'Delete',\n description: 'Remove the named app(s) from pm2 (stops them first).',\n inputSchema: targetInput,\n annotations: MUT(true, true),\n },\n (args) =>\n runTool(async () => {\n return act(args, 'delete');\n })\n );\n\n server.registerTool(\n 'lease_cancel',\n {\n title: 'Cancel a pending lease',\n description:\n \"Remove a pending lease from the host's queue (a start that has not been admitted yet), or a starting exec lease. A starting start or a running lease is refused: stop its target instead.\",\n inputSchema: {\n id: z.string().describe('The lease id from leases or a queued start'),\n },\n annotations: MUT(false, true),\n },\n (args) =>\n runTool(async () => {\n const l = await cancelLease(args.id);\n return {\n text: `cancelled ${l.id} (${l.project} ${l.target})`,\n data: l as unknown as Record<string, unknown>,\n };\n })\n );\n\n server.registerTool(\n 'flush',\n {\n title: 'Flush logs',\n description:\n 'Truncate the pm2 log files of one app, or of every app of the project (each on the host it runs on; with host, the apps that run there). Incidents start over from the flush: nothing logged before it is reported again.',\n inputSchema: { ...commonInput, app: z.string().optional() },\n annotations: MUT(true, true),\n },\n (args) =>\n runTool(async () => {\n const fleet = await fleetOf(args);\n const names = fleet.select(args.app ? [args.app] : ['all']);\n const hosts = fleet.groups(names).map((g) => g.host);\n const r = await clearLogs(fleet, names);\n return {\n text: renderFlushed(r, hosts.length > 1),\n data: { hosts, flushed: r },\n };\n })\n );\n\n server.registerTool(\n 'unpack',\n {\n title: 'Unpack runtime',\n description:\n 'Make a host self-sufficient: copy a pm2 tree (assembled once on this machine with npm from the lockfile mcproc ships; needs npm, tar and registry access the first time) and an official Node build when the host has no Node >= 18 (downloaded once from nodejs.org, checked against SHASUMS256), into <cwd>/.mcproc/runtime on that host or into dir, plus a copy of the manifest. Idempotent: same versions change nothing. Refused on readonly hosts and on a dir whose bin/ it did not write.',\n inputSchema: {\n ...commonInput,\n dir: z\n .string()\n .optional()\n .describe(\n 'Absolute runtime directory on the host; default <host cwd>/.mcproc/runtime'\n ),\n with_node: z\n .enum(['auto', 'always', 'never'])\n .optional()\n .describe(\n 'auto (default): bring Node only when the host has none >= 18'\n ),\n node_version: z\n .string()\n .optional()\n .describe('Exact Node version; default: the newest LTS'),\n force: z\n .boolean()\n .optional()\n .describe(\n 'Rewrite even when versions match, and overwrite a hand-written manifest on the host'\n ),\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n },\n (args) =>\n runTool(async () => {\n const p = prepare({\n project: args.project ?? deps.project,\n host: args.host,\n roots: await deps.roots(),\n });\n assertWritable(p.host);\n const r = await unpack(\n {\n manifest: p.manifest,\n host: p.host,\n transport: createTransport(p.host, deps.spawner),\n },\n {\n dir: args.dir,\n withNode: args.with_node,\n nodeVersion: args.node_version,\n force: args.force,\n },\n deps.unpack ?? defaultUnpackDeps()\n );\n return {\n text: renderUnpack(r),\n data: r as unknown as Record<string, unknown>,\n };\n })\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { commonInput, MUT, RO, runTool, type ToolDeps } from '../common.js';\nimport { connect, prepare } from '../../core/resolve.js';\nimport { assertExecHost, defaultExecDeps, runExec } from '../../core/exec.js';\nimport { parseSizeMib } from '../../core/sizes.js';\nimport { McprocError } from '../../core/errors.js';\nimport {\n defaultWorktreeDeps,\n worktreeAdd,\n worktreeLs,\n worktreeRemove,\n type WorktreeDeps,\n} from '../../core/worktree.js';\nimport {\n renderExec,\n renderWorktreeAdded,\n renderWorktreeRemoved,\n renderWorktrees,\n} from '../render.js';\n\n/**\n * The tools of the stands a checkout runs: `exec`, one-off work in a stand's environment under a memory lease when\n * asked, and the worktrees that give one repository several stands side by side.\n */\nexport function registerStandTools(server: McpServer, deps: ToolDeps): void {\n /** The checkout's manifest on the local host (git runs here) and the worktree deps, whose notes end up in `notes`. */\n const worktreeCtx = async (project: string | undefined, notes: string[]) => {\n const ctx = await connect(\n prepare({\n project: project ?? deps.project,\n roots: await deps.roots(),\n }),\n { spawner: deps.spawner, hereCheck: deps.hereCheck }\n );\n const wdeps: WorktreeDeps = await defaultWorktreeDeps(\n ctx,\n { out: (line) => notes.push(line) },\n { capture: true }\n );\n return { manifest: ctx.manifest, wdeps };\n };\n const withNotes = (text: string, notes: string[]) =>\n notes.length ? `${text}\\n${notes.join('\\n')}` : text;\n server.registerTool(\n 'exec',\n {\n title: 'Exec',\n description:\n 'Run a one-off command (a test run, a build, a seed) from the project root on THIS machine with the manifest\\'s exec.env (the stand\\'s addresses, interpolated) and MCPROC_PROJECT set. With memory (e.g. \"4G\") it is a lease like a start: it runs at once when the host has room and the queue is empty, else waits its turn behind the pending leases (timeout_s, default 600, max 3600) and is freed when the command exits. Local host only; refused when the local host is readonly. Returns the exit code and the last 200 lines of output; isError when the code is not 0.',\n inputSchema: {\n project: commonInput.project,\n host: z\n .string()\n .optional()\n .describe(\n 'Host name from the manifest; exec runs on this machine only, so a host other than a local one is refused.'\n ),\n command: z\n .array(z.string().min(1))\n .min(1)\n .describe(\n 'The command as argv, no shell: [\"bun\", \"run\", \"test:e2e\"]'\n ),\n memory: z\n .string()\n .optional()\n .describe('What it needs, as a size: 512M, 4G'),\n note: z.string().max(200).optional(),\n timeout_s: z.number().int().min(1).max(3600).optional(),\n },\n // any local argv, `rm` included: not an additive update, so clients ask before they run it\n annotations: MUT(true, false),\n },\n (args, extra) =>\n runTool(async () => {\n // a bad request is refused before any host is touched\n let memoryMib: number | undefined;\n if (args.memory !== undefined)\n try {\n memoryMib = parseSizeMib(args.memory);\n } catch (e) {\n throw new McprocError('BAD_ARGUMENT', (e as Error).message);\n }\n const prep = prepare({\n project: args.project ?? deps.project,\n host: args.host,\n roots: await deps.roots(),\n });\n assertExecHost(prep.host);\n const ctx = await connect(prep, {\n spawner: deps.spawner,\n hereCheck: deps.hereCheck,\n });\n const r = await runExec(\n ctx,\n {\n command: args.command,\n memoryMib,\n note: args.note,\n timeoutMs: args.timeout_s ? args.timeout_s * 1000 : undefined,\n capture: true,\n signal: extra.signal,\n },\n defaultExecDeps()\n );\n return {\n text: renderExec(args.command, r),\n data: { ...r },\n isError: r.code !== 0,\n };\n })\n );\n\n server.registerTool(\n 'worktree_add',\n {\n title: 'Worktree add',\n description:\n \"Make an isolated checkout of this repository on a branch, in the sibling folder <repo>.worktrees/<branch>, with the files its own manifest's worktree: section (plus the main checkout's override) copies or links, its own slot (ports shifted by that manifest's vars), its slug (the project slug this checkout runs under, default <project>-w<slot>) and the install. Then drive its stand with project: <its path> on every call.\",\n inputSchema: {\n project: commonInput.project,\n branch: z\n .string()\n .min(1)\n .describe(\n 'The branch to check out; made from `from` when it does not exist yet'\n ),\n from: z\n .string()\n .min(1)\n .optional()\n .describe(\n \"Where a new branch starts (default: the main checkout's HEAD)\"\n ),\n slot: z\n .number()\n .int()\n .min(1)\n .optional()\n .describe('A specific slot (default: the lowest free one)'),\n slug: z\n .string()\n .optional()\n .describe(\n 'The project slug this checkout runs under (default: <project>-w<slot>); project stays the project root'\n ),\n install: z\n .boolean()\n .optional()\n .describe(\n \"Run the install command in the new checkout (default true): the manifest's worktree.install, else by the lockfile\"\n ),\n },\n annotations: MUT(false, false),\n },\n (args) =>\n runTool(async () => {\n const notes: string[] = [];\n const { manifest, wdeps } = await worktreeCtx(args.project, notes);\n const r = await worktreeAdd(\n manifest,\n {\n branch: args.branch,\n from: args.from,\n slot: args.slot,\n project: args.slug,\n install: args.install ?? true,\n },\n wdeps\n );\n return {\n text: withNotes(renderWorktreeAdded(r), notes),\n data: { ...r, notes },\n };\n })\n );\n\n server.registerTool(\n 'worktree_ls',\n {\n title: 'Worktree ls',\n description:\n 'Every checkout of this repository on this host: its slot (0 is the main checkout), project slug, branch, how many of its apps are online, its lease state and its path. A read only: a slot whose folder is gone shows (gone) as its branch until worktree_add or worktree_remove frees it.',\n inputSchema: { project: commonInput.project },\n annotations: RO,\n },\n (args) =>\n runTool(async () => {\n const notes: string[] = [];\n const { manifest, wdeps } = await worktreeCtx(args.project, notes);\n const rows = await worktreeLs(manifest, wdeps);\n return {\n text: withNotes(renderWorktrees(rows), notes),\n data: { rows, notes },\n };\n })\n );\n\n server.registerTool(\n 'worktree_remove',\n {\n title: 'Worktree remove',\n description:\n 'Stop and delete the apps of a worktree (freeing its leases), remove the checkout and free its slot; the branch stays. ref is its slot number, path or branch. A checkout with uncommitted or untracked changes is refused unless force, which discards them. The main checkout (slot 0) is never removed.',\n inputSchema: {\n project: commonInput.project,\n ref: z\n .string()\n .min(1)\n .describe('The worktree: its slot number, path or branch'),\n force: z\n .boolean()\n .optional()\n .describe(\n 'Remove it even with uncommitted or untracked changes, discarding them (default false)'\n ),\n },\n annotations: MUT(true, false),\n },\n (args) =>\n runTool(async () => {\n const notes: string[] = [];\n const { manifest, wdeps } = await worktreeCtx(args.project, notes);\n const r = await worktreeRemove(\n manifest,\n args.ref,\n { force: args.force ?? false },\n wdeps\n );\n return {\n text: withNotes(renderWorktreeRemoved(r), notes),\n data: { ...r, notes },\n };\n })\n );\n}\n","import type { Manifest } from '../core/manifest.js';\nimport type { LsRow } from '../core/list.js';\nimport { pm2Name } from '../core/pm2.js';\nimport { sortByStamp, type LogLine } from '../core/logfollow.js';\nimport type { Incident } from '../core/incidents/detect.js';\nimport {\n isTaken,\n type ReadEnd,\n type TakenPoints,\n} from '../core/incidents/taken.js';\n\n/** An incident as the incidents view keeps it: with where the read that found it ended in its file. */\nexport type ShownIncident = Incident & { end?: ReadEnd };\n\nexport type Stream = 'out' | 'err' | 'both';\n/**\n * dashboard: table + the selected app's logs + details; flat: every app's logs merged into one labeled stream, compose\n * style; incidents: the errors, crashes and restarts of the apps in view, read for a person (never taken from the agent)\n */\nexport type View = 'dashboard' | 'flat' | 'incidents';\n/** The incidents view keeps this many, the newest. */\nexport const MAX_INCIDENTS = 200;\nexport interface FlatLine {\n app: string;\n stream: 'out' | 'err';\n text: string;\n seq: number;\n}\nexport interface AppInfo {\n description: string;\n run: string;\n cwd: string;\n pm2Name: string;\n}\n/**\n * An app's in-process reloads since pm2 started it, as ls --reloads reports them: how many, the last one's stamp as its\n * log wrote it, and partial when the lines seen do not reach back to the start (the count is then a lower bound).\n */\nexport type ReloadInfo = NonNullable<LsRow['reloads']>;\n/** A buffered log line with its arrival number: hosts have their own clocks (and time zones), so across hosts arrival is the order. */\nexport interface BufferedLine extends LogLine {\n seq: number;\n}\nexport interface MonitState {\n project: string;\n host: string;\n hosts: string[];\n apps: Record<string, AppInfo>;\n rows: LsRow[];\n selected: number;\n stream: Stream;\n view: View;\n /** the user moved the selection in this view; until then it is the first row, whichever host answered first */\n chosen: boolean;\n /** entries hidden below the log pane (0 = following the tail); the view stays put while new lines arrive */\n logScroll: number;\n /** rows of the lowest visible entry hidden below the pane: an entry taller than the pane is scrolled through row by row */\n logRowShift: number;\n /** one buffer per app, filled by every poll whichever view is active: the dashboard shows the selected app's, the flat view merges all */\n logs: Record<string, BufferedLine[]>;\n /** the arrival number the next buffered line gets */\n seq: number;\n maxLogs: number;\n logPaths: { out: string; err: string } | null;\n error: string | null;\n notice: string | null;\n busy: boolean;\n updatedAt: Date | null;\n /** when c or R was pressed once: the same key again within CONFIRM_MS does it */\n armedAt: number | null;\n /** what the first press asked for; only its own key confirms it, the other one arms itself instead */\n armed: Armed | null;\n /** the recorded clears, keyed host/app, as the project's store has them */\n cleared: Record<string, string>;\n /** per app whose logs this screen follows with reloads on and a known start: its reloads since that start */\n reloads: Record<string, ReloadInfo>;\n /** the view `i` returns to from the incidents view */\n back: 'dashboard' | 'flat';\n /** what the incidents view has read, oldest first, at most MAX_INCIDENTS */\n incidents: ShownIncident[];\n /** the incidents view has had its first answer (until then it says it is reading) */\n incidentsPolled: boolean;\n /** the latest clear of the apps the incidents view reads, as their store records it */\n incidentsCleared: string | null;\n /** what the last read could not do: hosts that did not answer, incidents left out */\n incidentsErrors: string[];\n /** how far the agent's takes have read each file, as the project's store has it: what lies before is shown muted */\n incidentsTaken: TakenPoints;\n /** the incidents view leaves out what the agent has taken (t) */\n hideTaken: boolean;\n}\n/** a key that asks twice: c clears the logs of the running apps in view, R reloads every app in view */\nexport type Armed = 'clear' | 'reload';\nexport type MonitAction =\n | { type: 'rows'; rows: LsRow[]; at?: Date } // no `at`: nothing new was heard (a host failed), so the clock stays\n | {\n type: 'logs';\n app: string;\n lines: LogLine[];\n reset?: boolean;\n paths?: { out: string; err: string } | null;\n }\n | { type: 'view'; view: View }\n | {\n type: 'scroll';\n delta: number;\n max?: number;\n to?: { entries: number; rows: number };\n } // + = older; ±Infinity = oldest / tail; max = the pane's ceiling (renderFrame().maxScroll); to = the place the screen measured in rows (frame scrollTo)\n | { type: 'select'; delta: number }\n | { type: 'stream'; stream: Stream }\n | { type: 'error'; message: string | null }\n | { type: 'notice'; message: string | null }\n | { type: 'busy'; busy: boolean }\n | { type: 'host'; host: string }\n | { type: 'arm'; at: null }\n | { type: 'arm'; at: number; what: Armed; apps: string[] }\n | { type: 'cleared'; cleared: Record<string, string> }\n | { type: 'reloads'; app: string; info: ReloadInfo | null } // null: the app is no longer counted\n | {\n type: 'incidents';\n incidents: ShownIncident[]; // one read's, newest first as the read answers\n cleared_at: string | null;\n errors: string[];\n }\n | { type: 'taken'; taken: TakenPoints }\n | { type: 'hideTaken' };\n\nexport function appInfos(m: Manifest): Record<string, AppInfo> {\n return Object.fromEntries(\n Object.values(m.apps).map((a) => [\n a.name,\n {\n description: a.description,\n run: a.run,\n cwd: a.cwd,\n pm2Name: pm2Name(m.project, a.name),\n },\n ])\n );\n}\nexport function hostNames(m: Manifest): string[] {\n return ['local', ...Object.keys(m.hosts).filter((h) => h !== 'local')];\n}\n/**\n * The screen's views in `h` order, each the --host a command would take: with host-bound apps first \"all\" (undefined:\n * every app at its own host), then each host; without any, just the hosts, as there is nothing else to tell apart.\n */\nexport function monitViews(m: Manifest): (string | undefined)[] {\n return Object.values(m.apps).some((a) => a.host !== null)\n ? [undefined, ...hostNames(m)]\n : hostNames(m);\n}\nexport const viewLabel = (requested: string | undefined): string =>\n requested ?? 'all';\n\nexport function initialState(p: {\n project: string;\n host: string;\n hosts: string[];\n apps: Record<string, AppInfo>;\n maxLogs?: number;\n}): MonitState {\n return {\n project: p.project,\n host: p.host,\n hosts: p.hosts,\n apps: p.apps,\n rows: [],\n selected: 0,\n chosen: false,\n stream: 'both',\n view: 'dashboard',\n logScroll: 0,\n logRowShift: 0,\n logs: {},\n seq: 0,\n maxLogs: p.maxLogs ?? 2000,\n logPaths: null,\n error: null,\n notice: null,\n busy: false,\n updatedAt: null,\n armedAt: null,\n armed: null,\n cleared: {},\n reloads: {},\n back: 'dashboard',\n incidents: [],\n incidentsPolled: false,\n incidentsCleared: null,\n incidentsErrors: [],\n incidentsTaken: {},\n hideTaken: false,\n };\n}\n\n/** What the incidents view shows, oldest first: all it has read, or only what the agent has not taken (t). */\nexport function visibleIncidents(s: MonitState): ShownIncident[] {\n return s.hideTaken\n ? s.incidents.filter((i) => !isTaken(i, s.incidentsTaken, i.end))\n : s.incidents;\n}\n\n/** Which view a reload covers, for its prompt: every host, the host `h` narrowed to, or nothing when there is one view only. */\nfunction reloadScope(s: MonitState): string {\n if (s.hosts.length <= 1) return '';\n return ` (${s.host === viewLabel(undefined) ? 'all hosts' : s.host})`;\n}\n\nconst clamp = (i: number, n: number) =>\n n === 0 ? 0 : Math.min(Math.max(i, 0), n - 1);\nconst selectedApp = (s: MonitState): string | undefined =>\n s.rows[s.selected]?.app;\n\nexport function reduce(s: MonitState, a: MonitAction): MonitState {\n switch (a.type) {\n case 'rows': {\n const name = s.rows[s.selected]?.app;\n const idx =\n s.chosen && name ? a.rows.findIndex((r) => r.app === name) : 0;\n const selected = clamp(idx >= 0 ? idx : s.selected, a.rows.length);\n const moved = a.rows[selected]?.app !== name; // another app is selected now: its log paths are not known yet\n return {\n ...s,\n rows: a.rows,\n selected,\n ...(moved ? { logPaths: null, logScroll: 0, logRowShift: 0 } : {}),\n updatedAt: a.at ?? s.updatedAt,\n error: null,\n };\n }\n case 'logs': {\n // one poll's stdout and stderr merge by pm2's stamp (one app, one clock); then the batch is numbered in arrival order\n const batch = sortByStamp(a.lines).map((l, i) => ({\n ...l,\n seq: s.seq + i,\n }));\n const buffer = (\n a.reset ? batch : [...(s.logs[a.app] ?? []), ...batch]\n ).slice(-s.maxLogs);\n const inView =\n s.view === 'flat' ||\n (s.view === 'dashboard' && a.app === selectedApp(s)); // the incidents view shows no logs: its scroll is its own\n // a scrolled view stays on the same lines while new ones arrive below it; a reset (rotation, flush) jumps to the tail\n const scrolled = s.logScroll > 0 || s.logRowShift > 0;\n const logScroll = !inView\n ? s.logScroll\n : a.reset\n ? 0\n : scrolled\n ? s.logScroll + a.lines.length\n : 0;\n const logRowShift = !inView\n ? s.logRowShift\n : a.reset || !scrolled\n ? 0\n : s.logRowShift;\n const logPaths =\n a.paths !== undefined && a.app === selectedApp(s)\n ? a.paths\n : s.logPaths;\n return {\n ...s,\n logs: { ...s.logs, [a.app]: buffer },\n seq: s.seq + batch.length,\n logScroll,\n logRowShift,\n logPaths,\n };\n }\n case 'select': {\n const selected = clamp(s.selected + a.delta, s.rows.length);\n return selected === s.selected\n ? { ...s, chosen: true }\n : {\n ...s,\n selected,\n chosen: true,\n logPaths: null,\n logScroll: 0,\n logRowShift: 0,\n }; // buffers are kept: the next selection shows its history at once\n }\n case 'view':\n return {\n ...s,\n view: a.view,\n back: s.view === 'incidents' ? s.back : s.view, // where the incidents view returns to\n logScroll: 0,\n logRowShift: 0,\n };\n case 'incidents': {\n const added = [...a.incidents].reverse();\n const shown = s.view === 'incidents';\n const rows = s.hideTaken\n ? added.filter((i) => !isTaken(i, s.incidentsTaken, i.end)).length\n : added.length; // what the new ones add to the view\n const scrolled = s.logScroll > 0 || s.logRowShift > 0;\n return {\n ...s,\n incidents: [...s.incidents, ...added].slice(-MAX_INCIDENTS),\n incidentsPolled: true,\n incidentsCleared: a.cleared_at,\n incidentsErrors: a.errors,\n // a scrolled view stays on the same incidents while new ones arrive below; at the tail it follows them\n logScroll: !shown ? s.logScroll : scrolled ? s.logScroll + rows : 0,\n };\n }\n case 'taken': {\n // what hides under the view stays where it was: the view keeps the incidents it shows\n if (s.view !== 'incidents' || !s.hideTaken || s.logScroll === 0)\n return { ...s, incidentsTaken: a.taken }; // another view's scroll is its own\n const below = visibleIncidents(s).slice(-s.logScroll);\n const still = below.filter((i) => !isTaken(i, a.taken, i.end)).length;\n return {\n ...s,\n incidentsTaken: a.taken,\n logScroll: still,\n logRowShift: still === s.logScroll ? s.logRowShift : 0,\n };\n }\n case 'hideTaken':\n return { ...s, hideTaken: !s.hideTaken, logScroll: 0, logRowShift: 0 };\n case 'scroll': {\n if (a.to)\n return { ...s, logScroll: a.to.entries, logRowShift: a.to.rows };\n const n =\n s.view === 'flat'\n ? Object.values(s.logs).reduce((t, l) => t + l.length, 0)\n : s.view === 'incidents'\n ? visibleIncidents(s).length\n : (s.logs[selectedApp(s) ?? ''] ?? []).length;\n const max = a.max ?? Math.max(0, n - 1); // without the pane's ceiling, at least never beyond the oldest entry\n return {\n ...s,\n logScroll: Math.min(\n Math.max(0, s.logScroll + a.delta),\n Math.max(0, max)\n ),\n logRowShift: 0,\n };\n }\n case 'stream':\n return { ...s, stream: a.stream };\n case 'error':\n return { ...s, error: a.message };\n case 'notice':\n return { ...s, notice: a.message };\n case 'busy':\n // a step that starts drops the last notice: the footer then shows what this one says it is doing, or working…\n return a.busy\n ? { ...s, busy: true, notice: null }\n : { ...s, busy: false };\n case 'arm':\n return a.at === null\n ? {\n ...s,\n armedAt: null,\n armed: null,\n notice: s.armedAt !== null ? null : s.notice,\n }\n : {\n ...s,\n armedAt: a.at,\n armed: a.what,\n notice:\n a.what === 'clear'\n ? `press c again to clear the logs of ${a.apps.join(', ')} (incidents start over there)`\n : `press R again to reload ${a.apps.length} app${a.apps.length === 1 ? '' : 's'}${reloadScope(s)}`,\n };\n case 'cleared':\n return { ...s, cleared: a.cleared };\n case 'reloads': {\n const { [a.app]: _, ...rest } = s.reloads;\n return { ...s, reloads: a.info ? { ...rest, [a.app]: a.info } : rest };\n }\n case 'host':\n return {\n ...s,\n host: a.host,\n rows: [],\n logs: {},\n reloads: {},\n incidents: [],\n incidentsPolled: false,\n incidentsCleared: null,\n incidentsErrors: [],\n logScroll: 0,\n logRowShift: 0,\n logPaths: null,\n selected: 0,\n chosen: false,\n error: null,\n notice: `host: ${a.host}`,\n };\n }\n}\n\nexport type KeyIntent =\n | { kind: 'action'; action: MonitAction }\n | { kind: 'command'; cmd: 'start' | 'restart' | 'stop'; app: string }\n | { kind: 'clear'; apps: string[] }\n | { kind: 'reload-all' }\n | { kind: 'host-next' }\n | { kind: 'quit' }\n | null;\n\n/** How long a first c or R waits for the second one. */\nexport const CONFIRM_MS = 3000;\n\nexport function keyIntent(\n key: string,\n s: MonitState,\n now = Date.now()\n): KeyIntent {\n const app = s.rows[s.selected]?.app;\n const canCommand = app && !s.busy && s.view === 'dashboard'; // commands act on the selected app, which only the dashboard shows\n /** the second press of the key that armed `what`, in time */\n const confirms = (what: Armed) =>\n s.armed === what && s.armedAt !== null && now - s.armedAt <= CONFIRM_MS;\n switch (key) {\n // mouse tracking stays off so terminal drag-selection works; the wheel then arrives as ↑/↓, so those scroll the logs\n case 'up':\n return { kind: 'action', action: { type: 'scroll', delta: 1 } };\n case 'down':\n return { kind: 'action', action: { type: 'scroll', delta: -1 } };\n case 'pageup':\n return { kind: 'action', action: { type: 'scroll', delta: 10 } };\n case 'pagedown':\n return { kind: 'action', action: { type: 'scroll', delta: -10 } };\n case 'home':\n case 'g':\n return { kind: 'action', action: { type: 'scroll', delta: Infinity } };\n case 'end':\n case 'G':\n return { kind: 'action', action: { type: 'scroll', delta: -Infinity } };\n case 'k':\n case 'S-tab':\n // the incidents view selects no app (and a new selection would reset its scroll)\n return s.view === 'incidents'\n ? null\n : { kind: 'action', action: { type: 'select', delta: -1 } };\n case 'j':\n case 'tab':\n return s.view === 'incidents'\n ? null\n : { kind: 'action', action: { type: 'select', delta: 1 } };\n case 'i':\n return {\n kind: 'action',\n action: {\n type: 'view',\n view: s.view === 'incidents' ? s.back : 'incidents',\n },\n };\n case 't':\n return s.view === 'incidents'\n ? { kind: 'action', action: { type: 'hideTaken' } }\n : null;\n case 'o':\n return { kind: 'action', action: { type: 'stream', stream: 'out' } };\n case 'e':\n return { kind: 'action', action: { type: 'stream', stream: 'err' } };\n case 'b':\n return { kind: 'action', action: { type: 'stream', stream: 'both' } };\n case 'f':\n return {\n kind: 'action',\n action: {\n type: 'view',\n view: s.view === 'flat' ? 'dashboard' : 'flat',\n },\n };\n case 'r':\n return canCommand ? { kind: 'command', cmd: 'restart', app } : null;\n case 's':\n return canCommand ? { kind: 'command', cmd: 'start', app } : null;\n case 'x':\n return canCommand ? { kind: 'command', cmd: 'stop', app } : null;\n case 'h':\n return s.hosts.length > 1 && !s.busy ? { kind: 'host-next' } : null; // one switch at a time\n case 'c': {\n // c clears every running app of the view, so it asks twice: a second c within CONFIRM_MS does it, any other key cancels\n const apps = s.rows\n .filter((r) => r.status === 'online')\n .map((r) => r.app);\n if (s.busy || apps.length === 0) return null;\n return confirms('clear')\n ? { kind: 'clear', apps }\n : {\n kind: 'action',\n action: { type: 'arm', at: now, what: 'clear', apps },\n };\n }\n case 'S-r': {\n // R (blessed: S-r) is `start all --reload` over the view: every app in dependency order with its waits, tasks re-run\n // included, in either view, so it asks twice like c\n const apps = s.rows.map((r) => r.app);\n if (s.busy || apps.length === 0) return null;\n return confirms('reload')\n ? { kind: 'reload-all' }\n : {\n kind: 'action',\n action: { type: 'arm', at: now, what: 'reload', apps },\n };\n }\n case 'q':\n case 'C-c':\n case 'escape':\n return { kind: 'quit' };\n default:\n return null;\n }\n}\n\nexport function selectedRow(s: MonitState): LsRow | null {\n return s.rows[s.selected] ?? null;\n}\n\nexport function visibleLogs(s: MonitState): LogLine[] {\n const all = s.logs[selectedApp(s) ?? ''] ?? [];\n const lines =\n s.stream === 'both' ? all : all.filter((l) => l.stream === s.stream);\n return s.stream === 'both' ? sortByStamp(lines) : lines;\n}\n\n/**\n * The flat stream: every app's buffer merged. Apps of one host are ordered by pm2's stamp (one clock); once the apps with\n * lines run on more than one host, by arrival — another host's stamps may be in another time zone, or just drift.\n */\nexport function visibleFlat(s: MonitState): FlatLine[] {\n const hostOf = new Map(s.rows.map((r) => [r.app, r.host]));\n const entries = Object.entries(s.logs).filter(\n ([, lines]) => lines.length > 0\n );\n const hosts = [...new Set(entries.map(([app]) => hostOf.get(app)))];\n // scrolling and selection leave the buffers alone: the merge of the last render is still the answer\n const key = `${s.stream}|${hosts.join(',')}`;\n if (flatMemo && flatMemo.logs === s.logs && flatMemo.key === key)\n return flatMemo.out;\n const all = entries.flatMap(([app, lines]) =>\n lines.map((l) => flatLineOf(app, l))\n );\n const shown =\n s.stream === 'both' ? all : all.filter((l) => l.stream === s.stream);\n // one host: by stamp, and within a stamp by arrival (lines arrive as they are written); several hosts: by arrival\n const byArrival = shown.sort((a, b) => a.seq - b.seq);\n const out = hosts.length <= 1 ? sortByStamp(byArrival) : byArrival;\n flatMemo = { logs: s.logs, key, out };\n return out;\n}\n/** One merged line per buffered line, for good: the screen keeps each line's rows cached on this object. */\nconst flatLines = new WeakMap<BufferedLine, FlatLine>();\nfunction flatLineOf(app: string, l: BufferedLine): FlatLine {\n let f = flatLines.get(l);\n if (!f) {\n f = { app, stream: l.stream, text: l.text, seq: l.seq };\n flatLines.set(l, f);\n }\n return f;\n}\nlet flatMemo: {\n logs: MonitState['logs'];\n key: string;\n out: FlatLine[];\n} | null = null;\n","import { charWidth, chars } from '@pm2/blessed/lib/unicode.js';\nimport { keepSgr, SGR_RE, stripAnsi } from '../core/logs.js';\n\n/*\n * Text for the monit screen. blessed keeps a model of the cells it has drawn and later redraws only the cells that\n * changed. It cuts a line at the pane width counted in UTF-16 units (plus a placeholder after each wide CJK character)\n * and draws each character as wide as its own table (charWidth) says. Wherever that width differs from the columns a\n * terminal gives the character, the rest of the row lands off by a column and later redraws leave old characters\n * behind. Emoji are where they differ: 🚀 and ✅ are 1 in blessed's table and 2 on a terminal, and for ⚠️, flags or\n * ZWJ families terminals disagree among themselves. So the screen shows text in which every character has the same\n * width in blessed's model as on a terminal: narrow characters, the wide CJK ranges blessed handles consistently, and\n * the combining marks both draw at zero width (Indic, Thai, accents). Characters outside the BMP become ?, wide CJK\n * extensions included: blessed's surrogate handling is not worth the rare name it would keep.\n */\n\nconst segmenter = new Intl.Segmenter('en', { granularity: 'grapheme' });\nconst EMOJI_PRESENTATION = /\\p{Emoji_Presentation}/u;\nconst PICTOGRAPH = /\\p{Extended_Pictographic}/u;\nconst REGIONAL = /\\p{Regional_Indicator}/u;\nconst KEYCAP = /^[0-9#*]\\uFE0F?\\u20E3$/;\nconst INVISIBLE = /[\\p{Cc}\\p{Cf}]/u; // controls and zero-width format characters (ZWJ, ZWSP, BOM, selectors are marks)\nconst LINE_BREAK = /\\r\\n|[\\n\\v\\f\\u0085\\u2028\\u2029]/g;\nconst MARK = /\\p{M}/u;\nconst SPACING_MARK = /\\p{Mc}/u;\nconst BLESSED_WIDE = new RegExp(chars.wide.source); // the characters blessed gives a placeholder cell\n/** status emoji with a narrow look-alike that keeps their meaning */\nconst NARROW: Record<string, string> = {\n '✅': '✔',\n '❌': '✖',\n '❎': '✖',\n '❗': '!',\n '❕': '!',\n '❓': '?',\n '❔': '?',\n};\nconst TAB = 8;\n\n/**\n * Width of screen text the way blessed's line cut counts it: one per character, two per wide one, nothing for a\n * color code. A kept zero-width mark counts one here and none on the terminal, so text that fits always fits.\n */\nexport function displayWidth(s: string): number {\n let w = 0;\n for (const ch of s.includes('\\x1b') ? s.replace(SGR_RE, '') : s)\n w += charWidth(ch.codePointAt(0)!) === 2 ? 2 : 1;\n return w;\n}\n\n/** Terminal columns of screen text (marks take none): what tab stops are counted in. */\nfunction columns(s: string): number {\n let w = 0;\n for (const ch of s) w += charWidth(ch.codePointAt(0)!);\n return w;\n}\n\n/** A mark stays when blessed and terminals give it the same width: zero for a combining mark it knows, one for a spacing mark. */\nfunction keepMark(ch: string, cp: number): boolean {\n return cp <= 0xffff && charWidth(cp) === (SPACING_MARK.test(ch) ? 1 : 0);\n}\n\nfunction cluster(c: string): string {\n if (c === '\\t') return c;\n const first = String.fromCodePoint(c.codePointAt(0)!);\n if (REGIONAL.test(first))\n return [...c]\n .filter((ch) => REGIONAL.test(ch))\n .map((ch) => String.fromCharCode(ch.codePointAt(0)! - 0x1f1e6 + 65))\n .join(''); // 🇺🇦 → UA\n if (KEYCAP.test(c)) return c[0]; // 1️⃣ → 1\n if (PICTOGRAPH.test(first) || EMOJI_PRESENTATION.test(first)) {\n if (NARROW[first]) return NARROW[first];\n // a symbol drawn as text by default (⚠ ✔ ❤) keeps its narrow form without the emoji selector; anything else is an emoji\n return !EMOJI_PRESENTATION.test(first) && first.length === 1 ? first : '?';\n }\n let out = '';\n for (const ch of c) {\n if (INVISIBLE.test(ch)) continue;\n const cp = ch.codePointAt(0)!;\n if (MARK.test(ch)) {\n if (keepMark(ch, cp)) out += ch;\n continue;\n }\n if (cp > 0xffff || (cp >= 0xd800 && cp <= 0xdfff)) {\n out += '?';\n continue;\n }\n // blessed has two tables of wide characters (the placeholder one and charWidth); where they disagree, it draws off by one\n out += (charWidth(cp) === 2) === BLESSED_WIDE.test(ch) ? ch : '?';\n }\n return out;\n}\n\n/**\n * blessed reads only `ESC [ digits ; m`; the colon form (`38:2::r:g:b` true color, `38:5:n`, `4:3` curly underline)\n * would show as text. Colors and underline get their semicolon form, any other colon code goes (never an empty code,\n * which would read as a reset).\n */\nfunction blessedSgr(code: string): string {\n if (!code.includes(':')) return code;\n const groups = code\n .slice(2, -1)\n .split(';')\n .flatMap((g) => {\n if (!g.includes(':')) return [g];\n const [kind, mode, ...rest] = g.split(':');\n if (kind === '4') return ['4'];\n if (!['38', '48', '58'].includes(kind)) return [];\n if (mode === '5' && rest[0]) return [`${kind};5;${rest[0]}`];\n if (mode === '2' && rest.length >= 3)\n return [`${kind};2;${rest.slice(-3).join(';')}`];\n return [];\n });\n return groups.length ? `\\x1b[${groups.join(';')}m` : '';\n}\n\nconst SGR_SPLIT = /(\\x1b\\[[0-9;:]*m)/;\nconst visible = (t: string) => t.replace(SGR_RE, '');\n\n/**\n * One log line or label as the screen shows it: the part after the last carriage return (what a terminal shows), line\n * breaks as spaces, tabs expanded to 8-column stops, every character as described above. Without `colors` all escapes\n * go; with it an app's color codes stay where they are (one set before a carriage return still applies after it) and\n * every other escape goes.\n */\nexport function screenText(\n input: string,\n opts: { colors?: boolean } = {}\n): string {\n const parts = (opts.colors ? keepSgr(input) : stripAnsi(input))\n .replace(/\\r\\n/g, '\\n')\n .split('\\r');\n let last = parts.length - 1;\n while (last > 0 && visible(parts[last]) === '') last--;\n const carried = parts\n .slice(0, last)\n .flatMap((p) => p.match(SGR_RE) ?? [])\n .join('');\n let out = '';\n let col = 0;\n for (const piece of (carried + parts[last]).split(SGR_SPLIT)) {\n if (SGR_SPLIT.test(piece) && piece.startsWith('\\x1b')) {\n out += blessedSgr(piece);\n continue;\n }\n for (const { segment } of segmenter.segment(\n piece.replace(LINE_BREAK, ' ').normalize('NFC')\n )) {\n const c = cluster(segment);\n if (c === '\\t') {\n const n = TAB - (col % TAB);\n out += ' '.repeat(n);\n col += n;\n continue;\n }\n out += c;\n col += columns(c);\n }\n }\n return out;\n}\n\n/** Cut screen text to `width` (as displayWidth counts), with an ellipsis when something was cut. */\nexport function cutWidth(s: string, width: number): string {\n if (displayWidth(s) <= width) return s;\n let out = '';\n let w = 0;\n for (const ch of s) {\n const cw = displayWidth(ch);\n if (w + cw > width - 1) break;\n out += ch;\n w += cw;\n }\n return `${out}…`;\n}\n","import type { LsRow } from '../core/list.js';\nimport { isRunning } from '../core/pm2.js';\nimport {\n fmtBytes,\n fmtCpu,\n fmtPorts,\n fmtUptime,\n fmtUrl,\n incidentLines,\n table,\n} from '../mcp/render.js';\nimport type { Incident } from '../core/incidents/detect.js';\nimport { DEFAULT_SINCE_MIN } from '../core/incidents/poll.js';\nimport { isTaken } from '../core/incidents/taken.js';\nimport {\n selectedRow,\n visibleFlat,\n visibleLogs,\n type FlatLine,\n type MonitState,\n type ReloadInfo,\n visibleIncidents,\n type ShownIncident,\n} from './state.js';\nimport type { LogLine } from '../core/logfollow.js';\nimport { cutWidth as cut, displayWidth, screenText } from './screentext.js';\nimport { stripAnsi } from '../core/logs.js';\nimport { markKey } from '../core/incidents/cursor.js';\nimport { localStamp } from '../core/incidents/store.js';\n\nexport interface Frame {\n header: string;\n table: string[];\n logs: string[];\n details: string[];\n footer: string;\n /** entries hidden below the log pane as rendered, and the most that can be hidden with the pane still full */\n scroll: number;\n maxScroll: number;\n}\n\n/**\n * The log pane: `logH` rows ending at the view's lowest row — `scroll` entries hidden below it, and `shift` rows of the\n * lowest visible entry, so an entry taller than the pane is reachable row by row. Past the top the pane shows the first\n * `logH` rows: the window never shrinks. `maxScroll` = entries beyond the leading ones that fill the pane (the ceiling\n * of a scroll by whole entries, and what the title counts).\n */\nfunction pane<T>(\n entries: T[],\n scroll: number,\n shift: number,\n logH: number,\n rowsOf: (e: T) => string[]\n): { rows: string[]; scroll: number; maxScroll: number } {\n let filled = 0;\n let k = 0;\n while (k < entries.length && filled < logH) {\n filled += rowsOf(entries[k]).length;\n k++;\n }\n const maxScroll = Math.max(0, entries.length - k);\n if (entries.length === 0) return { rows: [], scroll: 0, maxScroll: 0 };\n const eff = Math.min(Math.max(0, scroll), entries.length - 1);\n const bottom = rowsOf(entries[entries.length - 1 - eff]);\n let rows = bottom.slice(\n 0,\n bottom.length - Math.min(Math.max(0, shift), bottom.length - 1)\n );\n let i = entries.length - 1 - eff;\n while (rows.length < logH && i > 0) {\n i--;\n rows = [...rowsOf(entries[i]), ...rows];\n }\n if (rows.length < logH) {\n // past the top: the first rows of the buffer, a full pane\n rows = [];\n for (let j = 0; j < entries.length && rows.length < logH; j++)\n rows.push(...rowsOf(entries[j]));\n return { rows: rows.slice(0, logH), scroll: maxScroll, maxScroll };\n }\n return {\n rows: rows.slice(-logH),\n scroll: Math.min(eff, maxScroll),\n maxScroll,\n };\n}\n\n/** What the log pane shows for a state and a screen size: its entries, its height, and the rows of one entry. */\nfunction paneSpec(\n s: MonitState,\n size: { width: number; height: number }\n): { entries: object[]; logH: number; rowsOf: (e: object) => string[] } {\n const w = Math.max(40, size.width);\n if (s.view === 'incidents')\n return {\n entries: visibleIncidents(s),\n // header, the pane title, footer, and one line per thing the last read could not do\n logH: Math.max(3, size.height - 3 - s.incidentsErrors.length),\n rowsOf: (e) =>\n incidentRows(\n e as ShownIncident,\n w,\n isTaken(\n e as ShownIncident,\n s.incidentsTaken,\n (e as ShownIncident).end\n )\n ),\n };\n if (s.view === 'flat') {\n const label = Math.max(1, ...Object.keys(s.apps).map((a) => a.length));\n return {\n entries: visibleFlat(s),\n logH: Math.max(3, size.height - 3), // header, the pane title, footer\n rowsOf: (e) => {\n const l = e as FlatLine;\n return cachedRows(flatRows, l, `${w}|${label}`, () =>\n wrapText(\n `${l.app.padEnd(label)} ${l.stream === 'err' ? '!' : '|'} ${logText(l.text)}`,\n w,\n label + 3\n )\n );\n },\n };\n }\n const tableH = s.rows.length + 1; // the table's header line and one line per app\n return {\n entries: visibleLogs(s),\n logH: Math.max(3, size.height - 1 - tableH - 3 - 6 - 1), // 3: one title rule per pane, no frames; 6 details lines\n rowsOf: (e) => {\n const l = e as LogLine;\n return cachedRows(dashboardRows, l, `${w}`, () =>\n wrapText(`${l.stream === 'err' ? '! ' : ' '}${logText(l.text)}`, w, 2)\n );\n },\n };\n}\n\n/**\n * Where the log view is after moving `delta` rows (+ = older; ±Infinity = the top / the tail), measured in the rows the\n * pane draws: it stops when the oldest row is in view, and at the tail. Each step looks at one pane's worth of rows.\n */\nexport function scrollTo(\n s: MonitState,\n size: { width: number; height: number },\n delta: number\n): { entries: number; rows: number } {\n const { entries, logH, rowsOf } = paneSpec(s, size);\n const n = entries.length;\n if (n === 0 || delta === -Infinity) return { entries: 0, rows: 0 };\n const rowsAt = (e: number) => rowsOf(entries[n - 1 - e]).length;\n if (delta === Infinity) {\n // the top: the view ends where the first pane of rows ends, counted from the oldest entry\n let rows = 0;\n for (let j = 0; j < n; j++) {\n const len = rowsOf(entries[j]).length;\n if (rows + len >= logH)\n return { entries: n - 1 - j, rows: rows + len - logH };\n rows += len;\n }\n return { entries: 0, rows: 0 }; // fewer rows than the pane: nothing to scroll, the view stays on the tail\n }\n let e = Math.min(Math.max(0, s.logScroll), n - 1);\n let r = Math.min(Math.max(0, s.logRowShift), rowsAt(e) - 1);\n /** the rows from the view's lowest row up to the oldest one, counted only up to `limit` */\n const upTo = (limit: number) => {\n let c = rowsAt(e) - r;\n for (let i = n - 1 - e; c < limit && i > 0; )\n c += rowsOf(entries[--i]).length;\n return c;\n };\n for (let k = 0; k < Math.abs(delta); k++) {\n if (delta > 0) {\n if (upTo(logH + 1) <= logH) break; // the oldest row is already in view\n if (r + 1 < rowsAt(e)) r++;\n else {\n e++;\n r = 0;\n }\n } else {\n if (e === 0 && r === 0) break;\n if (r > 0) r--;\n else {\n e--;\n r = rowsAt(e) - 1;\n }\n }\n }\n return { entries: e, rows: r };\n}\n\n/**\n * The rows of one log entry, per pane and width. A line is cleaned and wrapped once and kept on its own object, so a\n * render (and every scroll step is one) touches only lines it has not drawn before: the work stays the size of the pane.\n */\ntype RowCache = WeakMap<object, { key: string; rows: string[] }>;\nconst dashboardRows: RowCache = new WeakMap();\nconst flatRows: RowCache = new WeakMap();\nfunction cachedRows(\n cache: RowCache,\n entry: object,\n key: string,\n make: () => string[]\n): string[] {\n const hit = cache.get(entry);\n if (hit && hit.key === key) return hit.rows;\n const rows = make();\n cache.set(entry, { key, rows });\n return rows;\n}\n\nconst incidentCache: RowCache = new WeakMap();\n/** The muted colors of what the agent has taken: grey text, and a soft red for the incident's own line. */\nconst TAKEN_TEXT = '\\x1b[90m';\nconst TAKEN_LINE = '\\x1b[38;5;131m';\n/**\n * An incident's rows as the incidents tool writes it, wrapped to the width; its own line red, each row closing its\n * color. One the agent has taken is muted throughout and says so on its first line.\n */\nfunction incidentRows(i: Incident, w: number, taken = false): string[] {\n return cachedRows(incidentCache, i, `${w}:${taken}`, () =>\n incidentLines(i).flatMap((line, k) => {\n const text = taken && k === 0 ? `${line} · taken` : line;\n const rows = wrapText(screenText(text), w, 4);\n const color = line.startsWith(' ▶ ')\n ? taken\n ? TAKEN_LINE\n : '\\x1b[31m'\n : taken\n ? TAKEN_TEXT\n : '';\n return color ? rows.map((r) => `${color}${r}${RESET}`) : rows;\n })\n );\n}\n\nconst PM2_STAMP = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{3})?: /; // seconds, or milliseconds\n/** A log line as screen text; pm2's time stamp stays even when carriage returns overwrote the text after it. */\nfunction logText(text: string): string {\n const stamp = PM2_STAMP.exec(text)?.[0] ?? '';\n return stamp + screenText(text.slice(stamp.length), { colors: true }); // the app's own colors, as on its terminal\n}\n\nconst RESET = '\\x1b[0m';\nconst SGR_TOKEN = /(\\x1b\\[[0-9;:]*m)/;\n/** The color state after an SGR code: a reset (`ESC[m`, `ESC[0m`, `ESC[0;…m`) starts over, anything else adds to it. */\nfunction nextActive(active: string, code: string): string {\n const params = code.slice(2, -1);\n if (params === '' || params === '0') return '';\n return params.split(/[;:]/)[0] === '0' ? code : active + code;\n}\n\n/**\n * Hard-wraps one line of screen text at the width (a wide character is never split, color codes take no room);\n * continuation rows are indented so the text stays under the text, not under the marker. Every row that carries a\n * color closes it, and a continuation row reopens the color active at its start: each row stands alone, as the pane\n * may show any of them without the rows above.\n */\nexport function wrapText(\n text: string,\n width: number,\n indent: number\n): string[] {\n const close = (r: string) => (r.includes('\\x1b[') ? r + RESET : r);\n if (width <= 0 || displayWidth(text) <= width) return [close(text)];\n const pad = ' '.repeat(Math.min(indent, width - 1));\n const rows: string[] = [];\n let row = '';\n let w = 0;\n let filled = false;\n let active = '';\n for (const token of text.split(SGR_TOKEN)) {\n if (token.startsWith('\\x1b[')) {\n row += token;\n active = nextActive(active, token);\n continue;\n }\n for (const ch of token) {\n const cw = displayWidth(ch);\n if (w + cw > width && filled) {\n rows.push(close(row));\n row = pad + active;\n w = pad.length;\n filled = false;\n }\n row += ch;\n w += cw;\n filled = true;\n }\n }\n rows.push(close(row));\n return rows;\n}\n\nfunction portDetails(r: LsRow): string {\n if (r.ports.checks.length === 0 && r.ports.actual.length === 0) return 'none';\n const parts = r.ports.checks.map((c) => {\n if (c.status === 'listening') {\n const l = r.ports.actual.find((x) => x.port === c.port);\n return `:${c.port} ✓${l ? ` pid ${l.pid ?? '?'} ${l.command ?? ''}`.trimEnd() : ''}`;\n }\n const who = c.held_by\n ? c.held_by.app\n ? `app ${c.held_by.app}`\n : c.held_by.container\n ? `container ${c.held_by.container}`\n : c.held_by.pid !== null\n ? `pid ${c.held_by.pid} ${c.held_by.command ?? ''}`.trimEnd()\n : \"another user's process\"\n : 'nothing listens';\n return `:${c.port} ✗ ${c.held_by ? 'held by ' : ''}${who}`;\n });\n for (const u of r.ports.undeclared) parts.push(`:${u} (undeclared)`);\n return parts.join(', ');\n}\n\n/**\n * What follows the restarts: ` (+7 reloads, last 12:01:05)`, `+≥7` when partial; nothing without a count, nor for an\n * app that is not running (pm2 keeps a stopped process's last start, but its run is over), as ls --reloads counts.\n */\nfunction reloadsNote(r: LsRow, info: ReloadInfo | undefined): string {\n if (!info || info.count === 0 || !isRunning(r.status)) return '';\n const last = info.last ? `, last ${info.last.slice(11, 19)}` : '';\n return ` (+${info.partial ? '≥' : ''}${info.count} reload${info.count === 1 ? '' : 's'}${last})`;\n}\n\nexport function renderFrame(\n s: MonitState,\n size: { width: number; height: number }\n): Frame {\n const w = Math.max(40, size.width);\n const clock = s.updatedAt\n ? s.updatedAt.toTimeString().slice(0, 8)\n : '--:--:--';\n const header = cut(\n `mcproc · ${s.project} · ${s.host}${s.hosts.length > 1 ? ` (h: ${s.hosts.join('/')})` : ''} ${clock}`,\n w\n );\n // everything that comes from outside (logs, descriptions, commands, errors) is shown as screen text: see screentext.ts.\n // While busy: what the step under way says it is doing (busy drops the notice before it), or working… when it says nothing\n const right = screenText(\n s.error ? `ERROR: ${s.error}` : (s.notice ?? (s.busy ? 'working…' : ''))\n );\n if (s.view === 'incidents') {\n // the incidents of the apps in view, oldest first, the newest at the bottom; what a read could not do under them\n const spec = paneSpec(s, size);\n const p = pane(\n spec.entries,\n s.logScroll,\n s.logRowShift,\n spec.logH,\n spec.rowsOf\n );\n const empty = !s.incidentsPolled\n ? 'reading incidents…'\n : s.incidents.length\n ? 'every incident here is taken (t shows them)'\n : `no incidents in the last ${DEFAULT_SINCE_MIN} min`;\n const keys = `↑↓ scroll i back f flat t ${s.hideTaken ? 'show' : 'hide'} taken c clear R reload all h host q quit`;\n return {\n header,\n table: [],\n logs: [\n ...(p.rows.length ? p.rows : [empty]),\n ...s.incidentsErrors.map((e) => cut(screenText(e), w)),\n ],\n details: [],\n footer: cut(right ? `${right} │ ${keys}` : keys, w),\n scroll: p.scroll,\n maxScroll: p.maxScroll,\n };\n }\n if (s.view === 'flat') {\n // compose style: every app, label padded to the longest name, `|` stdout / `!` stderr, continuations under the text\n const spec = paneSpec(s, size);\n const p = pane(\n spec.entries,\n s.logScroll,\n s.logRowShift,\n spec.logH,\n spec.rowsOf\n );\n const keys =\n '↑↓ scroll c clear R reload all f dashboard o/e/b logs i incidents h host q quit';\n return {\n header,\n table: [],\n logs: p.rows,\n details: [],\n footer: cut(right ? `${right} │ ${keys}` : keys, w),\n scroll: p.scroll,\n maxScroll: p.maxScroll,\n };\n }\n const multi = new Set(s.rows.map((r) => r.host)).size > 1; // apps of several hosts on one screen: say where each runs\n const tableLines = table([\n [\n '',\n 'APP',\n ...(multi ? ['HOST'] : []),\n 'STATUS',\n 'UP',\n 'MEM',\n 'CPU',\n 'PORTS',\n 'URL',\n 'RUNTIME',\n ],\n ...s.rows.map((r, i) => [\n i === s.selected ? '▶' : ' ',\n r.app,\n ...(multi ? [r.host] : []),\n r.status,\n fmtUptime(r.uptime_ms),\n r.memory ? fmtBytes(r.memory) : '-',\n r.status === 'online' ? fmtCpu(r.cpu) : '-',\n cut(screenText(fmtPorts(r.ports)), 22),\n cut(screenText(fmtUrl(r)), 36),\n r.runtime ? cut(screenText(r.runtime), 40) : '-',\n ]),\n ])\n .split('\\n')\n .map((l) => cut(l.replace(/^(.)\\s\\s/, '$1'), w));\n const spec = paneSpec(s, size); // its height counts the table as s.rows.length + 1 lines, as drawn here\n const p = pane(\n spec.entries,\n s.logScroll,\n s.logRowShift,\n spec.logH,\n spec.rowsOf\n );\n const logs = p.rows;\n const r = selectedRow(s);\n const a = r ? s.apps[r.app] : null;\n const details =\n r && a\n ? [\n cut(\n screenText(`${r.app} [${r.kind}] ${a.description.split('\\n')[0]}`),\n w\n ),\n cut(screenText(`run: ${a.run} cwd: ${a.cwd}`), w),\n cut(\n `pm2: ${a.pm2Name} on ${r.host} pid ${r.pid ?? '-'} restarts ${r.restarts}${reloadsNote(r, s.reloads[r.app])} procs ${r.procs ?? '?'} mem ${r.memory ? fmtBytes(r.memory) : '-'} (RSS sum of the tree; pm2 root: ${fmtBytes(r.pm2_memory)})`,\n w\n ),\n cut(screenText(`ports: ${portDetails(r)}`), w), // process names from ss/ps are outside text too\n cut(screenText(`url: ${fmtUrl(r)}`), w),\n cut(\n screenText(\n `logs: ${s.logPaths ? `${s.logPaths.out} | ${s.logPaths.err}` : '-'}`\n ),\n w\n ),\n ]\n : ['no app selected'];\n const keys =\n 'j/k app ↑↓ scroll r restart R reload all s start x stop c clear o/e/b logs f flat i incidents h host q quit';\n const footer = cut(right ? `${right} │ ${keys}` : keys, w); // the error or notice first: on a narrow terminal the key legend is what gets cut\n return {\n header,\n table: tableLines,\n logs,\n details,\n footer,\n scroll: p.scroll,\n maxScroll: p.maxScroll,\n };\n}\n\n/** A clear's time for a title: the time when it was today, the date too otherwise. */\nfunction clearedAt(at: string, now: Date): string {\n return at.slice(0, 10) === localStamp(now).slice(0, 10)\n ? at.slice(11, 16)\n : `${at.slice(0, 10)} ${at.slice(11, 16)}`;\n}\n\n/**\n * The pane's title: whose logs, which stream, the last clear of the apps shown, how far it is scrolled; in the incidents\n * view the window it reads, the last clear and how many incidents it shows.\n */\nexport function logsTitle(\n s: MonitState,\n scroll: number,\n now = new Date()\n): string {\n const up = scroll ? ` · ↑${scroll} (End: tail)` : '';\n if (s.view === 'incidents') {\n const since = s.incidentsCleared\n ? ` · since the clear ${clearedAt(s.incidentsCleared, now)}`\n : '';\n const taken = s.incidents.filter((i) =>\n isTaken(i, s.incidentsTaken, i.end)\n ).length;\n const marked = taken\n ? ` · ${taken} taken${s.hideTaken ? ' hidden' : ''}`\n : '';\n return `incidents · last ${DEFAULT_SINCE_MIN} min${since} · ${visibleIncidents(s).length} shown${marked}${up}`;\n }\n const shown =\n s.view === 'flat'\n ? s.rows\n : [selectedRow(s)].filter((r): r is LsRow => r !== null);\n const at = shown\n .map((r) => s.cleared[markKey(r.host, r.app)] ?? '')\n .filter(Boolean)\n .sort()\n .at(-1);\n const when = at ? ` · cleared ${clearedAt(at, now)}` : '';\n const who = s.view === 'flat' ? 'all apps' : (selectedRow(s)?.app ?? '-');\n return `logs · ${who} · ${s.stream}${when}${up}`;\n}\n\n/** A pane's one-line title rule: `── label ─────…` cut to the width. Panes have no frames, so a terminal selection copies text only. */\nexport function paneTitle(label: string, width: number): string {\n const head = `── ${label} `;\n return cut(head + '─'.repeat(Math.max(0, width - head.length)), width);\n}\n\nexport function frameToText(f: Frame): string {\n return [\n f.header,\n '',\n ...f.table,\n '',\n 'logs:',\n ...f.logs.map(stripAnsi),\n '',\n ...f.details,\n '',\n f.footer,\n ].join('\\n'); // text for agents: no escapes\n}\n","import { prepare, type Context } from '../core/resolve.js';\nimport { describeError, isMcprocError } from '../core/errors.js';\nimport { Fleet, listFleet } from '../core/fleet.js';\nimport type { Manifest } from '../core/manifest.js';\nimport { findProcess } from '../core/pm2.js';\nimport { createFollower, type LogLine } from '../core/logfollow.js';\nimport { historyReloads } from '../core/reloads.js';\nimport {\n appInfos,\n initialState,\n monitViews,\n reduce,\n selectedRow,\n viewLabel,\n} from './state.js';\nimport { frameToText, renderFrame } from './frame.js';\n\n/**\n * One frame of the monit surface as plain text: the same renderer the interactive screen uses, the same view it opens\n * on, with the selected app's reloads counted from the history it reads. `deps` stand in for the project's manifest,\n * its fleet and the log follower, and bound the app's own reloads patterns (budgetMs, default MATCH_BUDGET_MS): tests.\n */\nexport async function monitOnce(\n opts: {\n project?: string;\n host?: string;\n lines: number;\n width?: number;\n },\n deps: {\n manifest?: Manifest;\n fleet?: (requested: string | undefined) => Fleet;\n follower?: (\n ctx: Context,\n paths: { out: string; err: string },\n lines: number\n ) => { poll(): Promise<{ lines: LogLine[]; reset: boolean }> };\n budgetMs?: number;\n } = {}\n): Promise<string> {\n const manifest = deps.manifest ?? prepare({ project: opts.project }).manifest;\n const views = monitViews(manifest);\n const requested = opts.host ?? views[0];\n const fleet = deps.fleet?.(requested) ?? new Fleet(manifest, requested);\n let state = initialState({\n project: manifest.project,\n host: viewLabel(fleet.requested),\n hosts: views.map(viewLabel),\n apps: appInfos(manifest),\n });\n // defaults: inline cpu sample and the url checks — --once is the tool-facing frame\n const { rows, errors, probes } = await listFleet(\n fleet,\n fleet.select(['all'])\n );\n state = reduce(state, { type: 'rows', rows, at: new Date() });\n if (errors.length)\n state = reduce(state, {\n type: 'error',\n message: errors.map((e) => `${e.host}: ${e.message}`).join('; '),\n });\n const row = selectedRow(state);\n const probe = row ? probes.find((p) => p.apps.includes(row.app)) : undefined;\n const proc =\n row && probe?.snap\n ? findProcess(probe.snap.procs, manifest.project, row.app)\n : undefined;\n if (row && probe?.ctx && proc) {\n const paths = { out: proc.out_log, err: proc.err_log };\n const follow = deps.follower ?? createFollower;\n const { lines } = await follow(probe.ctx, paths, opts.lines).poll();\n state = reduce(state, { type: 'logs', app: row.app, lines, paths });\n try {\n const info = historyReloads(\n lines,\n manifest.apps[row.app]?.reloads ?? null,\n row,\n deps.budgetMs\n );\n if (info) state = reduce(state, { type: 'reloads', app: row.app, info });\n } catch (e) {\n if (!isMcprocError(e) || e.code !== 'TIMEOUT') throw e;\n state = reduce(state, {\n type: 'notice',\n message: `reloads of ${row.app} not counted: ${describeError(e)}`,\n });\n }\n }\n return frameToText(\n renderFrame(state, {\n width: opts.width ?? (process.stdout.columns || 120),\n height: 40,\n })\n );\n}\n","import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { McprocError } from '../core/errors.js';\nimport { findPackageRoot } from '../runtime/bundle.js';\nimport { shq } from '../transport/quote.js';\n\nexport const LAUNCHER_MARK = '# written by mcproc install';\n\nexport interface InstallOptions {\n binDir?: string;\n home?: string;\n shell?: string;\n pathEnv?: string;\n cliPath?: string;\n uninstall?: boolean;\n}\nexport interface InstallResult {\n launcher: string;\n binDir: string;\n cli: string;\n written: boolean;\n removed: boolean;\n onPath: boolean;\n rcFile: string | null;\n rcUpdated: boolean;\n next: string[];\n}\n\nfunction rcFor(home: string, shell: string): string {\n const name = path.basename(shell || '');\n return path.join(\n home,\n name === 'zsh' ? '.zshrc' : name === 'bash' ? '.bashrc' : '.profile'\n );\n}\n\n/**\n * Puts a `mcproc` shortcut on the shell PATH for a checkout (an `npm i -g` install needs none): a tiny sh launcher\n * that execs node on this package's dist/cli.js, plus one marked PATH line in the shell rc when the bin dir is not on PATH yet.\n * Idempotent; `uninstall` removes only a launcher it wrote and never edits the rc.\n */\nexport function installShortcut(o: InstallOptions = {}): InstallResult {\n const home = o.home ?? os.homedir();\n const binDir = path.resolve(o.binDir ?? path.join(home, '.local', 'bin'));\n const cli = path.resolve(\n o.cliPath ?? path.join(findPackageRoot(), 'dist', 'cli.js')\n );\n const launcher = path.join(binDir, 'mcproc');\n const pathEnv = o.pathEnv ?? process.env.PATH ?? '';\n const onPath = pathEnv\n .split(':')\n .some((p) => p && path.resolve(p.replace(/^~(?=\\/|$)/, home)) === binDir);\n const next: string[] = [];\n if (o.uninstall) {\n const exists = fs.existsSync(launcher);\n const ours =\n exists && fs.readFileSync(launcher, 'utf8').includes(LAUNCHER_MARK);\n if (ours) fs.unlinkSync(launcher);\n else if (exists)\n next.push(`${launcher} was not written by mcproc install; left in place`);\n else next.push(`nothing at ${launcher}`);\n return {\n launcher,\n binDir,\n cli,\n written: false,\n removed: ours,\n onPath,\n rcFile: null,\n rcUpdated: false,\n next,\n };\n }\n fs.mkdirSync(binDir, { recursive: true });\n // never write through a symlink (an `npm i -g` layout links bin/mcproc to the package) or over a file that is not ours\n let existing: fs.Stats | null = null;\n try {\n existing = fs.lstatSync(launcher);\n } catch {\n /* absent */\n }\n if (existing?.isSymbolicLink()) {\n throw new McprocError(\n 'BAD_ARGUMENT',\n `${launcher} is a symlink (to ${fs.readlinkSync(launcher)}); refusing to write through it`,\n { hint: 'Remove it yourself, or pass another --bin-dir.' }\n );\n }\n if (existing && !fs.readFileSync(launcher, 'utf8').includes(LAUNCHER_MARK)) {\n throw new McprocError(\n 'BAD_ARGUMENT',\n `${launcher} exists and was not written by mcproc install; refusing to overwrite it`,\n { hint: 'Remove it yourself, or pass another --bin-dir.' }\n );\n }\n fs.writeFileSync(\n launcher,\n `#!/bin/sh\\n${LAUNCHER_MARK}: runs the mcproc at ${path.dirname(path.dirname(cli))}\\nexec node ${shq(cli)} \"$@\"\\n`\n );\n fs.chmodSync(launcher, 0o755);\n let rcFile: string | null = null;\n let rcUpdated = false;\n if (!onPath) {\n rcFile = rcFor(home, o.shell ?? process.env.SHELL ?? '');\n const shown = binDir.startsWith(home + path.sep)\n ? `$HOME/${path.relative(home, binDir)}`\n : binDir;\n const line = `export PATH=\"${shown}:$PATH\"`;\n const current = fs.existsSync(rcFile)\n ? fs.readFileSync(rcFile, 'utf8')\n : '';\n if (!current.includes(line)) {\n fs.appendFileSync(\n rcFile,\n `${current === '' || current.endsWith('\\n') ? '' : '\\n'}\\n# mcproc install: the shortcut lives in ${shown}\\n${line}\\n`\n );\n rcUpdated = true;\n }\n next.push(`open a new shell (or run: ${line}) so that \\`mcproc\\` is found`);\n }\n next.push(\n 'register the MCP server once: claude mcp add -s user mcproc -- mcproc mcp'\n );\n return {\n launcher,\n binDir,\n cli,\n written: true,\n removed: false,\n onPath,\n rcFile,\n rcUpdated,\n next,\n };\n}\n","import blessed from '@pm2/blessed';\nimport { prepare } from '../core/resolve.js';\nimport type { Manifest } from '../core/manifest.js';\nimport { rowsFor, snapshot } from '../core/list.js';\nimport { Fleet, actOn } from '../core/fleet.js';\nimport { createFollower } from '../core/logfollow.js';\nimport {\n appInfos,\n CONFIRM_MS,\n initialState,\n keyIntent,\n monitViews,\n viewLabel,\n type MonitState,\n} from './state.js';\nimport {\n logsTitle,\n paneTitle,\n renderFrame,\n scrollTo,\n type Frame,\n} from './frame.js';\nimport { colorFor } from '../core/logstream.js';\nimport { MonitLoop, peekView, reloadView, type LoopDeps } from './loop.js';\nimport { screenDispatch } from './dispatch.js';\nimport { clearLogs, readStore, storePath } from '../core/incidents/store.js';\nimport { takenPoints } from '../core/incidents/taken.js';\n\nconst deps = (manifest: Manifest): LoopDeps => ({\n fleet: (requested) => new Fleet(manifest, requested),\n snapshot,\n rows: rowsFor,\n follower: createFollower,\n command: (fleet, cmd, app) => actOn(fleet, app, cmd),\n reloadAll: reloadView,\n clear: (fleet, apps) => clearLogs(fleet, apps),\n cleared: (fleet) => {\n const s = readStore(storePath(fleet.manifest.path));\n return { at: s.cleared, gen: s.clears, taken: takenPoints(s) };\n },\n peekIncidents: (fleet, names, cursor, restart) =>\n peekView(fleet, names, cursor, restart),\n});\n\n/** The blessed shell: it only paints frames from the pure renderer and forwards keys to the loop. */\nexport async function runMonit(opts: {\n project?: string;\n host?: string;\n intervalMs: number;\n lines: number;\n}): Promise<void> {\n const { manifest } = prepare({ project: opts.project });\n // apps bound to a host (`host:`) are shown from there: without --host the screen opens on every app at its own host\n const views = monitViews(manifest);\n const fleet = new Fleet(manifest, opts.host ?? views[0]);\n fleet.select(['all']); // a --host that no app runs on is refused here, before the screen takes the terminal\n let state: MonitState = initialState({\n project: manifest.project,\n host: viewLabel(fleet.requested),\n hosts: views.map(viewLabel),\n apps: appInfos(manifest),\n });\n\n const screen = blessed.screen({\n smartCSR: true,\n title: 'mcproc monit',\n fullUnicode: true,\n });\n // No frames: every pane is a one-line title rule plus full-width content, so a terminal drag-selection copies text only\n // (blessed enables mouse tracking only when something listens for mouse events, and nothing here does).\n // wrap: false everywhere — the renderer already cuts lines to the width.\n const box = (opts: Record<string, unknown>) =>\n blessed.box({ left: 0, width: '100%', wrap: false, ...opts });\n const header = box({ top: 0, height: 1 });\n const appsTitle = box({ top: 1, height: 1 });\n const tableBox = box({ top: 2, height: 1 });\n const logsHead = box({ top: 3, height: 1 });\n const logBox = box({\n top: 4,\n height: 5,\n scrollable: true,\n alwaysScroll: true,\n });\n const detailsTitle = box({ bottom: 7, height: 1 });\n const detailsBox = box({ bottom: 1, height: 6 });\n const footer = box({ bottom: 0, height: 1 });\n for (const b of [\n header,\n appsTitle,\n tableBox,\n logsHead,\n logBox,\n detailsTitle,\n detailsBox,\n footer,\n ])\n screen.append(b);\n\n // labels get the same ANSI colors as `mcproc logs`; blessed renders SGR codes in content, and the log text itself is\n // reduced by screen text to the apps' own color codes in the form blessed reads; tags are off, so no escaping is involved\n const appColor = new Map(\n Object.keys(manifest.apps).map((a, i) => [a, colorFor(i)])\n );\n const colorLabel = (line: string) => {\n const m = /^(\\S+)(\\s*)( [|!] )/.exec(line); // continuation rows start with spaces and keep no label\n const c = m && appColor.get(m[1]);\n return c ? `\\x1b[${c}m${m[1]}\\x1b[0m${line.slice(m[1].length)}` : line;\n };\n\n const size = () => ({\n width: screen.width as number,\n height: screen.height as number,\n });\n const show = (f: Frame) => {\n const { width: w, height: h } = size();\n header.setContent(f.header);\n footer.setContent(f.footer);\n if (state.view !== 'dashboard') {\n // the flat view and the incidents view: one pane across the screen\n for (const b of [appsTitle, tableBox, detailsTitle, detailsBox]) b.hide();\n logsHead.top = 1;\n logsHead.setContent(paneTitle(logsTitle(state, f.scroll), w));\n logBox.top = 2;\n logBox.height = Math.max(3, h - 3);\n logBox.setContent(\n (state.view === 'flat' ? f.logs.map(colorLabel) : f.logs).join('\\n')\n );\n } else {\n for (const b of [appsTitle, tableBox, detailsTitle, detailsBox]) b.show();\n appsTitle.setContent(paneTitle('apps', w));\n tableBox.height = f.table.length;\n tableBox.setContent(f.table.join('\\n'));\n logsHead.top = 2 + f.table.length;\n logsHead.setContent(paneTitle(logsTitle(state, f.scroll), w));\n logBox.top = 3 + f.table.length;\n logBox.height = Math.max(3, h - logBox.top - 8); // 8: details title + 6 details + footer\n logBox.setContent(f.logs.join('\\n'));\n detailsTitle.setContent(paneTitle('details', w));\n detailsBox.setContent(f.details.join('\\n'));\n }\n logBox.setScrollPerc(100);\n screen.render();\n };\n // reduce at once, paint once per burst (a wheel notch is three key presses), clamp a scroll by the pane as it is now\n const { dispatch, paint } = screenDispatch({\n get: () => state,\n set: (s) => {\n state = s;\n },\n render: (s) => renderFrame(s, size()),\n show,\n scrollTo: (s, delta) => scrollTo(s, size(), delta),\n });\n const loop = new MonitLoop(\n fleet,\n deps(manifest),\n { lines: opts.lines },\n () => state,\n dispatch\n );\n\n return new Promise<void>((resolve) => {\n const timer = setInterval(() => {\n void loop.refresh();\n }, opts.intervalMs);\n const quit = () => {\n clearInterval(timer);\n loop.close();\n screen.destroy();\n resolve();\n };\n screen.on(\n 'keypress',\n (_ch: string, key: { full?: string; name?: string }) => {\n const intent = keyIntent(key.full ?? key.name ?? '', state);\n // a pending clear or reload waits for the second press of its key; any other key cancels it (c and R arm their own)\n if (\n state.armedAt !== null &&\n !(intent?.kind === 'action' && intent.action.type === 'arm')\n )\n dispatch({ type: 'arm', at: null });\n if (!intent) return;\n if (intent.kind === 'quit') return quit();\n if (intent.kind === 'action') {\n if (intent.action.type === 'arm' && intent.action.at !== null) {\n const { at, what } = intent.action;\n setTimeout(() => {\n if (state.armedAt === at && state.armed === what)\n dispatch({ type: 'arm', at: null });\n }, CONFIRM_MS + 50).unref();\n }\n if (intent.action.type === 'select')\n loop.dispatchSelect(intent.action.delta);\n else {\n dispatch(intent.action);\n if (intent.action.type === 'view') void loop.refresh();\n } // fill the new view at once\n return;\n }\n if (intent.kind === 'host-next') return void loop.nextView();\n if (intent.kind === 'clear') return void loop.runClear(intent.apps);\n if (intent.kind === 'reload-all') return void loop.reloadAll();\n void loop.runCommand(intent.cmd, intent.app);\n }\n );\n screen.on('resize', paint);\n void loop.refresh().then(paint);\n });\n}\n","import { describeError, isMcprocError } from '../core/errors.js';\nimport {\n unreachableRow,\n type LsRow,\n type Snapshot,\n type SnapshotOptions,\n} from '../core/list.js';\nimport { findProcess } from '../core/pm2.js';\nimport { assertWritable, pickHost, type Context } from '../core/resolve.js';\nimport {\n actOn,\n assertWritableRuns,\n type Fleet,\n type HostApps,\n} from '../core/fleet.js';\nimport type { StatSample } from '../core/stats.js';\nimport type { FollowPoll, LogLine } from '../core/logfollow.js';\nimport {\n countedClearKey,\n isAppClearKey,\n parseFileClearKey,\n takeIncidents,\n type Cleared,\n type TakenAnswer,\n} from '../core/incidents/store.js';\nimport { markKey, type CursorState } from '../core/incidents/cursor.js';\nimport type { TakenPoints } from '../core/incidents/taken.js';\nimport {\n compileReloadRules,\n historyReaches,\n reloadCount,\n reloadStamp,\n ReloadTracker,\n} from '../core/reloads.js';\nimport { fmtBytes } from '../mcp/render.js';\nimport {\n MAX_INCIDENTS,\n monitViews,\n selectedRow,\n viewLabel,\n type MonitAction,\n type MonitState,\n type ReloadInfo,\n} from './state.js';\n\nexport type Cmd = 'start' | 'restart' | 'stop';\nexport interface Follower {\n poll(): Promise<FollowPoll>;\n /** calls `wake` as soon as the followed files change, when the follower can tell */\n watch?(wake: () => void): void;\n /** stops the wakes */\n close?(): void;\n}\ntype Paths = { out: string; err: string };\ninterface WakeQueue {\n dirty: Set<string>;\n /** a poll of these apps is scheduled or running */\n running: boolean;\n timer: NodeJS.Timeout | null;\n last: number;\n}\n/** What the loop needs from the rest of mcproc, injectable so the races below are testable without a terminal. */\nexport interface LoopDeps {\n /** the fleet a view acts on: `requested` is the --host it stands for (undefined = every app at its own host) */\n fleet(requested: string | undefined): Fleet;\n snapshot(ctx: Context, opts: SnapshotOptions): Promise<Snapshot>;\n rows(ctx: Context, snap: Snapshot, apps: string[]): LsRow[];\n follower(\n ctx: Context,\n paths: { out: string; err: string },\n lines: number\n ): Follower;\n /** the rows of what the command touched (a dependency on another host included), or nothing */\n command(fleet: Fleet, cmd: Cmd, app: string): Promise<LsRow[] | undefined>;\n /** `start all --reload` over the fleet: every app in dependency order with its waits; `signal` ends those waits as aborted */\n reloadAll(fleet: Fleet, signal: AbortSignal): Promise<LsRow[] | undefined>;\n /** truncate the apps' logs and record the clear in the project's store (incidents start there) */\n clear(fleet: Fleet, apps: string[]): Promise<Cleared[]>;\n /**\n * the clears recorded in the project's store, keyed host/app: when (shown in the title) and how many (a new one\n * restarts that app's logs); and how far the agent's takes have read each file (the incidents view mutes what lies before)\n */\n cleared(fleet: Fleet): {\n at: Record<string, string>;\n gen: Record<string, number>;\n taken?: TakenPoints;\n };\n /** the incidents view's read: new incidents of the apps since `cursor`, the screen's own position, never taking any */\n peekIncidents(\n fleet: Fleet,\n names: string[],\n cursor: CursorState,\n restart: Restarts\n ): Promise<{ answer: TakenAnswer; next: CursorState }>;\n}\n\nexport { describeError };\n\n/**\n * What `R` twice runs (the screen's `reloadAll` dep): `start all --reload` over the view's fleet, so every app in\n * dependency order with its waits; running apps restart, stopped ones start, tasks run again. `signal` ends the waits.\n */\nexport const reloadView = (\n fleet: Fleet,\n signal: AbortSignal\n): Promise<LsRow[]> => actOn(fleet, 'all', 'start', { reload: true, signal });\n\n/** Files emptied since the incidents view last read them, per host/app and stream: their paths, or `*` for either. */\nexport type Restarts = Record<string, Partial<Record<'out' | 'err', string[]>>>;\n\ninterface IncidentsView {\n cursor: CursorState | null;\n last: number;\n running: boolean;\n clears: number;\n pending: Record<string, Partial<Record<'out' | 'err', Set<string>>>>;\n}\nconst freshView = (): IncidentsView => ({\n cursor: null,\n last: 0,\n running: false,\n clears: 0,\n pending: {},\n});\n\n/** The incidents view reads again at most this often while it is open (and not at all while it is closed). */\nexport const INCIDENTS_POLL_MS = 5000;\n\n/**\n * What the incidents view reads (the screen's `peekIncidents` dep): the apps' new incidents since `cursor` through the\n * peek path, so the pick-up point the agent takes from is neither the start nor moved. An empty cursor reads the window a\n * first call reads. `file`: the store, for the last clear only (default: next to the manifest).\n */\nexport const peekView = (\n fleet: Fleet,\n names: string[],\n cursor: CursorState,\n restart: Restarts = {},\n file?: string\n): Promise<{ answer: TakenAnswer; next: CursorState }> =>\n takeIncidents(\n fleet,\n names,\n { peek: true, cursor, restart, max: MAX_INCIDENTS, chars: Infinity }, // a screen shows them all\n file\n );\n\n/** One followed app's reloads since its pm2 start: the run it counts (its start and restarts) and the count so far. */\ninterface Counter {\n tracker: ReloadTracker;\n started: string;\n restarts: number;\n info: ReloadInfo;\n}\n\n/** polls a wake asks for run at most this often: a chatty app repaints the screen in steps, not on every write */\nconst WAKE_GAP_MS = 50;\n\n/**\n * The monit screen's data loop: periodic refreshes of every host the view reaches, each host on its own, log following\n * for the selected app (or every app in the flat view) on the host it runs on, view switches and commands. Every refresh\n * belongs to a generation; a view switch starts a new one, and whatever an older refresh still returns is dropped. The\n * followers of the apps on screen wake the loop when their files change, so new lines show without waiting for a\n * refresh; the refresh stays as the clock behind them.\n */\nexport class MonitLoop {\n private gen = 0;\n /** one refresh in flight per host: a host that hangs holds back only its own rows, never the others' */\n private inflight = new Map<string, { gen: number; done: Promise<void> }>();\n private followers = new Map<string, { f: Follower; paths: Paths }>(); // app names are unique across hosts\n private watched = new Set<string>(); // apps whose follower wakes the loop: the ones on screen\n /** per host: woken apps waiting for their poll — a slow host never holds another host's lines */\n private wakes = new Map<string, WakeQueue>();\n private closed = false;\n private prev = new Map<string, { sample: StatSample; at: number }>(); // per host: cpu is a difference of two samples of one clock\n private latest = new Map<string, LsRow>(); // the newest row of each app in this view\n private errors = new Map<string, string>(); // hosts whose last refresh failed, and why\n private epochs = new Map<string, number>(); // per app, bumped by each clear: a read begun before it is dropped\n private seen: Record<string, number> = {}; // the clear counts of the store this screen has acted on\n private switchSeq = 0; // the newest view switch asked for: an older one that connects late changes nothing\n private counters = new Map<string, Counter>(); // per followed app with reloads on and a known start\n /**\n * per app, when its lines were last lost (a poll that lost some, or a clear), numbered by `losses`: until rows taken\n * after it were looked at, a run those rows did not know yet may have begun in that gap, so a fresh look at a run\n * counts as partial\n */\n private gaps = new Map<string, number>();\n private losses = 0;\n private uncounted = new Set<string>(); // apps whose own reloads patterns ran away: not counted again in this view\n private reloading: AbortController | null = null; // the running reload of the view: quitting ends its dependency waits\n private names: string[];\n private groups: HostApps[];\n /**\n * the incidents view's own position (null: not read yet in this view), when it last read, whether a read runs, how\n * many log clears it has seen (a read that spans one is dropped: its position is from before the clear), and the files\n * emptied since it last read them, which its next read starts at their beginning when pm2 still writes them\n */\n private inc: IncidentsView = freshView();\n\n constructor(\n public fleet: Fleet,\n private readonly deps: LoopDeps,\n /** budgetMs: how long an app's own reloads patterns may take on one poll's lines (default MATCH_BUDGET_MS) */\n private readonly opts: { lines: number; budgetMs?: number },\n private readonly getState: () => MonitState,\n public readonly dispatch: (a: MonitAction) => void\n ) {\n this.names = fleet.select(['all']);\n this.groups = fleet.groups(this.names);\n }\n\n /** One refresh of every host of the view (or of `hosts`); a host whose refresh of this generation is still in flight shares it. */\n refresh(hosts?: string[]): Promise<void> {\n this.readCleared();\n this.syncWatches();\n const gen = this.gen;\n // the incidents view reads with the periodic refresh of the whole view, not with one that follows a command\n const incidents =\n !hosts && this.getState().view === 'incidents'\n ? this.pollIncidents()\n : undefined;\n return Promise.all([\n ...this.groups\n .filter((g) => !hosts || hosts.includes(g.host))\n .map((g) => {\n const cur = this.inflight.get(g.host);\n if (cur && cur.gen === gen) return cur.done;\n const done: Promise<void> = this.runHost(gen, g).finally(() => {\n if (this.inflight.get(g.host)?.done === done)\n this.inflight.delete(g.host);\n });\n this.inflight.set(g.host, { gen, done });\n return done;\n }),\n incidents,\n ]).then(() => undefined);\n }\n\n /**\n * One read of the incidents view: from its own position (the first one from an empty position, so the window a first\n * call reads), at most every INCIDENTS_POLL_MS, one at a time. What it could not read is shown in the view; a failed\n * read keeps the position, so the next one tries the same lines again. A read of a view that has changed meanwhile,\n * or of a screen that went away, is dropped.\n */\n private async pollIncidents(): Promise<void> {\n const st = this.inc;\n if (this.closed || st.running) return;\n if (st.cursor && Date.now() - st.last < INCIDENTS_POLL_MS) return;\n st.running = true;\n const gen = this.gen;\n const clears = st.clears;\n const stale = () => this.closed || gen !== this.gen || st.clears !== clears;\n const restart: Restarts = Object.fromEntries(\n Object.entries(st.pending).map(([k, by]) => [\n k,\n Object.fromEntries(\n Object.entries(by).map(([stream, paths]) => [stream, [...paths]])\n ),\n ])\n );\n try {\n const { answer, next } = await this.deps.peekIncidents(\n this.fleet,\n this.names,\n st.cursor ?? { v: 1, apps: {} },\n restart\n );\n if (stale()) return;\n st.cursor = next;\n st.last = Date.now();\n // a file this read positioned began at its start if it was emptied, or pm2 no longer writes the emptied path; a\n // restart of a file it did not reach (a host that failed, an app that stalled or is not running) waits for the next\n for (const [key, streams] of Object.entries(answer.positioned ?? {})) {\n const by = st.pending[key];\n if (!by) continue;\n for (const s of streams) delete by[s];\n if (!by.out && !by.err) delete st.pending[key];\n }\n this.dispatch({\n type: 'incidents',\n // each with where this read ended in its file: what tells one stamped like the agent's last line from a later one\n incidents: answer.incidents.map((i) => {\n const m = next.apps[markKey(i.host, i.app)]?.[i.stream];\n return m ? { ...i, end: { path: m.path, offset: m.offset } } : i;\n }),\n cleared_at: answer.cleared_at,\n errors: [\n ...answer.errors.map((e) => `${e.host}: ${e.message}`),\n ...answer.skipped.map(\n (k) =>\n `skipped ${fmtBytes(k.bytes)} of ${k.app} ${k.stream} on ${k.host} (too much new log; the most recent 1 MB was read)`\n ),\n ...(answer.more > 0\n ? [`+${answer.more} older incidents not shown`]\n : []),\n ],\n });\n } catch (e) {\n if (stale()) return;\n st.last = Date.now();\n this.dispatch({\n type: 'incidents',\n incidents: [],\n cleared_at: this.getState().incidentsCleared,\n errors: [`incidents: ${describeError(e)}`],\n });\n } finally {\n st.running = false;\n }\n }\n\n /** A refresh that reflects a change just made on `hosts`: waits for their current refresh, then runs again. */\n private async refreshAfterCurrent(hosts: string[]): Promise<void> {\n const current = hosts\n .map((h) => this.inflight.get(h))\n .filter((c) => c && c.gen === this.gen);\n await Promise.all(current.map((c) => c!.done.catch(() => undefined)));\n if (this.closed) return; // the screen went away while that refresh ran: nothing to reflect any more\n return this.refresh(hosts);\n }\n\n /** Rows of every app in manifest order: the newest of each, the error of every host that did not answer in the footer. */\n private publish(heard: boolean): void {\n this.dispatch({\n type: 'rows',\n rows: this.names.flatMap((n) => this.latest.get(n) ?? []),\n ...(heard ? { at: new Date() } : {}),\n });\n if (this.errors.size)\n this.dispatch({\n type: 'error',\n message: [...this.errors]\n .map(([h, m]) => (this.groups.length > 1 ? `${h}: ${m}` : m))\n .join('; '),\n });\n }\n\n private async runHost(gen: number, g: HostApps): Promise<void> {\n const probed = this.losses; // a gap numbered after this was not seen by the rows this refresh takes\n try {\n const ctx = await this.fleet.ctx(g.host);\n // the live screen never requests the apps' URLs: dev servers log every request, and this pane is where those logs are read\n const snap = await this.deps.snapshot(ctx, {\n cpu: 'none',\n prev: this.prev.get(g.host),\n urls: 'none',\n });\n if (gen !== this.gen) return; // the view changed meanwhile\n if (snap.stats.samples[0])\n this.prev.set(g.host, {\n sample: snap.stats.samples[0],\n at: snap.sampledAt,\n });\n for (const r of this.deps.rows(ctx, snap, g.apps))\n this.latest.set(r.app, r);\n this.errors.delete(g.host);\n this.publish(true);\n // every app gets its own buffer and follower; the dashboard polls the selected app, the flat view every running one.\n // Lines are consumed from the file by offset, so a poll's result always lands in its app's buffer — even if the\n // selection moved on meanwhile (the reducer only shows the selected app; nothing is lost).\n const state = this.getState();\n const selected = selectedRow(state)?.app;\n for (const app of state.view === 'flat'\n ? g.apps\n : g.apps.filter((a) => a === selected)) {\n const proc = findProcess(snap.procs, this.fleet.manifest.project, app);\n if (!proc) continue;\n const paths = { out: proc.out_log, err: proc.err_log };\n let e = this.followers.get(app);\n if (!e) {\n e = { f: this.deps.follower(ctx, paths, this.opts.lines), paths };\n this.followers.set(app, e);\n }\n const epoch = this.epochs.get(app);\n const r = await e.f.poll();\n if (gen !== this.gen) return; // the view moved on during the poll\n if (this.epochs.get(app) !== epoch) continue; // cleared during the read: these lines are from before the clear\n const before = this.getState().logs[app] ?? [];\n this.dispatch({\n type: 'logs',\n app,\n lines: r.lines,\n reset: r.reset,\n paths,\n });\n this.track(app, r.lines, before, r.lost === true);\n // the rows were taken before this poll, so what it lost may hold a run they do not know yet; an older gap is\n // settled once a counter of the app has looked at rows taken after it\n if (r.lost) this.gaps.set(app, ++this.losses);\n else if (this.counters.has(app) && (this.gaps.get(app) ?? 0) <= probed)\n this.gaps.delete(app);\n }\n this.syncWatches();\n } catch (e) {\n if (gen !== this.gen) return;\n // a host that did not answer keeps its apps' last rows (unreachable ones the first time); the footer says why\n this.errors.set(g.host, describeError(e));\n for (const a of g.apps)\n if (!this.latest.has(a))\n this.latest.set(\n a,\n unreachableRow(\n this.fleet.manifest.apps[a],\n g.host,\n describeError(e)\n )\n );\n this.publish(false);\n }\n }\n\n /** the apps whose logs the screen shows: the selected one, or every app in the flat view */\n private onScreen(): Set<string> {\n const s = this.getState();\n if (s.view === 'flat') return new Set(this.names);\n const app = selectedRow(s)?.app;\n return new Set(app ? [app] : []);\n }\n\n /** The followers of the apps on screen wake the loop; the others stop. */\n private syncWatches(): void {\n if (this.closed) return;\n const want = this.onScreen();\n for (const app of [...this.watched]) if (!want.has(app)) this.unwatch(app);\n for (const app of want) {\n const e = this.followers.get(app);\n if (!e?.f.watch || this.watched.has(app)) continue;\n this.watched.add(app);\n e.f.watch(() => this.wake(app));\n }\n }\n\n private unwatch(app: string): void {\n if (this.watched.delete(app)) this.followers.get(app)?.f.close?.();\n }\n\n private wake(app: string): void {\n if (!this.watched.has(app)) return;\n const host = this.fleet.hostOf(app);\n let q = this.wakes.get(host);\n if (!q) {\n q = { dirty: new Set(), running: false, timer: null, last: 0 };\n this.wakes.set(host, q);\n }\n q.dirty.add(app);\n this.kick(q);\n }\n\n /** Polls a host's woken apps now, or once the gap since its last such poll has passed. */\n private kick(q: WakeQueue): void {\n if (q.running || !q.dirty.size || this.closed) return;\n q.running = true;\n const run = () => {\n q.timer = null;\n void this.pollWoken(q);\n };\n const wait = q.last + WAKE_GAP_MS - Date.now();\n if (wait > 0) q.timer = setTimeout(run, wait);\n else queueMicrotask(run);\n }\n\n /** One poll of a host's woken apps; their lines are dispatched together, so the screen paints once. */\n private async pollWoken(q: WakeQueue): Promise<void> {\n const gen = this.gen;\n const apps = [...q.dirty];\n q.dirty.clear();\n q.last = Date.now();\n try {\n const got = await Promise.allSettled(\n apps.map(async (app) => {\n const e = this.followers.get(app);\n if (!e) return null;\n const epoch = this.epochs.get(app);\n return { app, e, epoch, r: await e.f.poll() }; // a host that fails here is reported by the next refresh\n })\n );\n for (const g of got) {\n if (g.status !== 'fulfilled' || !g.value) continue;\n const { app, e, epoch, r } = g.value;\n // the view moved on, the follower was replaced or the logs were cleared during the read\n if (\n gen !== this.gen ||\n this.followers.get(app) !== e ||\n this.epochs.get(app) !== epoch\n )\n continue;\n const before = this.getState().logs[app] ?? [];\n if (r.lines.length || r.reset)\n this.dispatch({\n type: 'logs',\n app,\n lines: r.lines,\n reset: r.reset,\n paths: e.paths,\n });\n this.track(app, r.lines, before, r.lost === true);\n if (r.lost) this.gaps.set(app, ++this.losses);\n }\n } finally {\n q.running = false;\n this.kick(q);\n }\n }\n\n /**\n * Counts the reloads in a followed app's new lines and closes a burst that went quiet. The first look at a run (the\n * app's first poll, or the first after pm2 started it again) starts a tracker over what the screen buffered of the\n * app's log before this poll, then every line of this poll: a new run's boot that a wake delivered before the rows told\n * of the restart is still taken for the boot, and a catch-up poll longer than the buffer loses nothing. After a\n * restart the count starts at 0 and is exact (the new run is followed from its start); a first look is judged by how\n * far those lines reach back. Lines lost by this poll (`lost`), or by one since the rows were taken (`gaps`), make the\n * count partial for the rest of its run, and the change is shown even when no reload closed.\n */\n private track(\n app: string,\n lines: LogLine[],\n before: LogLine[],\n lost: boolean\n ): void {\n const settings = this.fleet.manifest.apps[app]?.reloads;\n const row = this.latest.get(app);\n if (!settings || !row || this.uncounted.has(app)) return;\n const prev = this.counters.get(app);\n const { started, restarts } = row;\n const now = Date.now();\n const gap = lost || this.gaps.has(app);\n try {\n if (\n started !== null &&\n (!prev || prev.started !== started || prev.restarts !== restarts)\n ) {\n const input = [...before, ...lines];\n const rules = compileReloadRules(settings, this.opts.budgetMs);\n let tracker = null as ReloadTracker | null;\n const info = reloadCount(\n prev ? ['start'] : historyReaches(input, started),\n (coversStart) => {\n tracker = new ReloadTracker(rules, {\n app,\n start: started,\n coversStart,\n });\n return [...tracker.push(input, now), ...tracker.idle(now)];\n }\n );\n if (!tracker) return;\n if (gap) info.partial = true;\n this.counters.set(app, { tracker, started, restarts, info });\n this.dispatch({ type: 'reloads', app, info });\n return;\n }\n if (!prev) return;\n const found = [\n ...prev.tracker.push(lines, now),\n ...prev.tracker.idle(now),\n ];\n const last = found.at(-1);\n const partial = prev.info.partial || gap;\n if (!last && partial === prev.info.partial) return;\n prev.info = {\n count: prev.info.count + found.length,\n last: last ? reloadStamp(last) : prev.info.last,\n partial,\n };\n this.dispatch({ type: 'reloads', app, info: prev.info });\n } catch (e) {\n if (!isMcprocError(e) || e.code !== 'TIMEOUT') throw e;\n // its own patterns ran away: this app goes without a count, its logs and the other apps' counts go on\n this.counters.delete(app);\n this.uncounted.add(app);\n this.dispatch({ type: 'reloads', app, info: null });\n this.dispatch({\n type: 'notice',\n message: `reloads of ${app} not counted: ${describeError(e)}`,\n });\n }\n }\n\n /** The screen is going away: no follower wakes it any more, and a running reload stops waiting for dependencies. */\n close(): void {\n this.closed = true;\n this.reloading?.abort();\n for (const q of this.wakes.values()) {\n if (q.timer) clearTimeout(q.timer);\n q.timer = null;\n q.dirty.clear();\n }\n for (const app of [...this.watched]) this.unwatch(app);\n }\n\n /** The user moved the selection: refresh its host so an app seen for the first time gets its follower (history) at once. */\n dispatchSelect(delta: number): void {\n const before = selectedRow(this.getState())?.app;\n this.dispatch({ type: 'select', delta });\n const after = selectedRow(this.getState())?.app;\n if (after && after !== before)\n void this.refreshAfterCurrent([this.fleet.hostOf(after)]);\n }\n\n /** `h`: the next view — all apps at their hosts, then each host as --host would narrow it. */\n nextView(): Promise<void> {\n const views = monitViews(this.fleet.manifest);\n return this.switchView(\n views[(views.indexOf(this.fleet.requested) + 1) % views.length]\n );\n }\n\n /** Switch to the view of `requested`; when none of its hosts can be reached, the current view stays and the footer says why. */\n async switchView(requested: string | undefined): Promise<void> {\n const seq = ++this.switchSeq;\n this.dispatch({ type: 'busy', busy: true });\n try {\n const fleet = this.deps.fleet(requested);\n const names = fleet.select(['all']);\n const groups = fleet.groups(names);\n const connected = await Promise.allSettled(\n groups.map((g) => fleet.ctx(g.host))\n );\n if (seq !== this.switchSeq) return; // a newer switch was asked for meanwhile: it decides the view\n const firstFailure = connected.find(\n (c): c is PromiseRejectedResult => c.status === 'rejected'\n );\n if (firstFailure && connected.every((c) => c.status === 'rejected'))\n throw firstFailure.reason;\n this.gen++;\n this.fleet = fleet;\n this.names = names;\n this.groups = groups;\n for (const app of [...this.watched]) this.unwatch(app);\n this.followers.clear();\n this.counters.clear(); // the new view's followers start with their history, which is counted afresh\n this.gaps.clear();\n this.uncounted.clear();\n this.prev.clear();\n this.latest.clear();\n this.errors.clear();\n this.inc = freshView(); // the incidents of the new view are read afresh\n this.dispatch({ type: 'host', host: viewLabel(requested) });\n await this.refresh(); // a new generation: starts at once, the old view's pending probes are dropped when they return\n } catch (e) {\n if (seq === this.switchSeq)\n this.dispatch({ type: 'error', message: describeError(e) });\n } finally {\n if (seq === this.switchSeq) this.dispatch({ type: 'busy', busy: false });\n }\n }\n\n /**\n * One change made from the screen. While it runs: busy, and `<label>…` in the footer. The guard runs first, so a\n * refusal touches nothing. Then the change, then a refresh of `hosts`, and only then how it ended, together with busy\n * off: the footer never says done while keys are still refused. Once the screen has gone away (quit, at any point of\n * the step), it issues nothing more: no refresh, no notice, no busy.\n */\n private async step(o: {\n label: string;\n guard: () => void;\n act: () => Promise<LsRow[] | undefined>;\n /** the hosts the change touched */\n hosts: () => string[];\n }): Promise<void> {\n this.dispatch({ type: 'busy', busy: true });\n this.dispatch({ type: 'notice', message: `${o.label}…` });\n try {\n o.guard();\n const bad = ((await o.act()) ?? []).filter((r) => r.error);\n if (this.closed) return;\n await this.refreshAfterCurrent(o.hosts());\n if (this.closed) return;\n // a dependency may have started on one host while the app itself failed on another: never report that as done\n this.dispatch({\n type: 'notice',\n message: bad.length\n ? `${o.label} partly failed: ${bad[0].app} (${bad[0].host}): ${bad[0].error}`\n : `${o.label}: done`,\n });\n } catch (e) {\n if (this.closed) return;\n // a notice, not an `error`: the next good refresh clears errors within the interval, but a failed change must stay readable\n this.dispatch({\n type: 'notice',\n message: `${o.label} failed: ${describeError(e)}`,\n });\n } finally {\n if (!this.closed) this.dispatch({ type: 'busy', busy: false });\n }\n }\n\n runCommand(cmd: Cmd, app: string): Promise<void> {\n return this.step({\n label: `${cmd} ${app}`,\n // the actions do not check by themselves: the CLI and the MCP tools guard, so must the screen — on the app's own host\n guard: () =>\n assertWritable(pickHost(this.fleet.manifest, this.fleet.hostOf(app))),\n act: () => this.deps.command(this.fleet, cmd, app),\n hosts: () => [this.fleet.hostOf(app)],\n });\n }\n\n /**\n * `R` twice: `start all --reload` over the view — every app at its own host, or only those of the host `h` narrowed\n * to — in dependency order with their waits; running apps restart, stopped ones start, tasks run again. A view with an\n * app on a readonly host is refused whole before anything runs: reloading only the writable hosts could stop halfway on\n * a dependency there. Then every host of the view is refreshed.\n */\n async reloadAll(): Promise<void> {\n const fleet = this.fleet;\n const names = this.names;\n const hosts = this.groups.map((g) => g.host);\n const abort = new AbortController();\n this.reloading = abort;\n try {\n await this.step({\n label: 'reload all',\n guard: () => assertWritableRuns(fleet, fleet.runs(names), names),\n act: () => this.deps.reloadAll(fleet, abort.signal),\n hosts: () => hosts,\n });\n } finally {\n if (this.reloading === abort) this.reloading = null;\n }\n }\n\n /** The clears recorded in the store (by this screen, the CLI or an agent), dispatched when they changed: the log pane title shows them. */\n private readCleared(): void {\n const { at, gen, taken } = this.deps.cleared(this.fleet);\n if (\n taken &&\n JSON.stringify(taken) !== JSON.stringify(this.getState().incidentsTaken)\n )\n this.dispatch({ type: 'taken', taken });\n // a count that appears or grows is a clear; one that vanished (the store was removed) is none\n const changed = Object.keys(gen).filter(\n (key) => gen[key] !== this.seen[key]\n );\n const apps = changed.filter(isAppClearKey);\n const before = this.seen;\n this.seen = { ...gen };\n this.restart(\n apps\n .map((key) => key.slice(key.indexOf('/') + 1))\n .filter((a) => this.names.includes(a))\n );\n this.clearIncidents(changed, gen, before);\n if (JSON.stringify(at) !== JSON.stringify(this.getState().cleared))\n this.dispatch({ type: 'cleared', cleared: at });\n }\n\n /**\n * Clears of apps in view that the incidents view has read: each file they emptied (by path, as the store counts them)\n * is started at its beginning by the view's next read when pm2 still writes it, and a clear by an mcproc that counts\n * no files (its app count grew more than the clears that counted theirs) starts either file of the app. A file the\n * clear could not empty keeps its place, so nothing is shown twice. The counts are the clear's own record, never the\n * shared point (an agent may take before the view looks). A read under way is dropped: its position is from before.\n */\n private clearIncidents(\n changed: string[],\n gen: Record<string, number>,\n before: Record<string, number>\n ): void {\n const inView = new Set(\n this.names.map((a) => markKey(this.fleet.hostOf(a), a))\n );\n const st = this.inc;\n const add = (key: string, stream: 'out' | 'err', path: string) => {\n const by = st.pending[key] ?? {};\n const paths = by[stream] ?? new Set<string>();\n paths.add(path);\n by[stream] = paths;\n st.pending[key] = by;\n };\n let any = false;\n for (const k of changed) {\n const f = parseFileClearKey(k);\n const key = f?.key ?? (isAppClearKey(k) ? k : null);\n if (!key || !inView.has(key)) continue;\n any = true;\n if (!st.cursor?.apps[key]) continue; // not read yet: its first read sees the emptied files\n if (f) add(key, f.stream, f.path);\n else {\n const grew = (k2: string) =>\n Math.max(0, (gen[k2] ?? 0) - (before[k2] ?? 0));\n if (grew(k) > grew(countedClearKey(k))) {\n add(k, 'out', '*');\n add(k, 'err', '*');\n }\n }\n }\n if (any) st.clears++;\n }\n\n /**\n * The logs of these apps start over (they were cleared): buffers empty, the next refresh reads the emptied files with a\n * new follower — the old one would go on at its offset if the file regrew past it — and a read begun before is dropped.\n * A count kept across the clear is partial from now on: what the clear removed may hold reloads, or a new run's start.\n */\n private restart(apps: string[]): void {\n for (const app of apps) {\n this.unwatch(app);\n this.followers.delete(app);\n this.epochs.set(app, (this.epochs.get(app) ?? 0) + 1);\n this.dispatch({ type: 'logs', app, lines: [], reset: true });\n const c = this.counters.get(app);\n if (!c) continue;\n this.gaps.set(app, ++this.losses);\n if (c.info.partial) continue;\n c.info = { ...c.info, partial: true };\n this.dispatch({ type: 'reloads', app, info: c.info });\n }\n }\n\n /** `c` twice: clear the logs of the view's running apps; apps on a readonly host are skipped and named. */\n async runClear(apps: string[]): Promise<void> {\n const ro = apps.filter(\n (a) => pickHost(this.fleet.manifest, this.fleet.hostOf(a)).readonly\n );\n const go = apps.filter((a) => !ro.includes(a));\n const skipped = ro.length\n ? `; skipped ${ro.join(', ')} (readonly host)`\n : '';\n if (go.length === 0)\n return this.dispatch({\n type: 'notice',\n message: `nothing cleared${skipped}`,\n });\n this.dispatch({ type: 'busy', busy: true });\n this.dispatch({\n type: 'notice',\n message: `clearing logs of ${go.join(', ')}…`,\n });\n try {\n const r = await this.deps.clear(this.fleet, go);\n const freed = r.reduce((t, x) => t + x.out_bytes + x.err_bytes, 0);\n const failed = r.flatMap((x) => x.failed ?? []);\n const kept = failed.length\n ? `; could not truncate ${failed.join(', ')} (its incidents go on from before)`\n : '';\n this.readCleared(); // the store counted the clear: the apps whose files emptied start over\n await this.refreshAfterCurrent([\n ...new Set(go.map((a) => this.fleet.hostOf(a))),\n ]);\n // shown once the refresh is done, together with busy off: never \"cleared\" while keys are still refused\n this.dispatch({\n type: 'notice',\n message: `cleared logs of ${go.join(', ')} (${fmtBytes(freed)}); incidents start here${skipped}${kept}`,\n });\n } catch (e) {\n this.dispatch({\n type: 'notice',\n message: `clear failed: ${describeError(e)}`,\n });\n } finally {\n this.dispatch({ type: 'busy', busy: false });\n }\n }\n}\n","/**\n * Work asked for several times in one synchronous burst runs once, right after it: a wheel notch arrives as three key\n * events in one input chunk, a refresh dispatches rows and an error together, and the screen needs one paint for each\n * burst. The run is a microtask, so it happens before the next input or I/O callback: a key never acts on a frame\n * older than the state (the scroll ceiling comes from the last painted frame).\n */\nexport function coalesce(\n run: () => void,\n defer: (cb: () => void) => void = queueMicrotask\n): () => void {\n let pending = false;\n return () => {\n if (pending) return;\n pending = true;\n defer(() => {\n pending = false;\n run();\n });\n };\n}\n","import { coalesce } from './coalesce.js';\nimport { reduce, type MonitAction, type MonitState } from './state.js';\nimport type { Frame } from './frame.js';\n\n/**\n * The screen's dispatch: every action reduces at once, the screen paints once per burst (see coalesce), and a scroll\n * is clamped by the ceiling of the pane as it is NOW. The ceiling only changes with what the pane shows, never with the\n * scroll position, so a burst of scroll keys reuses the one of the last paint; a key that changed the pane in the same\n * burst (`b`, then Home) makes the next scroll measure it again instead of trusting a frame painted before that key.\n */\nexport function screenDispatch(io: {\n get: () => MonitState;\n set: (s: MonitState) => void;\n render: (s: MonitState) => Frame;\n show: (f: Frame) => void;\n defer?: (cb: () => void) => void;\n /** where a scroll of `delta` rows lands, measured on the pane as it is now (frame scrollTo); without it, whole entries */\n scrollTo?: (\n s: MonitState,\n delta: number\n ) => { entries: number; rows: number };\n}): { dispatch: (a: MonitAction) => void; paint: () => void } {\n let ceiling: number | undefined;\n const paint = () => {\n const f = io.render(io.get());\n ceiling = f.maxScroll;\n io.show(f);\n };\n const schedule = coalesce(paint, io.defer);\n const dispatch = (a: MonitAction) => {\n if (a.type === 'scroll' && io.scrollTo) {\n io.set(reduce(io.get(), { ...a, to: io.scrollTo(io.get(), a.delta) }));\n } else if (a.type === 'scroll') {\n ceiling ??= io.render(io.get()).maxScroll;\n io.set(reduce(io.get(), { ...a, max: ceiling }));\n } else {\n io.set(reduce(io.get(), a));\n ceiling = undefined;\n }\n schedule();\n };\n return { dispatch, paint };\n}\n","import { buildProgram } from './cli/program.js';\n\nawait buildProgram().parseAsync(process.argv);\n"],"mappings":"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","names":["fs","fs","os","path","createRequire","name","createRequire","path","fs","path","parseYaml","z","q","own","path","path","varName","v","name","path","z","fs","walk","parseYaml","name","deps","isIP","secs","name","connect","name","isIP","own","path","name","fs","path","fs","path","compareVersions","runtimeDir","pkg","fs","os","path","createHash","path","os","sha256","createHash","fs","compareVersions","want","data","runtimeDir","fs","os","deps","path","fs","name","os","path","fs","path","path","path","fs","os","path","fs","stateDir","deps","path","r","os","name","fs","path","own","fs","spawn","fs","path","path","fs","path","lineStart","HINT","z","path","streams","notStarted","stream","name","section","z","descendants","name","name","name","path","fs","path","open","READ_CAP","HEX","HEX","READ_CAP","path","READ_CAP","HEX","wallMs","detect","own","deps","down","cut","name","deps","bad","bad","deps","seen","name","path","fs","crypto","fs","path","crypto","stateDir","path","fs","fs","deps","deps","lease","created","bad","notStarted","deps","path","fs","name","spawn","spawn","spawn","deps","l","fs","path","fs","path","hits","add","deps","file","project","own","k","e","fs","createHash","path","STREAMS","path","latest","chars","path","LOCK_WAIT_MS","fs","createHash","name","fs","path","parseYaml","fs","path","readJson","pkg","deps","fs","path","name","own","section","pkg","readJson","t","parseYaml","fs","name","own","kr","last","i","j","fs","STREAMS","fileURLToPath","z","z","z","deps","z","d","fleet","z","deps","z","r","z","deps","z","deps","fileURLToPath","name","MARK","e","cache","PM2_STAMP","pad","spec","p","keys","r","deps","fs","os","path","name","path","os","fs","WAKE_GAP_MS","deps","streams","bad","add","path","opts","r","d","connect","signals","deps","fs"]}
|