metheus-governance-mcp-cli 0.2.103 → 0.2.104

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/README.md CHANGED
@@ -280,7 +280,7 @@ Behavior:
280
280
  - Slack and KakaoTalk currently use a single local token entry per provider in this command flow.
281
281
  - `bot verify` checks the configured local token, cross-checks the server bot binding, prints the effective runtime role profile summary that the runner will use, and shows which local runner routes currently point at this bot entry.
282
282
  - `bot show` prints one local bot entry in detail, including grouped role summaries when one server bot name expands to multiple roles and any linked local runner routes.
283
- - In `bot show` and `bot verify`, `stored_*` fields come from the local env file and `live_server_*` fields come from the current server `me/bots` response.
283
+ - In `bot show` and `bot verify`, `saved_local_file` means the values already stored on disk under `~/.metheus/telegram-bots/*.env`, while `current_server_protocol` means the fresh `/api/v1/me/bots` response from the server right now.
284
284
  - `bot global` edits Telegram-wide local settings such as API base URL, allowed updates, and default bot key.
285
285
  - `bot set-default` updates `TELEGRAM_DEFAULT_BOT_KEY`.
286
286
  - `bot migrate` moves legacy `TELEGRAM_BOT_TOKEN` into a named Telegram bot entry.
@@ -302,6 +302,8 @@ For direct Telegram adds, the CLI derives the local file name from the matched s
302
302
 
303
303
  For direct Telegram edits, prefer `--bot-name` or `--bot-id` because server bot identity is the source of truth. Use `--bot-key` only when you intentionally need the advanced local selector. If one server bot name expands to multiple roles such as `approval / worker / review / monitor`, prefer the guided `bot edit` flow so you can keep the current grouped settings, edit one role only, or walk every role in sequence instead of forcing one entry-level AI override.
304
304
 
305
+ For runner commands, you can still use `--route-name` directly, but normal operator workflows can also use `--bot-name` or `--bot-id` when those identify one enabled route uniquely. Use `runner list` first if you are not sure which route belongs to which server bot.
306
+
305
307
  Current support status:
306
308
 
307
309
  - Telegram: full local bot entry management, token verification, bot-to-AI binding, inbound runner support
