metheus-governance-mcp-cli 0.2.289 → 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 (3) hide show
  1. package/README.md +2 -4
  2. package/cli.mjs +179 -119
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -379,7 +379,7 @@ Behavior:
379
379
  - `bot room-audit` now suggests executable runner routes for the managed server+local intersection. Room visibility is still reported, but a bot no longer has to appear in the admin list before route automation can prepare it.
380
380
  - `bot room-audit` defaults to `monitor` only unless you pass `--role` or `--roles`.
381
381
  - `bot room-audit --apply true` writes missing suggested routes into `~/.metheus/bot-runner.json` and disables overlapping enabled routes in the same project/provider/destination/bot scope that are outside the selected role set.
382
- - `runner project up` is the one-command direct CLI path for Telegram project operations: it runs the same room audit, applies the selected role routes, and starts detached polling by default unless you explicitly pass `--start false`.
382
+ - `runner project up` is the direct CLI preparation path for Telegram project operations: it runs the same room audit and applies the selected role routes. Use `runner start-detached` for persistent polling, or let the TUI call `runner.project_up` to bootstrap detached polling in one step.
383
383
  - `runner project up` can be narrowed with `--bot-name`, `--bot-id`, `--role`, or `--roles <csv>` when you do not want every suggested role route for that room.
384
384
  - `bot remove` without flags starts a guided numbered flow: provider -> bot entry -> confirm removal.
385
385
  - Telegram stores one bot file per entry under `~/.metheus/telegram-bots/<ServerBotName>.env` with generic fields:
@@ -421,7 +421,6 @@ metheus-governance-mcp-cli bot remove --provider telegram --bot-name <server_bot
421
421
  metheus-governance-mcp-cli bot verify --provider telegram --bot-name <server_bot_name> --json true
422
422
  metheus-governance-mcp-cli bot room-audit --provider telegram --project-id <project_uuid> --destination-label <room_label> --json true
423
423
  metheus-governance-mcp-cli bot room-audit --provider telegram --project-id <project_uuid> --destination-label <room_label> --apply true --json true
424
- metheus-governance-mcp-cli runner project up --project-id <project_uuid> --provider telegram --destination-label <room_label>
425
424
  metheus-governance-mcp-cli runner project up --project-id <project_uuid> --provider telegram --destination-label <room_label> --start false
426
425
  metheus-governance-mcp-cli runner start-detached --project-id <project_uuid> --provider telegram --destination-label <room_label>
427
426
  metheus-governance-mcp-cli runner project up --project-id <project_uuid> --provider telegram --destination-label <room_label> --bot-name <server_bot_name> --roles monitor,review --start false
@@ -556,7 +555,7 @@ metheus-governance-mcp-cli runner start --route-name telegram-monitor --concurre
556
555
  Route management:
557
556
  - `runner route add` creates one executable route by selecting the project, provider, role, server bot, and project chat destination in order.
558
557
  - `runner route add` now auto-uses the suggested route name, `5000` ms poll interval, and `enabled=true` unless you pass explicit flags or edit the route later.
559
- - `runner project up` is the shortest practical route bootstrap path for Telegram: it audits one project destination, writes any missing suggested routes, and starts detached polling by default unless you explicitly pass `--start false`.
558
+ - `runner project up` is the shortest practical direct CLI preparation path for Telegram: it audits one project destination and writes any missing suggested routes. Start persistent polling separately with `runner start-detached`, or use the TUI/local tool path that bootstraps detached polling for you.
560
559
  - if room visibility probe fails but one or more enabled routes already exist for that project destination, `runner project up` now treats the probe failure as a warning and can still start those existing routes.
561
560
  - `runner project up --dry-run-delivery true` lets the started runner validate route execution without sending a real provider message.
562
561
  - In public Telegram bot conversations, the stored route role is treated as a hint only. Live room context, the current human request, and recent bot replies take priority over the stored route role hint when the local AI client decides how to answer.
@@ -569,7 +568,6 @@ Route management:
569
568
  Recommended operational path:
570
569
 
