metheus-governance-mcp-cli 0.2.290 → 0.2.291

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.
Files changed (2) hide show
  1. package/cli.mjs +145 -106
  2. package/package.json +1 -1
package/cli.mjs CHANGED
@@ -12329,16 +12329,53 @@ function sleepSyncMilliseconds(durationMs) {
12329
12329
  Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, numericDurationMs);
12330
12330
  }
12331
12331
 
12332
- function ensureDetachedRunnerBootstrapped(childPID, logFilePath = "") {
12333
- sleepSyncMilliseconds(1200);
12334
- if (isProcessAlive(childPID)) {
12335
- return;
12332
+ function buildDetachedRunnerBootstrapLogPaths(logFilePath = "") {
12333
+ const normalizedLogFilePath = String(logFilePath || "").trim();
12334
+ if (!normalizedLogFilePath) {
12335
+ return { stdoutPath: "", stderrPath: "" };
12336
12336
  }
12337
+ const parsed = path.parse(normalizedLogFilePath);
12338
+ const baseName = parsed.name || "runner-start";
12339
+ return {
12340
+ stdoutPath: path.join(parsed.dir, `${baseName}.bootstrap.out.log`),
12341
+ stderrPath: path.join(parsed.dir, `${baseName}.bootstrap.err.log`),
12342
+ };
12343
+ }
12344
+
12345
+ function ensureDetachedRunnerBootstrapped(childPID, logFilePath = "", bootstrapLogPaths = {}) {
12337
12346
  const normalizedLogFilePath = String(logFilePath || "").trim();
12338
- if (normalizedLogFilePath && fs.existsSync(normalizedLogFilePath)) {
12339
- throw new Error(`detached runner exited during bootstrap; inspect ${normalizedLogFilePath}`);
12347
+ const normalizedBootstrapStdoutPath = String(safeObject(bootstrapLogPaths).stdoutPath || "").trim();
12348
+ const normalizedBootstrapStderrPath = String(safeObject(bootstrapLogPaths).stderrPath || "").trim();
12349
+ const deadlineMs = Date.now() + 5000;
12350
+ while (Date.now() < deadlineMs) {
12351
+ if (!isProcessAlive(childPID)) {
12352
+ if (normalizedBootstrapStderrPath && fs.existsSync(normalizedBootstrapStderrPath)) {
12353
+ throw new Error(`detached runner exited during bootstrap; inspect ${normalizedBootstrapStderrPath}`);
12354
+ }
12355
+ if (normalizedBootstrapStdoutPath && fs.existsSync(normalizedBootstrapStdoutPath)) {
12356
+ throw new Error(`detached runner exited during bootstrap; inspect ${normalizedBootstrapStdoutPath}`);
12357
+ }
12358
+ if (normalizedLogFilePath && fs.existsSync(normalizedLogFilePath)) {
12359
+ throw new Error(`detached runner exited during bootstrap; inspect ${normalizedLogFilePath}`);
12360
+ }
12361
+ throw new Error("detached runner exited during bootstrap before the polling loop became stable");
12362
+ }
12363
+ if (normalizedLogFilePath && fs.existsSync(normalizedLogFilePath)) {
12364
+ try {
12365
+ if (fs.statSync(normalizedLogFilePath).size > 0) {
12366
+ return;
12367
+ }
12368
+ } catch {}
12369
+ }
12370
+ sleepSyncMilliseconds(250);
12340
12371
  }
12341
- throw new Error("detached runner exited during bootstrap before the polling loop became stable");
12372
+ if (normalizedBootstrapStderrPath && fs.existsSync(normalizedBootstrapStderrPath)) {
12373
+ throw new Error(`detached runner stayed alive but did not create the runner log; inspect ${normalizedBootstrapStderrPath}`);
12374
+ }
12375
+ if (normalizedBootstrapStdoutPath && fs.existsSync(normalizedBootstrapStdoutPath)) {
12376
+ throw new Error(`detached runner stayed alive but did not create the runner log; inspect ${normalizedBootstrapStdoutPath}`);
12377
+ }
12378
+ throw new Error("detached runner stayed alive but did not create the runner log during bootstrap");
12342
12379
  }
12343
12380
 
12344
12381
  function buildRunnerProjectUpNextSteps({
@@ -12800,16 +12837,16 @@ async function waitForRunnerPIDFile(pidFilePath, timeoutMs = 8000) {
12800
12837
  throw new Error(`detached runner launch did not publish a child process id: ${pidFilePath}`);
12801
12838
  }
12802
12839
 
12803
- function buildRunnerDetachedLaunchRecord(childPID, routes, flags, sourceCommand, logFilePath = "") {
12804
- const normalizedRoutes = ensureArray(routes).map((route) => normalizeRunnerRoute(route));
12805
- const cliPath = fileURLToPath(import.meta.url);
12806
- return normalizeRunnerProcessLaunchEntry({
12807
- launch_id: `${Date.now()}-${childPID}`,
12808
- pid: childPID,
12809
- started_at: new Date().toISOString(),
12810
- command: [process.execPath, cliPath, "--no-update", "runner", "start", ...serializeCLIFlags(flags, { omit: ["json", "start", "start-detached", "detached"] })].join(" "),
12811
- cli_path: cliPath,
12812
- working_directory: path.dirname(cliPath),
12840
+ function buildRunnerDetachedLaunchRecord(childPID, routes, flags, sourceCommand, logFilePath = "") {
12841
+ const normalizedRoutes = ensureArray(routes).map((route) => normalizeRunnerRoute(route));
12842
+ const cliPath = fileURLToPath(import.meta.url);
12843
+ return normalizeRunnerProcessLaunchEntry({
12844
+ launch_id: `${Date.now()}-${childPID}`,
12845
+ pid: childPID,
12846
+ started_at: new Date().toISOString(),
12847
+ command: [process.execPath, cliPath, "runner", "start", "--no-update", ...serializeCLIFlags(flags, { omit: ["json", "start", "start-detached", "detached"] })].join(" "),
12848
+ cli_path: cliPath,
12849
+ working_directory: path.dirname(cliPath),
12813
12850
  route_set_signature: runnerDetachedRouteSetSignature(normalizedRoutes),
12814
12851
  route_keys: normalizedRoutes.map((route) => runnerRouteKey(route)),
12815
12852
  route_names: normalizedRoutes.map((route) => route.name || runnerRouteKey(route)),
@@ -12831,46 +12868,43 @@ function findExistingDetachedRunnerLaunch(registry, routes) {
12831
12868
  }) || null;
12832
12869
  }
12833
12870
 
12834
- async function launchDetachedRunnerProcess(flags, routes, sourceCommand) {
12835
- const cliPath = fileURLToPath(import.meta.url);
12836
- const detachedLogFilePath = resolveRunnerLogFilePath(flags["log-file"], routes, sourceCommand);
12837
- const startFlags = {
12838
- ...safeObject(flags),
12839
- ...(detachedLogFilePath ? { "log-file": detachedLogFilePath } : {}),
12840
- };
12841
- const startArgs = [cliPath, "--no-update", "runner", "start", ...serializeCLIFlags(startFlags, {
12842
- omit: ["json", "start", "start-detached", "detached"],
12843
- })];
12844
- if (process.platform === "win32") {
12845
- const script = [
12846
- `$wd = ${powershellSingleQuote(path.dirname(cliPath))}`,
12847
- `$node = ${powershellSingleQuote(process.execPath)}`,
12848
- `$args = @(${startArgs.map((item) => powershellSingleQuote(item)).join(", ")})`,
12849
- "$p = Start-Process -FilePath $node -WorkingDirectory $wd -ArgumentList $args -WindowStyle Normal -PassThru",
12850
- "Write-Output $p.Id",
12851
- ].join("; ");
12852
- const launched = spawnSync("powershell.exe", [
12853
- "-NoLogo",
12854
- "-NoProfile",
12855
- "-ExecutionPolicy",
12856
- "Bypass",
12857
- "-Command",
12858
- script,
12859
- ], {
12860
- encoding: "utf8",
12861
- windowsHide: true,
12862
- });
12863
- if (launched.error) {
12864
- throw launched.error;
12865
- }
12866
- if (launched.status !== 0) {
12867
- throw new Error(String(launched.stderr || launched.stdout || "failed to launch detached runner").trim());
12868
- }
12869
- const childPID = intFromRawAllowZero(String(launched.stdout || "").trim().split(/\r?\n/).pop(), 0);
12870
- if (childPID <= 0) {
12871
- throw new Error("detached runner launch did not return a child process id");
12871
+ async function launchDetachedRunnerProcess(flags, routes, sourceCommand) {
12872
+ const cliPath = fileURLToPath(import.meta.url);
12873
+ const detachedLogFilePath = resolveRunnerLogFilePath(flags["log-file"], routes, sourceCommand);
12874
+ const bootstrapLogPaths = buildDetachedRunnerBootstrapLogPaths(detachedLogFilePath);
12875
+ const startFlags = {
12876
+ ...safeObject(flags),
12877
+ tui: boolFromRaw(flags.tui, false),
12878
+ ...(detachedLogFilePath ? { "log-file": detachedLogFilePath } : {}),
12879
+ };
12880
+ const startArgs = [cliPath, "runner", "start", "--no-update", ...serializeCLIFlags(startFlags, {
12881
+ omit: ["json", "start", "start-detached", "detached"],
12882
+ })];
12883
+ if (process.platform === "win32") {
12884
+ const stdoutFd = bootstrapLogPaths.stdoutPath ? fs.openSync(bootstrapLogPaths.stdoutPath, "a") : "ignore";
12885
+ const stderrFd = bootstrapLogPaths.stderrPath ? fs.openSync(bootstrapLogPaths.stderrPath, "a") : "ignore";
12886
+ let child = null;
12887
+ try {
12888
+ child = spawn(process.execPath, startArgs, {
12889
+ cwd: path.dirname(cliPath),
12890
+ detached: true,
12891
+ stdio: ["ignore", stdoutFd, stderrFd],
12892
+ windowsHide: true,
12893
+ });
12894
+ if (!child.pid) {
12895
+ throw new Error("detached runner launch did not return a child process id");
12896
+ }
12897
+ child.unref();
12898
+ } finally {
12899
+ if (typeof stdoutFd === "number") {
12900
+ try { fs.closeSync(stdoutFd); } catch {}
12901
+ }
12902
+ if (typeof stderrFd === "number") {
12903
+ try { fs.closeSync(stderrFd); } catch {}
12904
+ }
12872
12905
  }
12873
- ensureDetachedRunnerBootstrapped(childPID, detachedLogFilePath);
12906
+ const childPID = intFromRawAllowZero(child?.pid, 0);
12907
+ ensureDetachedRunnerBootstrapped(childPID, detachedLogFilePath, bootstrapLogPaths);
12874
12908
  return buildRunnerDetachedLaunchRecord(childPID, routes, startFlags, sourceCommand, detachedLogFilePath);
12875
12909
  }
12876
12910
  const launchTempDir = fs.mkdtempSync(path.join(os.tmpdir(), "metheus-runner-launch-"));
@@ -12901,7 +12935,7 @@ async function launchDetachedRunnerProcess(flags, routes, sourceCommand) {
12901
12935
  throw new Error(String(launched.stderr || launched.stdout || "failed to launch detached runner in Terminal.app").trim());
12902
12936
  }
12903
12937
  const childPID = await waitForRunnerPIDFile(pidFilePath);
12904
- ensureDetachedRunnerBootstrapped(childPID, detachedLogFilePath);
12938
+ ensureDetachedRunnerBootstrapped(childPID, detachedLogFilePath, bootstrapLogPaths);
12905
12939
  return buildRunnerDetachedLaunchRecord(childPID, routes, startFlags, sourceCommand, detachedLogFilePath);
12906
12940
  }
12907
12941
  const terminalLauncher = resolveLinuxDetachedTerminalLauncher(scriptPath);
@@ -12918,7 +12952,7 @@ async function launchDetachedRunnerProcess(flags, routes, sourceCommand) {
12918
12952
  throw new Error("detached terminal launcher did not return a process id");
12919
12953
  }
12920
12954
  const runnerPID = await waitForRunnerPIDFile(pidFilePath);
12921
- ensureDetachedRunnerBootstrapped(runnerPID, detachedLogFilePath);
12955
+ ensureDetachedRunnerBootstrapped(runnerPID, detachedLogFilePath, bootstrapLogPaths);
12922
12956
  return buildRunnerDetachedLaunchRecord(runnerPID, routes, startFlags, sourceCommand, detachedLogFilePath);
12923
12957
  } finally {
12924
12958
  try {
@@ -19251,25 +19285,28 @@ TELEGRAM_BOT_REVIEW_TOKEN=review-token
19251
19285
  }
19252
19286
  }
19253
19287
 
19254
- try {
19255
- const detachedArgs = serializeCLIFlags({
19256
- "project-id": selftestProjectID,
19257
- provider: "telegram",
19258
- "destination-id": "dest-1",
19259
- "start-detached": "true",
19260
- detached: "true",
19261
- start: "true",
19262
- }, {
19263
- omit: ["start", "start-detached", "detached"],
19288
+ try {
19289
+ const detachedArgs = serializeCLIFlags({
19290
+ "project-id": selftestProjectID,
19291
+ provider: "telegram",
19292
+ "destination-id": "dest-1",
19293
+ tui: "false",
19294
+ "start-detached": "true",
19295
+ detached: "true",
19296
+ start: "true",
19297
+ }, {
19298
+ omit: ["start", "start-detached", "detached"],
19264
19299
  });
19265
- push(
19266
- "detached_runner_cli_args_strip_control_flags",
19267
- detachedArgs.includes("--project-id")
19268
- && detachedArgs.includes(selftestProjectID)
19269
- && !detachedArgs.includes("--start")
19270
- && !detachedArgs.includes("--start-detached")
19271
- && !detachedArgs.includes("--detached"),
19272
- detachedArgs.join(" "),
19300
+ push(
19301
+ "detached_runner_cli_args_strip_control_flags",
19302
+ detachedArgs.includes("--project-id")
19303
+ && detachedArgs.includes(selftestProjectID)
19304
+ && detachedArgs.includes("--tui")
19305
+ && detachedArgs.includes("false")
19306
+ && !detachedArgs.includes("--start")
19307
+ && !detachedArgs.includes("--start-detached")
19308
+ && !detachedArgs.includes("--detached"),
19309
+ detachedArgs.join(" "),
19273
19310
  );
19274
19311
  } catch (err) {
19275
19312
  push("detached_runner_cli_args_strip_control_flags", false, String(err?.message || err));
@@ -19293,43 +19330,45 @@ TELEGRAM_BOT_REVIEW_TOKEN=review-token
19293
19330
  push("runner_default_log_file_path_uses_runner_logs_directory", false, String(err?.message || err));
19294
19331
  }
19295
19332
 
19296
- try {
19297
- const detachedLaunch = buildRunnerDetachedLaunchRecord(
19298
- 4321,
19299
- [{ name: "telegram-monitor-selftest", projectID: selftestProjectID, provider: "telegram", destinationLabel: "Selftest Room" }],
19300
- {},
19301
- "runner start-detached",
19302
- "C:\\logs\\runner-selftest.jsonl",
19303
- );
19304
- push(
19305
- "detached_runner_launch_record_persists_log_file",
19306
- String(detachedLaunch.log_file || "").trim() === "C:\\logs\\runner-selftest.jsonl",
19307
- `log_file=${String(detachedLaunch.log_file || "").trim() || "(none)"}`,
19308
- );
19309
- } catch (err) {
19310
- push("detached_runner_launch_record_persists_log_file", false, String(err?.message || err));
19311
- }
19333
+ try {
19334
+ const detachedLaunch = buildRunnerDetachedLaunchRecord(
19335
+ 4321,
19336
+ [{ name: "telegram-monitor-selftest", projectID: selftestProjectID, provider: "telegram", destinationLabel: "Selftest Room" }],
19337
+ { tui: false },
19338
+ "runner start-detached",
19339
+ "C:\\logs\\runner-selftest.jsonl",
19340
+ );
19341
+ push(
19342
+ "detached_runner_launch_record_persists_log_file",
19343
+ String(detachedLaunch.log_file || "").trim() === "C:\\logs\\runner-selftest.jsonl"
19344
+ && String(detachedLaunch.command || "").includes(" runner start --no-update ")
19345
+ && String(detachedLaunch.command || "").includes("--tui false"),
19346
+ `log_file=${String(detachedLaunch.log_file || "").trim() || "(none)"} command=${String(detachedLaunch.command || "").trim() || "(none)"}`,
19347
+ );
19348
+ } catch (err) {
19349
+ push("detached_runner_launch_record_persists_log_file", false, String(err?.message || err));
19350
+ }
19312
19351
 
19313
19352
  let detachedRunnerPosixTempDir = "";
19314
19353
  try {
19315
19354
  detachedRunnerPosixTempDir = fs.mkdtempSync(path.join(os.tmpdir(), "metheus-detached-script-selftest-"));
19316
19355
  const scriptPath = path.join(detachedRunnerPosixTempDir, "start-runner.sh");
19317
19356
  const pidFilePath = path.join(detachedRunnerPosixTempDir, "runner.pid");
19318
- buildRunnerDetachedPosixLaunchScript({
19319
- scriptPath,
19320
- pidFilePath,
19321
- workingDirectory: detachedRunnerPosixTempDir,
19322
- nodePath: "/usr/local/bin/node",
19323
- startArgs: ["/tmp/cli.mjs", "--no-update", "runner", "start", "--project-id", selftestProjectID],
19324
- });
19357
+ buildRunnerDetachedPosixLaunchScript({
19358
+ scriptPath,
19359
+ pidFilePath,
19360
+ workingDirectory: detachedRunnerPosixTempDir,
19361
+ nodePath: "/usr/local/bin/node",
19362
+ startArgs: ["/tmp/cli.mjs", "runner", "start", "--no-update", "--project-id", selftestProjectID],
19363
+ });
19325
19364
  const scriptText = fs.readFileSync(scriptPath, "utf8");
19326
- push(
19327
- "detached_runner_posix_launch_script_serializes_runner_command",
19328
- scriptText.includes(`echo $$ > ${posixSingleQuote(pidFilePath)}`)
19329
- && scriptText.includes(`cd ${posixSingleQuote(detachedRunnerPosixTempDir)} || exit 1`)
19330
- && scriptText.includes(`exec ${posixSingleQuote("/usr/local/bin/node")} ${posixSingleQuote("/tmp/cli.mjs")} ${posixSingleQuote("--no-update")} ${posixSingleQuote("runner")} ${posixSingleQuote("start")}`),
19331
- scriptText.replace(/\r?\n/g, " | "),
19332
- );
19365
+ push(
19366
+ "detached_runner_posix_launch_script_serializes_runner_command",
19367
+ scriptText.includes(`echo $$ > ${posixSingleQuote(pidFilePath)}`)
19368
+ && scriptText.includes(`cd ${posixSingleQuote(detachedRunnerPosixTempDir)} || exit 1`)
19369
+ && scriptText.includes(`exec ${posixSingleQuote("/usr/local/bin/node")} ${posixSingleQuote("/tmp/cli.mjs")} ${posixSingleQuote("runner")} ${posixSingleQuote("start")} ${posixSingleQuote("--no-update")}`),
19370
+ scriptText.replace(/\r?\n/g, " | "),
19371
+ );
19333
19372
  } catch (err) {
19334
19373
  push("detached_runner_posix_launch_script_serializes_runner_command", false, String(err?.message || err));
19335
19374
  } finally {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "metheus-governance-mcp-cli",
3
- "version": "0.2.290",
3
+ "version": "0.2.291",
4
4
  "description": "Metheus Governance MCP CLI (setup + stdio proxy)",
5
5
  "type": "module",
6
6
  "files": [