package/cli.mjs CHANGED
@@ -242,21 +242,21 @@ function printUsage() {
242
242
  ` ${cmd} setup [--project-id <uuid>] [--ctxpack-key <key>] [--base-url <url>] [--workspace-dir <path|auto>] [--workspace-fallback-dir <path>] [--name <server_name>]`,
243
243
  ` ${cmd} bot setup [--provider <telegram|slack|kakaotalk>] [--base-url <url>] [--timeout-seconds <n>]`,
244
244
  ` ${cmd} bot list [--provider <telegram|slack|kakaotalk>] [--json <true|false>]`,
245
- ` ${cmd} bot show [--provider <telegram|slack|kakaotalk>] [--bot-name <server_name>] [--bot-id <uuid>] [--bot-key <advanced_key>] [--json <true|false>]`,
245
+ ` ${cmd} bot show [--provider <telegram|slack|kakaotalk>] [--bot-name <server_name>] [--bot-id <uuid>] [--json <true|false>]`,
246
246
  ` ${cmd} bot add [--provider <telegram|slack|kakaotalk>] [--base-url <url>] [--timeout-seconds <n>]`,
247
247
  ` ${cmd} bot edit [--provider <telegram|slack|kakaotalk>] [--base-url <url>] [--timeout-seconds <n>]`,
248
248
  ` ${cmd} bot remove [--provider <telegram|slack|kakaotalk>]`,
249
- ` ${cmd} bot set-default --provider telegram [--bot-name <server_name>] [--bot-id <uuid>] [--bot-key <advanced_key>]`,
250
- ` ${cmd} bot migrate --provider telegram [--bot-name <server_name>] [--bot-id <uuid>] [--bot-key <advanced_key>]`,
251
- ` ${cmd} bot verify [--provider <telegram|slack|kakaotalk>] [--bot-name <server_name>] [--bot-id <uuid>] [--bot-key <advanced_key>] [--timeout-seconds <n>] [--json <true|false>]`,
249
+ ` ${cmd} bot set-default --provider telegram [--bot-name <server_name>] [--bot-id <uuid>]`,
250
+ ` ${cmd} bot migrate --provider telegram [--bot-name <server_name>] [--bot-id <uuid>]`,
251
+ ` ${cmd} bot verify [--provider <telegram|slack|kakaotalk>] [--bot-name <server_name>] [--bot-id <uuid>] [--timeout-seconds <n>] [--json <true|false>]`,
252
252
  ` ${cmd} bot global --provider telegram [--api-base-url <url>] [--auto-clear-webhook <true|false>] [--allowed-updates <csv>] [--default-bot-key <key>]`,
253
253
  ` ${cmd} doctor [--project-id <uuid>] [--ctxpack-key <key>] [--base-url <url>] [--timeout-seconds <n>] [--strict <true|false>]`,
254
254
  ` ${cmd} proxy [--project-id <uuid>] [--ctxpack-key <key>] [--base-url <url>] [--workspace-dir <path|auto>] [--include-drafts <true|false>] [--auto-pull-on-conflict <true|false>] [--timeout-seconds <n>]`,
255
255
  ` ${cmd} selftest [--json <true|false>]`,
256
256
  ` ${cmd} local-bot-bridge [--client <codex|claude|gemini|sample>] [--cwd <path>] [--model <name>] [--permission-mode <read_only|workspace_write|danger_full_access>] [--reasoning-effort <low|medium|high>]`,
257
257
  ` ${cmd} runner list [--json <true|false>]`,
258
- ` ${cmd} runner once [--route-name <name>] [--project-id <uuid>] [--provider <telegram|slack|kakaotalk>] [--role <monitor|review|worker|approval>] [--role-profile <name>] [--bot-name <name>] [--bot-id <uuid>] [--mentions-only <true|false>] [--reply-to-bot-messages <true|false>] [--direct-messages <true|false>] [--ignore-edited-messages <true|false>] [--dry-run-delivery <true|false>] [--context-comments <n>] [--archive-replies <true|false>]`,
259
- ` ${cmd} runner start [--route-name <name>] [--project-id <uuid>] [--provider <telegram|slack|kakaotalk>] [--role <monitor|review|worker|approval>] [--role-profile <name>] [--bot-name <name>] [--bot-id <uuid>] [--mentions-only <true|false>] [--reply-to-bot-messages <true|false>] [--direct-messages <true|false>] [--ignore-edited-messages <true|false>] [--dry-run-delivery <true|false>] [--poll-interval-ms <n>] [--context-comments <n>] [--archive-replies <true|false>]`,
258
+ ` ${cmd} runner once [--route-name <name> | --bot-name <server_name> | --bot-id <uuid>] [--project-id <uuid>] [--provider <telegram|slack|kakaotalk>] [--role <monitor|review|worker|approval>] [--role-profile <name>] [--mentions-only <true|false>] [--reply-to-bot-messages <true|false>] [--direct-messages <true|false>] [--ignore-edited-messages <true|false>] [--dry-run-delivery <true|false>] [--context-comments <n>] [--archive-replies <true|false>]`,
259
+ ` ${cmd} runner start [--route-name <name> | --bot-name <server_name> | --bot-id <uuid>] [--project-id <uuid>] [--provider <telegram|slack|kakaotalk>] [--role <monitor|review|worker|approval>] [--role-profile <name>] [--mentions-only <true|false>] [--reply-to-bot-messages <true|false>] [--direct-messages <true|false>] [--ignore-edited-messages <true|false>] [--dry-run-delivery <true|false>] [--poll-interval-ms <n>] [--context-comments <n>] [--archive-replies <true|false>]`,
260
260
  ` ${cmd} ctxpack pull [--project-id <uuid>] [--base-url <url>] [--workspace-dir <path|auto>] [--paths <csv>] [--timeout-seconds <n>]`,
261
261
  ` ${cmd} auth status`,
262
262
  ` ${cmd} auth login [--base-url <url>] [--flow <auto|device|callback|manual>] [--keycloak-url <url>] [--realm <name>] [--client-id <id>] [--open-browser <true|false>] [--callback-port <n>] [--timeout-seconds <n>] [--manual <true|false>]`,
@@ -2568,15 +2568,32 @@ async function runRunnerOnce(flags) {
2568
2568
 
2569
2569
  function buildRunnerRouteListRows() {
2570
2570
  const config = loadBotRunnerConfig({ persistIfNeeded: true });
2571
+ const telegramState = readTelegramEnvState();
2572
+ const telegramEntries = ensureArray(telegramState.entries);
2571
2573
  return ensureArray(config.routes).map((rawRoute, index) => {
2572
2574
  const route = normalizeRunnerRoute(rawRoute);
2575
+ const matchedTelegramEntry = route.provider === "telegram"
2576
+ ? telegramEntries.find((entry) => {
2577
+ const current = safeObject(entry);
2578
+ return (
2579
+ (route.botID && current.serverBotID && current.serverBotID === route.botID)
2580
+ || (route.botName && current.serverBotName && current.serverBotName === route.botName)
2581
+ );
2582
+ })
2583
+ : null;
2584
+ const resolvedBotName = firstNonEmptyString([
2585
+ route.botName,
2586
+ matchedTelegramEntry?.serverBotName,
2587
+ matchedTelegramEntry?.key,
2588
+ "-",
2589
+ ]);
2573
2590
  return {
2574
2591
  index: index + 1,
2575
2592
  name: route.name || runnerRouteKey(route),
2576
2593
  enabled: route.enabled !== false,
2577
2594
  provider: route.provider || "-",
2578
2595
  projectID: route.projectID || "-",
2579
- botName: route.botName || "-",
2596
+ botName: resolvedBotName,
2580
2597
  botID: route.botID || "-",
2581
2598
  role: route.role || "-",
2582
2599
  roleProfile: route.roleProfile || "-",
@@ -2605,13 +2622,14 @@ async function runRunnerList(flags) {
2605
2622
  ` - ${row.name}${row.enabled ? "" : " [disabled]"}`,
2606
2623
  ` provider: ${row.provider}`,
2607
2624
  ` project_id: ${row.projectID}`,
2608
- ` bot_name: ${row.botName}`,
2625
+ ` server_bot_name: ${row.botName}`,
2609
2626
  ` bot_id: ${row.botID}`,
2610
2627
  ` role: ${row.role}`,
2611
2628
  ` role_profile: ${row.roleProfile}`,
2612
2629
  ` destination_label: ${row.destinationLabel}`,
2613
2630
  ` poll_interval_ms: ${row.pollIntervalMs}`,
2614
2631
  ` run_once: ${CLI_NAME} runner once --route-name ${row.name}`,
2632
+ row.botName ? ` run_once_by_bot_name: ${CLI_NAME} runner once --bot-name "${row.botName}"` : "",
2615
2633
  ].join("\n") + "\n",
2616
2634
  );
2617
2635
  });
@@ -216,24 +216,25 @@ function printBotUsage(deps) {
216
216
  "",
217
217
  ` ${cliName} bot setup`,
218
218
  ` ${cliName} bot list [--provider <telegram|slack|kakaotalk>] [--json <true|false>]`,
219
- ` ${cliName} bot show [--provider <telegram|slack|kakaotalk>] [--bot-name <server_name>] [--bot-id <uuid>] [--bot-key <advanced_key>] [--json <true|false>]`,
220
- ` ${cliName} bot add [--provider <telegram|slack|kakaotalk>] [--base-url <url>] [--timeout-seconds <n>] [--non-interactive <true|false>] [--server-bot-id <uuid>] [--token <token>] [--default <true|false>] [--verify <true|false>] [--ai-client <name>] [--ai-model <name>] [--ai-permission-mode <mode>] [--ai-reasoning-effort <level>] [--bot-key <advanced_key>] [--username <fallback_name>] [--role-profile <name>]`,
221
- ` ${cliName} bot edit [--provider <telegram|slack|kakaotalk>] [--base-url <url>] [--timeout-seconds <n>] [--non-interactive <true|false>] [--bot-name <server_name>] [--bot-id <uuid>] [--bot-key <advanced_key>] [--username <fallback_name>] [--token <token>] [--role-profile <name>] [--ai-client <name>] [--ai-model <name>] [--ai-permission-mode <mode>] [--ai-reasoning-effort <level>]`,
222
- ` ${cliName} bot remove [--provider <telegram|slack|kakaotalk>] [--non-interactive <true|false>] [--bot-name <server_name>] [--bot-id <uuid>] [--bot-key <advanced_key>]`,
223
- ` ${cliName} bot set-default --provider telegram [--bot-name <server_name>] [--bot-id <uuid>] [--bot-key <advanced_key>] [--non-interactive <true|false>]`,
224
- ` ${cliName} bot migrate --provider telegram [--bot-name <server_name>] [--bot-id <uuid>] [--bot-key <advanced_key>] [--keep-legacy-token <true|false>] [--non-interactive <true|false>]`,
225
- ` ${cliName} bot verify [--provider <telegram|slack|kakaotalk>] [--bot-name <server_name>] [--bot-id <uuid>] [--bot-key <advanced_key>] [--timeout-seconds <n>] [--json <true|false>]`,
219
+ ` ${cliName} bot show [--provider <telegram|slack|kakaotalk>] [--bot-name <server_name>] [--bot-id <uuid>] [--json <true|false>]`,
220
+ ` ${cliName} bot add [--provider <telegram|slack|kakaotalk>] [--base-url <url>] [--timeout-seconds <n>] [--non-interactive <true|false>] [--server-bot-id <uuid>] [--token <token>] [--default <true|false>] [--verify <true|false>] [--ai-client <name>] [--ai-model <name>] [--ai-permission-mode <mode>] [--ai-reasoning-effort <level>] [--username <fallback_name>] [--role-profile <name>]`,
221
+ ` ${cliName} bot edit [--provider <telegram|slack|kakaotalk>] [--base-url <url>] [--timeout-seconds <n>] [--non-interactive <true|false>] [--bot-name <server_name>] [--bot-id <uuid>] [--username <fallback_name>] [--token <token>] [--role-profile <name>] [--ai-client <name>] [--ai-model <name>] [--ai-permission-mode <mode>] [--ai-reasoning-effort <level>]`,
222
+ ` ${cliName} bot remove [--provider <telegram|slack|kakaotalk>] [--non-interactive <true|false>] [--bot-name <server_name>] [--bot-id <uuid>]`,
223
+ ` ${cliName} bot set-default --provider telegram [--bot-name <server_name>] [--bot-id <uuid>] [--non-interactive <true|false>]`,
224
+ ` ${cliName} bot migrate --provider telegram [--bot-name <server_name>] [--bot-id <uuid>] [--keep-legacy-token <true|false>] [--non-interactive <true|false>]`,
225
+ ` ${cliName} bot verify [--provider <telegram|slack|kakaotalk>] [--bot-name <server_name>] [--bot-id <uuid>] [--timeout-seconds <n>] [--json <true|false>]`,
226
226
  ` ${cliName} bot global --provider telegram [--non-interactive <true|false>] [--api-base-url <url>] [--auto-clear-webhook <true|false>] [--allowed-updates <csv>] [--default-bot-key <advanced_key>]`,
227
227
  "",
228
228
  `Behavior:`,
229
229
  ` - bot setup asks for provider first, then shows a numbered action menu.`,
230
230
  ` - bot add without flags uses the shortest practical guided flow: provider -> token -> verify -> optional username fallback -> optional default bot.`,
231
231
  ` - in the normal Telegram path, bot add does not ask for a local bot key or a server role/profile choice.`,
232
- ` - server bot name/UUID is the source of truth; --bot-key is an advanced local selector only.`,
233
- ` - runner commands use route names. Use runner list first, then run runner once/start with --route-name.`,
232
+ ` - server bot name/UUID is the source of truth; --bot-key is an advanced compatibility selector only.`,
233
+ ` - runner commands can auto-select by --bot-name or --bot-id when one enabled route matches. Use runner list first if you are unsure.`,
234
234
  ` - bot edit without flags asks for provider, existing entry, then walks field-by-field in a numbered flow.`,
235
235
  ` - in the normal Telegram edit path, the CLI keeps or re-resolves the server bot binding automatically instead of asking you to pick a server role/profile UUID first.`,
236
236
  ` - bot set-default / bot verify / bot remove also support guided numbered selection when run without flags.`,
237
+ ` - advanced selectors: --bot-key is still supported for compatibility, but prefer --bot-name or --bot-id in normal operator workflows.`,
237
238
  "",
238
239
  ].join("\n"),
239
240
  );
@@ -1307,12 +1308,15 @@ function printBotList(provider, state, deps) {
1307
1308
  }
1308
1309
  process.stdout.write(` default: ${String(state.parsed.TELEGRAM_DEFAULT_BOT_KEY || "").trim() || "-"}\n`);
1309
1310
  entries.forEach((entry) => {
1311
+ const advancedSelectorLine = entry.key
1312
+ ? ` advanced_local_selector: ${entry.key} (compatibility only)`
1313
+ : "";
1310
1314
  process.stdout.write(
1311
1315
  [
1312
1316
  ` - ${telegramEntryDisplayName(entry)}${entry.isDefault ? " [default]" : ""}`,
1313
1317
  ` entry_file: ${resolveTelegramEntryFilePath(entry, deps) || "-"}`,
1314
- ` local_selector: ${entry.key || "-"}${entry.key ? " (advanced)" : ""}`,
1315
1318
  ` server_bot_id: ${entry.serverBotID || "-"}`,
1319
+ ` server_name: ${entry.serverBotName || telegramEntryDisplayName(entry)}`,
1316
1320
  ` server_role_ids: ${formatTelegramServerRoleIDs(entry.serverRoleIDs) || "-"}`,
1317
1321
  ` fallback_username: ${entry.username ? `@${entry.username}` : "-"}`,
1318
1322
  ` token: ${entry.token ? maskSecret(entry.token) : "-"}`,
@@ -1321,6 +1325,7 @@ function printBotList(provider, state, deps) {
1321
1325
  ` model: ${entry.model || "-"}`,
1322
1326
  ` permission_mode: ${entry.permissionMode || "-"}`,
1323
1327
  ` reasoning_effort: ${entry.reasoningEffort || "-"}`,
1328
+ advancedSelectorLine,
1324
1329
  ].join("\n") + "\n",
1325
1330
  );
1326
1331
  });
@@ -1341,42 +1346,43 @@ function printBotShow(provider, state, entry, deps, extras = {}) {
1341
1346
  `global_file: ${state.filePath}`,
1342
1347
  `entry_file: ${resolveTelegramEntryFilePath(selectedEntry, deps) || "-"}`,
1343
1348
  `server_name: ${telegramEntryDisplayName(selectedEntry)}`,
1349
+ `comparison_help: saved_local_file = values stored on disk | current_server_protocol = fresh /api/v1/me/bots response`,
1344
1350
  ];
1345
- appendTextSection(lines, "stored_local_entry", [
1346
- `local_selector: ${selectedEntry.key || "-"}${selectedEntry.key ? " (advanced)" : ""}`,
1347
- `default: ${selectedEntry.isDefault ? "yes" : "no"}`,
1348
- `stored_server_bot_id: ${selectedEntry.serverBotID || "-"}`,
1349
- `stored_server_name: ${selectedEntry.serverBotName || "-"}`,
1350
- `stored_server_roles: ${ensureArray(selectedEntry.serverRoles).join(", ") || "-"}`,
1351
- `stored_server_role_ids: ${formatTelegramServerRoleIDs(selectedEntry.serverRoleIDs) || "-"}`,
1352
- `fallback_username: ${selectedEntry.username ? `@${selectedEntry.username}` : "-"}`,
1351
+ appendTextSection(lines, "saved_local_file", [
1352
+ `default_entry: ${selectedEntry.isDefault ? "yes" : "no"}`,
1353
+ `server_bot_id_in_file: ${selectedEntry.serverBotID || "-"}`,
1354
+ `server_name_in_file: ${selectedEntry.serverBotName || "-"}`,
1355
+ `server_roles_in_file: ${ensureArray(selectedEntry.serverRoles).join(", ") || "-"}`,
1356
+ `server_role_ids_in_file: ${formatTelegramServerRoleIDs(selectedEntry.serverRoleIDs) || "-"}`,
1357
+ `fallback_username_in_file: ${selectedEntry.username ? `@${selectedEntry.username}` : "-"}`,
1353
1358
  `token: ${selectedEntry.token ? maskSecret(selectedEntry.token) : "(not configured)"}`,
1354
1359
  `role_profile: ${selectedEntry.roleProfile || "-"}`,
1355
1360
  `ai_client: ${selectedEntry.client ? displayLocalAIClientName(selectedEntry.client) : "-"}`,
1356
1361
  `ai_model: ${selectedEntry.model || "-"}`,
1357
1362
  `permission_mode: ${selectedEntry.permissionMode || "-"}`,
1358
1363
  `reasoning_effort: ${selectedEntry.reasoningEffort || "-"}`,
1364
+ selectedEntry.key ? `advanced_local_selector: ${selectedEntry.key} (compatibility only)` : "",
1359
1365
  ]);
1360
1366
  if (Object.keys(serverBinding).length) {
1361
1367
  const liveLines = [
1362
1368
  `status: ${serverBinding.ok ? "OK" : "FAIL"}${serverBinding.detail ? ` (${serverBinding.detail})` : ""}`,
1363
1369
  `binding_mode: ${serverBinding.mode || "-"}`,
1364
- `live_server_name: ${serverBinding.name || "-"}`,
1365
- `live_server_bot_id: ${serverBinding.serverBotID || selectedEntry.serverBotID || "-"}`,
1370
+ `server_name_now: ${serverBinding.name || "-"}`,
1371
+ `server_bot_id_now: ${serverBinding.serverBotID || selectedEntry.serverBotID || "-"}`,
1366
1372
  ];
1367
1373
  if (serverBinding.mode === "group") {
1368
- liveLines.push(`live_server_roles: ${ensureArray(serverBinding.roles).join(", ") || "-"}`);
1369
- liveLines.push(`live_server_role_ids: ${formatTelegramServerRoleIDs(serverBinding.serverRoleIDs) || "-"}`);
1374
+ liveLines.push(`server_roles_now: ${ensureArray(serverBinding.roles).join(", ") || "-"}`);
1375
+ liveLines.push(`server_role_ids_now: ${formatTelegramServerRoleIDs(serverBinding.serverRoleIDs) || "-"}`);
1370
1376
  const groupedProfiles = safeObject(serverBinding.effectiveRoleProfiles);
1371
1377
  Object.keys(groupedProfiles).forEach((role) => {
1372
1378
  liveLines.push(`runtime_role_profile[${role}]: ${formatRoleProfileOutputLine(groupedProfiles[role])}`);
1373
1379
  });
1374
1380
  } else if (serverBinding.effectiveRoleProfile) {
1375
- liveLines.push(`live_server_role: ${serverBinding.role || "-"}`);
1376
- liveLines.push(`live_server_role_ids: ${formatTelegramServerRoleIDs(serverBinding.serverRoleIDs) || "-"}`);
1381
+ liveLines.push(`server_role_now: ${serverBinding.role || "-"}`);
1382
+ liveLines.push(`server_role_ids_now: ${formatTelegramServerRoleIDs(serverBinding.serverRoleIDs) || "-"}`);
1377
1383
  liveLines.push(`runtime_role_profile: ${formatRoleProfileOutputLine(serverBinding.effectiveRoleProfile)}`);
1378
1384
  }
1379
- appendTextSection(lines, "live_server_binding", liveLines);
1385
+ appendTextSection(lines, "current_server_protocol", liveLines);
1380
1386
  }
1381
1387
  const routeLines = [`count: ${intFromRaw(routeLinks.total, 0)}`];
1382
1388
  ensureArray(routeLinks.routes).forEach((route) => {
@@ -2254,9 +2260,9 @@ async function buildTelegramEntrySelectionRows(entries, flags, deps) {
2254
2260
  label = serverName;
2255
2261
  }
2256
2262
  const descriptionParts = [
2257
- current.key ? `local_selector:${current.key} (advanced)` : "",
2258
2263
  current.serverBotID ? `stored_server_bot_id:${current.serverBotID}` : "",
2259
2264
  current.client ? `ai_client:${displayLocalAIClientName(current.client)}` : "",
2265
+ current.key ? `advanced_selector:${current.key}` : "",
2260
2266
  ].filter(Boolean);
2261
2267
  return {
2262
2268
  value: current.key,
@@ -2821,28 +2827,29 @@ async function verifyProviderEntry(ui, provider, flags, deps) {
2821
2827
  `global_file: ${envConfig.filePath}`,
2822
2828
  provider === "telegram" ? `entry_file: ${resolveTelegramEntryFilePath(envConfig, deps) || "-"}` : "",
2823
2829
  `detail: ${result.detail || "-"}`,
2830
+ provider === "telegram" ? `comparison_help: saved_local_file = values stored on disk | current_server_protocol = fresh /api/v1/me/bots response` : "",
2824
2831
  ];
2825
2832
  if (provider === "telegram") {
2826
- appendTextSection(lines, "stored_local_entry", [
2827
- `local_selector: ${envConfig.botKey || "-"}${envConfig.botKey ? " (advanced)" : ""}`,
2828
- `stored_server_bot_id: ${envConfig.serverBotID || "-"}`,
2829
- `stored_server_name: ${envConfig.serverBotName || "-"}`,
2830
- `stored_server_roles: ${ensureArray(envConfig.serverRoles).join(", ") || "-"}`,
2831
- `stored_server_role_ids: ${formatTelegramServerRoleIDs(envConfig.serverRoleIDs) || "-"}`,
2833
+ appendTextSection(lines, "saved_local_file", [
2834
+ `server_bot_id_in_file: ${envConfig.serverBotID || "-"}`,
2835
+ `server_name_in_file: ${envConfig.serverBotName || "-"}`,
2836
+ `server_roles_in_file: ${ensureArray(envConfig.serverRoles).join(", ") || "-"}`,
2837
+ `server_role_ids_in_file: ${formatTelegramServerRoleIDs(envConfig.serverRoleIDs) || "-"}`,
2832
2838
  `role_profile: ${envConfig.roleProfile || "-"}`,
2833
2839
  `ai_client: ${envConfig.client ? displayLocalAIClientName(envConfig.client) : "-"}`,
2834
2840
  `ai_model: ${envConfig.model || "-"}`,
2835
2841
  `permission_mode: ${envConfig.permissionMode || "-"}`,
2836
2842
  `reasoning_effort: ${envConfig.reasoningEffort || "-"}`,
2843
+ envConfig.botKey ? `advanced_local_selector: ${envConfig.botKey} (compatibility only)` : "",
2837
2844
  ]);
2838
2845
  }
2839
2846
  if (provider === "telegram" && serverBinding) {
2840
2847
  const liveLines = [
2841
2848
  `status: ${serverBinding.ok ? "OK" : "FAIL"}${serverBinding.detail ? ` (${serverBinding.detail})` : ""}`,
2842
2849
  `binding_mode: ${serverBinding.mode || "-"}`,
2843
- `live_server_name: ${serverBinding.name || "-"}`,
2844
- `live_server_roles: ${ensureArray(serverBinding.roles).join(", ") || "-"}`,
2845
- `live_server_role_ids: ${formatTelegramServerRoleIDs(serverBinding.serverRoleIDs) || "-"}`,
2850
+ `server_name_now: ${serverBinding.name || "-"}`,
2851
+ `server_roles_now: ${ensureArray(serverBinding.roles).join(", ") || "-"}`,
2852
+ `server_role_ids_now: ${formatTelegramServerRoleIDs(serverBinding.serverRoleIDs) || "-"}`,
2846
2853
  ];
2847
2854
  if (serverBinding.mode === "group") {
2848
2855
  const groupedProfiles = safeObject(serverBinding.effectiveRoleProfiles);
@@ -2852,7 +2859,7 @@ async function verifyProviderEntry(ui, provider, flags, deps) {
2852
2859
  } else if (serverBinding.effectiveRoleProfile) {
2853
2860
  liveLines.push(`runtime_role_profile: ${formatRoleProfileOutputLine(serverBinding.effectiveRoleProfile)}`);
2854
2861
  }
2855
- appendTextSection(lines, "live_server_binding", liveLines);
2862
+ appendTextSection(lines, "current_server_protocol", liveLines);
2856
2863
  }
2857
2864
  if (provider === "telegram" && routeLinks) {
2858
2865
  const routeSection = [`count: ${intFromRaw(routeLinks.total, 0)}`];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "metheus-governance-mcp-cli",
3
- "version": "0.2.103",
3
+ "version": "0.2.104",
4
4
  "description": "Metheus Governance MCP CLI (setup + stdio proxy)",
5
5
  "type": "module",
6
6
  "files": [