571
570
  ```bash
572
- metheus-governance-mcp-cli runner project up --project-id <project_uuid> --provider telegram --destination-label <room_label>
573
571
  metheus-governance-mcp-cli runner project up --project-id <project_uuid> --provider telegram --destination-label <room_label> --start false
574
572
  metheus-governance-mcp-cli runner start-detached --project-id <project_uuid> --provider telegram --destination-label <room_label>
575
573
  metheus-governance-mcp-cli runner project up --project-id <project_uuid> --provider telegram --destination-label <room_label> --bot-name <server_bot_name> --roles monitor,review --start false
package/cli.mjs CHANGED
@@ -12306,7 +12306,7 @@ function resolveRunnerProjectUpExecutionPolicy(flags = {}) {
12306
12306
  ? boolFromRaw(startDetachedRaw, true)
12307
12307
  : (explicitDetachedAliasRequested
12308
12308
  ? boolFromRaw(flags.detached, false)
12309
- : !explicitStartRequested);
12309
+ : false);
12310
12310
  const shouldStartRunner = startRequested || startDetachedRequested;
12311
12311
  return {
12312
12312
  applyRequested,
@@ -12323,6 +12323,61 @@ function buildRunnerStartDetachedCommand(flags = {}) {
12323
12323
  })].join(" ");
12324
12324
  }
12325
12325
 
12326
+ function sleepSyncMilliseconds(durationMs) {
12327
+ const numericDurationMs = Math.max(0, intFromRaw(durationMs, 0) || 0);
12328
+ if (numericDurationMs <= 0) return;
12329
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, numericDurationMs);
12330
+ }
12331
+
12332
+ function buildDetachedRunnerBootstrapLogPaths(logFilePath = "") {
12333
+ const normalizedLogFilePath = String(logFilePath || "").trim();
12334
+ if (!normalizedLogFilePath) {
12335
+ return { stdoutPath: "", stderrPath: "" };
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 = {}) {
12346
+ const normalizedLogFilePath = String(logFilePath || "").trim();
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);
12371
+ }
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");
12379
+ }
12380
+
12326
12381
  function buildRunnerProjectUpNextSteps({
12327
12382
  applyRequested,
12328
12383
  shouldStartRunner,
@@ -12354,7 +12409,7 @@ async function buildRunnerProjectUpResult(flags = {}) {
12354
12409
  const ui = createPrompter();
12355
12410
  try {
12356
12411
  if (shouldRenderPromptChrome(flags)) {
12357
- ui.setFlow("RUNNER PROJECT UP", "Audit one project destination, create missing runner routes, and start detached polling by default unless --start false is passed");
12412
+ ui.setFlow("RUNNER PROJECT UP", "Audit one project destination, create missing runner routes, and optionally start polling when explicitly requested");
12358
12413
  }
12359
12414
  const provider = String(flags.provider || "").trim()
12360
12415
  ? normalizeBotProvider(flags.provider)
@@ -12452,7 +12507,7 @@ async function buildRunnerProjectUpResult(flags = {}) {
12452
12507
  route_apply_changed: Boolean(applyResult.changed),
12453
12508
  route_config_file: String(applyResult.filePath || auditPayload.routeSuggestionConfigFilePath || "-").trim() || "-",
12454
12509
  enabled_routes_for_selection: matchingRoutes.map((route) => normalizeRunnerRoute(route).name).filter(Boolean),
12455
- start_requested: shouldStartRunner,
12510
+ start_requested: startRequested,
12456
12511
  start_detached_requested: startDetachedRequested,
12457
12512
  next_steps: [],
12458
12513
  applied_routes: ensureArray(applyResult.appliedRoutes).map((item) => safeObject(item)),
@@ -12782,16 +12837,16 @@ async function waitForRunnerPIDFile(pidFilePath, timeoutMs = 8000) {
12782
12837
  throw new Error(`detached runner launch did not publish a child process id: ${pidFilePath}`);
12783
12838
  }
12784
12839
 
12785
- function buildRunnerDetachedLaunchRecord(childPID, routes, flags, sourceCommand, logFilePath = "") {
12786
- const normalizedRoutes = ensureArray(routes).map((route) => normalizeRunnerRoute(route));
12787
- const cliPath = fileURLToPath(import.meta.url);
12788
- return normalizeRunnerProcessLaunchEntry({
12789
- launch_id: `${Date.now()}-${childPID}`,
12790
- pid: childPID,
12791
- started_at: new Date().toISOString(),
12792
- command: [process.execPath, cliPath, "--no-update", "runner", "start", ...serializeCLIFlags(flags, { omit: ["json", "start", "start-detached", "detached"] })].join(" "),
12793
- cli_path: cliPath,
12794
- 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),
12795
12850
  route_set_signature: runnerDetachedRouteSetSignature(normalizedRoutes),
12796
12851
  route_keys: normalizedRoutes.map((route) => runnerRouteKey(route)),
12797
12852
  route_names: normalizedRoutes.map((route) => route.name || runnerRouteKey(route)),
@@ -12813,47 +12868,45 @@ function findExistingDetachedRunnerLaunch(registry, routes) {
12813
12868
  }) || null;
12814
12869
  }
12815
12870
 
12816
- async function launchDetachedRunnerProcess(flags, routes, sourceCommand) {
12817
- const cliPath = fileURLToPath(import.meta.url);
12818
- const detachedLogFilePath = resolveRunnerLogFilePath(flags["log-file"], routes, sourceCommand);
12819
- const startFlags = {
12820
- ...safeObject(flags),
12821
- ...(detachedLogFilePath ? { "log-file": detachedLogFilePath } : {}),
12822
- };
12823
- const startArgs = [cliPath, "--no-update", "runner", "start", ...serializeCLIFlags(startFlags, {
12824
- omit: ["json", "start", "start-detached", "detached"],
12825
- })];
12826
- if (process.platform === "win32") {
12827
- const script = [
12828
- `$wd = ${powershellSingleQuote(path.dirname(cliPath))}`,
12829
- `$node = ${powershellSingleQuote(process.execPath)}`,
12830
- `$args = @(${startArgs.map((item) => powershellSingleQuote(item)).join(", ")})`,
12831
- "$p = Start-Process -FilePath $node -WorkingDirectory $wd -ArgumentList $args -WindowStyle Normal -PassThru",
12832
- "Write-Output $p.Id",
12833
- ].join("; ");
12834
- const launched = spawnSync("powershell.exe", [
12835
- "-NoLogo",
12836
- "-NoProfile",
12837
- "-ExecutionPolicy",
12838
- "Bypass",
12839
- "-Command",
12840
- script,
12841
- ], {
12842
- encoding: "utf8",
12843
- windowsHide: true,
12844
- });
12845
- if (launched.error) {
12846
- throw launched.error;
12847
- }
12848
- if (launched.status !== 0) {
12849
- throw new Error(String(launched.stderr || launched.stdout || "failed to launch detached runner").trim());
12850
- }
12851
- const childPID = intFromRawAllowZero(String(launched.stdout || "").trim().split(/\r?\n/).pop(), 0);
12852
- if (childPID <= 0) {
12853
- throw new Error("detached runner launch did not return a child process id");
12854
- }
12855
- return buildRunnerDetachedLaunchRecord(childPID, routes, startFlags, sourceCommand, detachedLogFilePath);
12856
- }
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
+ }
12905
+ }
12906
+ const childPID = intFromRawAllowZero(child?.pid, 0);
12907
+ ensureDetachedRunnerBootstrapped(childPID, detachedLogFilePath, bootstrapLogPaths);
12908
+ return buildRunnerDetachedLaunchRecord(childPID, routes, startFlags, sourceCommand, detachedLogFilePath);
12909
+ }
12857
12910
  const launchTempDir = fs.mkdtempSync(path.join(os.tmpdir(), "metheus-runner-launch-"));
12858
12911
  const scriptPath = path.join(launchTempDir, "start-runner.sh");
12859
12912
  const pidFilePath = path.join(launchTempDir, "runner.pid");
@@ -12877,13 +12930,14 @@ async function launchDetachedRunnerProcess(flags, routes, sourceCommand) {
12877
12930
  });
12878
12931
  if (launched.error) {
12879
12932
  throw launched.error;
12880
- }
12881
- if (launched.status !== 0) {
12882
- throw new Error(String(launched.stderr || launched.stdout || "failed to launch detached runner in Terminal.app").trim());
12883
- }
12884
- const childPID = await waitForRunnerPIDFile(pidFilePath);
12885
- return buildRunnerDetachedLaunchRecord(childPID, routes, startFlags, sourceCommand, detachedLogFilePath);
12886
- }
12933
+ }
12934
+ if (launched.status !== 0) {
12935
+ throw new Error(String(launched.stderr || launched.stdout || "failed to launch detached runner in Terminal.app").trim());
12936
+ }
12937
+ const childPID = await waitForRunnerPIDFile(pidFilePath);
12938
+ ensureDetachedRunnerBootstrapped(childPID, detachedLogFilePath, bootstrapLogPaths);
12939
+ return buildRunnerDetachedLaunchRecord(childPID, routes, startFlags, sourceCommand, detachedLogFilePath);
12940
+ }
12887
12941
  const terminalLauncher = resolveLinuxDetachedTerminalLauncher(scriptPath);
12888
12942
  if (!terminalLauncher) {
12889
12943
  throw new Error("no supported Linux terminal emulator was found (tried x-terminal-emulator, gnome-terminal, konsole, mate-terminal, tilix, alacritty, xterm). Install one of those terminals so runner.start_detached can open an independent window");
@@ -12894,12 +12948,13 @@ async function launchDetachedRunnerProcess(flags, routes, sourceCommand) {
12894
12948
  stdio: "ignore",
12895
12949
  });
12896
12950
  child.unref();
12897
- if (!child.pid) {
12898
- throw new Error("detached terminal launcher did not return a process id");
12899
- }
12900
- const runnerPID = await waitForRunnerPIDFile(pidFilePath);
12901
- return buildRunnerDetachedLaunchRecord(runnerPID, routes, startFlags, sourceCommand, detachedLogFilePath);
12902
- } finally {
12951
+ if (!child.pid) {
12952
+ throw new Error("detached terminal launcher did not return a process id");
12953
+ }
12954
+ const runnerPID = await waitForRunnerPIDFile(pidFilePath);
12955
+ ensureDetachedRunnerBootstrapped(runnerPID, detachedLogFilePath, bootstrapLogPaths);
12956
+ return buildRunnerDetachedLaunchRecord(runnerPID, routes, startFlags, sourceCommand, detachedLogFilePath);
12957
+ } finally {
12903
12958
  try {
12904
12959
  fs.rmSync(launchTempDir, { recursive: true, force: true });
12905
12960
  } catch {}
@@ -19230,25 +19285,28 @@ TELEGRAM_BOT_REVIEW_TOKEN=review-token
19230
19285
  }
19231
19286
  }
19232
19287
 
19233
- try {
19234
- const detachedArgs = serializeCLIFlags({
19235
- "project-id": selftestProjectID,
19236
- provider: "telegram",
19237
- "destination-id": "dest-1",
19238
- "start-detached": "true",
19239
- detached: "true",
19240
- start: "true",
19241
- }, {
19242
- 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"],
19243
19299
  });
19244
- push(
19245
- "detached_runner_cli_args_strip_control_flags",
19246
- detachedArgs.includes("--project-id")
19247
- && detachedArgs.includes(selftestProjectID)
19248
- && !detachedArgs.includes("--start")
19249
- && !detachedArgs.includes("--start-detached")
19250
- && !detachedArgs.includes("--detached"),
19251
- 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(" "),
19252
19310
  );
19253
19311
  } catch (err) {
19254
19312
  push("detached_runner_cli_args_strip_control_flags", false, String(err?.message || err));
@@ -19272,43 +19330,45 @@ TELEGRAM_BOT_REVIEW_TOKEN=review-token
19272
19330
  push("runner_default_log_file_path_uses_runner_logs_directory", false, String(err?.message || err));
19273
19331
  }
19274
19332
 
19275
- try {
19276
- const detachedLaunch = buildRunnerDetachedLaunchRecord(
19277
- 4321,
19278
- [{ name: "telegram-monitor-selftest", projectID: selftestProjectID, provider: "telegram", destinationLabel: "Selftest Room" }],
19279
- {},
19280
- "runner start-detached",
19281
- "C:\\logs\\runner-selftest.jsonl",
19282
- );
19283
- push(
19284
- "detached_runner_launch_record_persists_log_file",
19285
- String(detachedLaunch.log_file || "").trim() === "C:\\logs\\runner-selftest.jsonl",
19286
- `log_file=${String(detachedLaunch.log_file || "").trim() || "(none)"}`,
19287
- );
19288
- } catch (err) {
19289
- push("detached_runner_launch_record_persists_log_file", false, String(err?.message || err));
19290
- }
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
+ }
19291
19351
 
19292
19352
  let detachedRunnerPosixTempDir = "";
19293
19353
  try {
19294
19354
  detachedRunnerPosixTempDir = fs.mkdtempSync(path.join(os.tmpdir(), "metheus-detached-script-selftest-"));
19295
19355
  const scriptPath = path.join(detachedRunnerPosixTempDir, "start-runner.sh");
19296
19356
  const pidFilePath = path.join(detachedRunnerPosixTempDir, "runner.pid");
19297
- buildRunnerDetachedPosixLaunchScript({
19298
- scriptPath,
19299
- pidFilePath,
19300
- workingDirectory: detachedRunnerPosixTempDir,
19301
- nodePath: "/usr/local/bin/node",
19302
- startArgs: ["/tmp/cli.mjs", "--no-update", "runner", "start", "--project-id", selftestProjectID],
19303
- });
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
+ });
19304
19364
  const scriptText = fs.readFileSync(scriptPath, "utf8");
19305
- push(
19306
- "detached_runner_posix_launch_script_serializes_runner_command",
19307
- scriptText.includes(`echo $$ > ${posixSingleQuote(pidFilePath)}`)
19308
- && scriptText.includes(`cd ${posixSingleQuote(detachedRunnerPosixTempDir)} || exit 1`)
19309
- && scriptText.includes(`exec ${posixSingleQuote("/usr/local/bin/node")} ${posixSingleQuote("/tmp/cli.mjs")} ${posixSingleQuote("--no-update")} ${posixSingleQuote("runner")} ${posixSingleQuote("start")}`),
19310
- scriptText.replace(/\r?\n/g, " | "),
19311
- );
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
+ );
19312
19372
  } catch (err) {
19313
19373
  push("detached_runner_posix_launch_script_serializes_runner_command", false, String(err?.message || err));
19314
19374
  } finally {
@@ -19334,15 +19394,15 @@ TELEGRAM_BOT_REVIEW_TOKEN=review-token
19334
19394
  try {
19335
19395
  const projectUpPolicy = resolveRunnerProjectUpExecutionPolicy({});
19336
19396
  push(
19337
- "runner_project_up_default_policy_prefers_detached_start",
19397
+ "runner_project_up_default_policy_keeps_prepare_only_for_direct_cli",
19338
19398
  projectUpPolicy.applyRequested === true
19339
19399
  && projectUpPolicy.startRequested === false
19340
- && projectUpPolicy.startDetachedRequested === true
19341
- && projectUpPolicy.shouldStartRunner === true,
19400
+ && projectUpPolicy.startDetachedRequested === false
19401
+ && projectUpPolicy.shouldStartRunner === false,
19342
19402
  `apply=${projectUpPolicy.applyRequested} start=${projectUpPolicy.startRequested} detached=${projectUpPolicy.startDetachedRequested} shouldStart=${projectUpPolicy.shouldStartRunner}`,
19343
19403
  );
19344
19404
  } catch (err) {
19345
- push("runner_project_up_default_policy_prefers_detached_start", false, String(err?.message || err));
19405
+ push("runner_project_up_default_policy_keeps_prepare_only_for_direct_cli", false, String(err?.message || err));
19346
19406
  }
19347
19407
 
19348
19408
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "metheus-governance-mcp-cli",
3
- "version": "0.2.289",
3
+ "version": "0.2.291",
4
4
  "description": "Metheus Governance MCP CLI (setup + stdio proxy)",
5
5
  "type": "module",
6
6
  "files": [