metheus-governance-mcp-cli 0.2.103 → 0.2.105

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
@@ -95,7 +95,7 @@ Runner template:
95
95
  },
96
96
  "role_profiles": {
97
97
  "monitor": {
98
- "client": "codex",
98
+ "client": "gpt",
99
99
  "model": "",
100
100
  "permission_mode": "read_only",
101
101
  "reasoning_effort": "low"
@@ -106,7 +106,7 @@ Runner template:
106
106
  "bot_id": "<server_bot_uuid>",
107
107
  "bot_name": "<bot_name>",
108
108
  "role_profile": "monitor",
109
- "client": "codex",
109
+ "client": "gpt",
110
110
  "model": "",
111
111
  "permission_mode": "read_only",
112
112
  "reasoning_effort": "low"
@@ -194,15 +194,18 @@ Fill provider bot secrets and provider-local transport options locally. Project
194
194
  Built-in helper command for legacy fallback/testing:
195
195
 
196
196
  ```bash
197
- metheus-governance-mcp-cli local-bot-bridge --client codex --no-update
197
+ metheus-governance-mcp-cli local-bot-bridge --client gpt --no-update
198
198
  ```
199
199
 
200
200
  Supported `--client` values:
201
- - `codex`
201
+ - `gpt`
202
202
  - `claude`
203
203
  - `gemini`
204
204
  - `sample`
205
205
 
206
+ Compatibility note:
207
+ - `codex` is still accepted as an alias for `gpt` because the GPT adapter runs through the Codex CLI binary.
208
+
206
209
  Use `sample` first for smoke tests before switching to a real AI client.
207
210
 
208
211
  Gemini CLI note:
@@ -280,7 +283,7 @@ Behavior:
280
283
  - Slack and KakaoTalk currently use a single local token entry per provider in this command flow.
281
284
  - `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
285
  - `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.
286
+ - 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
287
  - `bot global` edits Telegram-wide local settings such as API base URL, allowed updates, and default bot key.
285
288
  - `bot set-default` updates `TELEGRAM_DEFAULT_BOT_KEY`.
286
289
  - `bot migrate` moves legacy `TELEGRAM_BOT_TOKEN` into a named Telegram bot entry.
@@ -302,6 +305,8 @@ For direct Telegram adds, the CLI derives the local file name from the matched s
302
305
 
303
306
  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
307
 
308
+ 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.
309
+
305
310
  Current support status:
306
311
 
307
312
  - Telegram: full local bot entry management, token verification, bot-to-AI binding, inbound runner support
@@ -376,7 +381,7 @@ Execution model:
376
381
  - local runner stores workspace mapping and role profiles
377
382
  - runner resolves `project_id -> workspace_dir`
378
383
  - runner resolves server bot role to a local `role_profile`
379
- - runner executes the mapped client adapter (`codex` / `claude` / `gemini`)
384
+ - runner executes the mapped client adapter (`gpt` / `claude` / `gemini`)
380
385
  - legacy `command` remains readable for migration, but execution is disabled by default unless `METHEUS_ALLOW_LEGACY_RUNNER_COMMAND=1`
381
386
 
382
387
  Commands:
@@ -419,7 +424,8 @@ Why `workspace_dir` matters:
419
424
  - without a valid project mapping, bots may answer with a generic local root instead of the real project workspace
420
425
 
421
426
  Role profile fields:
422
- - `client`: `codex`, `claude`, `gemini`, or `sample`
427
+ - `client`: `gpt`, `claude`, `gemini`, or `sample`
428
+ - `codex` is still accepted as a compatibility alias for `gpt`
423
429
  - `model`: optional CLI-specific model name
424
430
  - `permission_mode`: `read_only`, `workspace_write`, `danger_full_access`
425
431
  - `reasoning_effort`: `low`, `medium`, `high`
package/cli.mjs CHANGED
@@ -185,7 +185,7 @@ const CTXPACK_PUSH_TOOL_NAMES = ["ctxpack.push", "ctxpack.update", "ctxpack.save
185
185
  const CLI_META = loadCLIMeta();
186
186
  const CLI_NAME = CLI_META.name || "metheus-governance-mcp-cli";
187
187
  const CLI_VERSION = CLI_META.version || "0.0.0";
188
- const DEFAULT_BOT_RUNNER_CLIENT = DEFAULT_LOCAL_AI_CLIENT;
188
+ const DEFAULT_BOT_RUNNER_CLIENT = "gpt";
189
189
  const SELF_UPDATE_CHECK_INTERVAL_MS = 6 * 60 * 60 * 1000;
190
190
  const SELF_UPDATE_TIMEOUT_SECONDS = 6;
191
191
  const SELF_UPDATE_ENV_KEY = "METHEUS_CLI_AUTO_UPDATE";
@@ -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
- ` ${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>]`,
256
+ ` ${cmd} local-bot-bridge [--client <gpt|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>]`,
@@ -832,7 +832,7 @@ function defaultLocalBotBridgeCommand(client = DEFAULT_BOT_RUNNER_CLIENT) {
832
832
  function defaultBotRunnerRoleProfiles() {
833
833
  return {
834
834
  monitor: {
835
- client: "codex",
835
+ client: "gpt",
836
836
  model: "",
837
837
  permission_mode: "read_only",
838
838
  reasoning_effort: "low",
@@ -844,7 +844,7 @@ function defaultBotRunnerRoleProfiles() {
844
844
  reasoning_effort: "medium",
845
845
  },
846
846
  worker: {
847
- client: "codex",
847
+ client: "gpt",
848
848
  model: "",
849
849
  permission_mode: "danger_full_access",
850
850
  reasoning_effort: "medium",
@@ -1243,6 +1243,7 @@ function normalizeBotRunnerConfigContents(parsed, filePath) {
1243
1243
  const defaults = defaultBotRunnerRoleProfiles();
1244
1244
  const rawRoleProfiles = safeObject(raw.role_profiles || raw.roleProfiles);
1245
1245
  const roleProfiles = {};
1246
+ let migrated = rawVersion < BOT_RUNNER_CONFIG_VERSION;
1246
1247
  const roleProfileNames = new Set([
1247
1248
  ...Object.keys(defaults),
1248
1249
  ...Object.keys(rawRoleProfiles).map((name) => normalizeRunnerRoleProfileName(name)).filter(Boolean),
@@ -1253,6 +1254,10 @@ function normalizeBotRunnerConfigContents(parsed, filePath) {
1253
1254
  rawRoleProfiles[profileName],
1254
1255
  defaults[profileName] || {},
1255
1256
  );
1257
+ const rawClient = String(safeObject(rawRoleProfiles[profileName]).client || safeObject(rawRoleProfiles[profileName]).cli || "").trim().toLowerCase();
1258
+ if (rawClient === "codex") {
1259
+ migrated = true;
1260
+ }
1256
1261
  }
1257
1262
 
1258
1263
  const botBindings = {};
@@ -1262,6 +1267,10 @@ function normalizeBotRunnerConfigContents(parsed, filePath) {
1262
1267
  if (!binding.name || (!binding.botID && !binding.botName)) continue;
1263
1268
  if (!binding.roleProfile && !binding.client && !binding.model && !binding.permissionMode && !binding.reasoningEffort) continue;
1264
1269
  botBindings[binding.name] = binding;
1270
+ const rawClient = String(safeObject(rawBinding).client || "").trim().toLowerCase();
1271
+ if (rawClient === "codex") {
1272
+ migrated = true;
1273
+ }
1265
1274
  }
1266
1275
 
1267
1276
  const projectMappings = {};
@@ -1274,7 +1283,6 @@ function normalizeBotRunnerConfigContents(parsed, filePath) {
1274
1283
  }
1275
1284
 
1276
1285
  const routes = [];
1277
- let migrated = rawVersion < BOT_RUNNER_CONFIG_VERSION;
1278
1286
  for (const rawRoute of ensureArray(raw.routes)) {
1279
1287
  const routeSource = safeObject(rawRoute);
1280
1288
  const route = normalizeRunnerRoute(routeSource);
@@ -2568,15 +2576,32 @@ async function runRunnerOnce(flags) {
2568
2576
 
2569
2577
  function buildRunnerRouteListRows() {
2570
2578
  const config = loadBotRunnerConfig({ persistIfNeeded: true });
2579
+ const telegramState = readTelegramEnvState();
2580
+ const telegramEntries = ensureArray(telegramState.entries);
2571
2581
  return ensureArray(config.routes).map((rawRoute, index) => {
2572
2582
  const route = normalizeRunnerRoute(rawRoute);
2583
+ const matchedTelegramEntry = route.provider === "telegram"
2584
+ ? telegramEntries.find((entry) => {
2585
+ const current = safeObject(entry);
2586
+ return (
2587
+ (route.botID && current.serverBotID && current.serverBotID === route.botID)
2588
+ || (route.botName && current.serverBotName && current.serverBotName === route.botName)
2589
+ );
2590
+ })
2591
+ : null;
2592
+ const resolvedBotName = firstNonEmptyString([
2593
+ route.botName,
2594
+ matchedTelegramEntry?.serverBotName,
2595
+ matchedTelegramEntry?.key,
2596
+ "-",
2597
+ ]);
2573
2598
  return {
2574
2599
  index: index + 1,
2575
2600
  name: route.name || runnerRouteKey(route),
2576
2601
  enabled: route.enabled !== false,
2577
2602
  provider: route.provider || "-",
2578
2603
  projectID: route.projectID || "-",
2579
- botName: route.botName || "-",
2604
+ botName: resolvedBotName,
2580
2605
  botID: route.botID || "-",
2581
2606
  role: route.role || "-",
2582
2607
  roleProfile: route.roleProfile || "-",
@@ -2605,13 +2630,14 @@ async function runRunnerList(flags) {
2605
2630
  ` - ${row.name}${row.enabled ? "" : " [disabled]"}`,
2606
2631
  ` provider: ${row.provider}`,
2607
2632
  ` project_id: ${row.projectID}`,
2608
- ` bot_name: ${row.botName}`,
2633
+ ` server_bot_name: ${row.botName}`,
2609
2634
  ` bot_id: ${row.botID}`,
2610
2635
  ` role: ${row.role}`,
2611
2636
  ` role_profile: ${row.roleProfile}`,
2612
2637
  ` destination_label: ${row.destinationLabel}`,
2613
2638
  ` poll_interval_ms: ${row.pollIntervalMs}`,
2614
2639
  ` run_once: ${CLI_NAME} runner once --route-name ${row.name}`,
2640
+ row.botName ? ` run_once_by_bot_name: ${CLI_NAME} runner once --bot-name "${row.botName}"` : "",
2615
2641
  ].join("\n") + "\n",
2616
2642
  );
2617
2643
  });
@@ -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
  );
@@ -812,7 +813,7 @@ function telegramEntryDisplayName(entry) {
812
813
 
813
814
  function displayLocalAIClientName(clientName) {
814
815
  const normalized = String(clientName || "").trim().toLowerCase();
815
- if (normalized === "codex" || normalized === "gpt") return "GPT";
816
+ if (normalized === "gpt" || normalized === "codex") return "GPT";
816
817
  if (normalized === "claude") return "Claude";
817
818
  if (normalized === "gemini") return "Gemini";
818
819
  if (normalized === "sample") return "Sample";
@@ -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) => {
@@ -1752,7 +1758,7 @@ async function promptAIClient(ui, deps, defaultValue = "") {
1752
1758
 
1753
1759
  function suggestedAIModelsForClient(clientName) {
1754
1760
  const normalizedClient = String(clientName || "").trim().toLowerCase();
1755
- if (normalizedClient === "codex") {
1761
+ if (normalizedClient === "gpt") {
1756
1762
  return [
1757
1763
  { value: "gpt-5.4", label: "gpt-5.4", description: "recommended GPT model" },
1758
1764
  { value: "gpt-5.3-codex", label: "gpt-5.3-codex", description: "stable GPT codex model" },
@@ -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)}`];
@@ -3,8 +3,8 @@ import os from "node:os";
3
3
  import path from "node:path";
4
4
  import { spawnSync } from "node:child_process";
5
5
 
6
- export const SUPPORTED_LOCAL_AI_CLIENTS = ["codex", "claude", "gemini", "sample"];
7
- export const DEFAULT_LOCAL_AI_CLIENT = "codex";
6
+ export const SUPPORTED_LOCAL_AI_CLIENTS = ["gpt", "claude", "gemini", "sample"];
7
+ export const DEFAULT_LOCAL_AI_CLIENT = "gpt";
8
8
 
9
9
  const SUPPORTED_PERMISSION_MODES = ["read_only", "workspace_write", "danger_full_access"];
10
10
  const SUPPORTED_REASONING_EFFORTS = ["low", "medium", "high"];
@@ -18,7 +18,7 @@ const GEMINI_HOME_SYNC_FILES = [
18
18
  "settings.json",
19
19
  ];
20
20
  const LOCAL_AI_MODEL_MAPPINGS = {
21
- codex: [
21
+ gpt: [
22
22
  {
23
23
  display: "gpt-5.4",
24
24
  execution: "gpt-5.4",
@@ -589,8 +589,8 @@ function runSampleAdapter(payload) {
589
589
 
590
590
  export function normalizeLocalAIClientName(rawValue, fallback = DEFAULT_LOCAL_AI_CLIENT) {
591
591
  const value = String(rawValue || "").trim().toLowerCase();
592
- if (["gpt", "openai-gpt", "openai"].includes(value)) {
593
- return "codex";
592
+ if (["gpt", "openai-gpt", "openai", "codex"].includes(value)) {
593
+ return "gpt";
594
594
  }
595
595
  if (SUPPORTED_LOCAL_AI_CLIENTS.includes(value)) {
596
596
  return value;
@@ -734,7 +734,7 @@ export function runLocalAIClient({
734
734
  METHEUS_AI_RUNNER_REASONING_EFFORT: normalizedReasoningEffort,
735
735
  METHEUS_RUNNER_WORKSPACE_DIR: resolvedWorkspaceDir,
736
736
  };
737
- if (normalizedClient === "codex") {
737
+ if (normalizedClient === "gpt") {
738
738
  return runCodexAdapter({
739
739
  promptText,
740
740
  workspaceDir: resolvedWorkspaceDir,
@@ -236,20 +236,20 @@ export async function runSelftestBotCommands(push, deps) {
236
236
  try {
237
237
  push(
238
238
  "display_model_labels_map_to_tested_execution_ids",
239
- resolveLocalAIExecutionModel("codex", "gpt-5.4") === "gpt-5.4"
240
- && resolveLocalAIExecutionModel("codex", "gpt-5.3-codex") === "gpt-5.3-codex"
241
- && resolveLocalAIExecutionModel("codex", "gpt-5.3-codex-spark") === "gpt-5.3-codex-spark"
242
- && resolveLocalAIExecutionModel("codex", "GPT-5.4") === "gpt-5.4"
243
- && resolveLocalAIExecutionModel("codex", "GPT-5.3-CODEX") === "gpt-5.3-codex"
244
- && resolveLocalAIExecutionModel("codex", "GPT-5.3-CODEX-Spark") === "gpt-5.3-codex-spark"
239
+ resolveLocalAIExecutionModel("gpt", "gpt-5.4") === "gpt-5.4"
240
+ && resolveLocalAIExecutionModel("gpt", "gpt-5.3-codex") === "gpt-5.3-codex"
241
+ && resolveLocalAIExecutionModel("gpt", "gpt-5.3-codex-spark") === "gpt-5.3-codex-spark"
242
+ && resolveLocalAIExecutionModel("gpt", "GPT-5.4") === "gpt-5.4"
243
+ && resolveLocalAIExecutionModel("gpt", "GPT-5.3-CODEX") === "gpt-5.3-codex"
244
+ && resolveLocalAIExecutionModel("gpt", "GPT-5.3-CODEX-Spark") === "gpt-5.3-codex-spark"
245
245
  && resolveLocalAIExecutionModel("claude", "Sonnet 4.6r") === "sonnet"
246
246
  && resolveLocalAIExecutionModel("claude", "Haiku 4.5") === "haiku"
247
247
  && resolveLocalAIExecutionModel("claude", "Opus 4.6") === "opus"
248
248
  && resolveLocalAIExecutionModel("gemini", "gemini-3.1-pro") === "auto-gemini-3",
249
249
  [
250
- `gpt54=${resolveLocalAIExecutionModel("codex", "gpt-5.4")}`,
251
- `gpt53codex=${resolveLocalAIExecutionModel("codex", "gpt-5.3-codex")}`,
252
- `spark=${resolveLocalAIExecutionModel("codex", "gpt-5.3-codex-spark")}`,
250
+ `gpt54=${resolveLocalAIExecutionModel("gpt", "gpt-5.4")}`,
251
+ `gpt53codex=${resolveLocalAIExecutionModel("gpt", "gpt-5.3-codex")}`,
252
+ `spark=${resolveLocalAIExecutionModel("gpt", "gpt-5.3-codex-spark")}`,
253
253
  `claude=${resolveLocalAIExecutionModel("claude", "Sonnet 4.6r")}`,
254
254
  `gemini=${resolveLocalAIExecutionModel("gemini", "gemini-3.1-pro")}`,
255
255
  ].join(" "),
@@ -257,11 +257,11 @@ export async function runSelftestBotCommands(push, deps) {
257
257
 
258
258
  push(
259
259
  "blank_model_defaults_to_first_display_model_for_each_client",
260
- suggestLocalAIModelDisplayName("codex", "") === "gpt-5.4"
260
+ suggestLocalAIModelDisplayName("gpt", "") === "gpt-5.4"
261
261
  && suggestLocalAIModelDisplayName("claude", "") === "Sonnet 4.6r"
262
262
  && suggestLocalAIModelDisplayName("gemini", "") === "gemini-3.1-pro",
263
263
  [
264
- `codex=${suggestLocalAIModelDisplayName("codex", "")}`,
264
+ `gpt=${suggestLocalAIModelDisplayName("gpt", "")}`,
265
265
  `claude=${suggestLocalAIModelDisplayName("claude", "")}`,
266
266
  `gemini=${suggestLocalAIModelDisplayName("gemini", "")}`,
267
267
  ].join(" "),
@@ -367,7 +367,7 @@ export async function runSelftestBotCommands(push, deps) {
367
367
  && String(addState.TELEGRAM_BOT_SERVER_ROLES || "") === "monitor"
368
368
  && String(addState.TELEGRAM_BOT_TOKEN || "") === "selftest-main-token"
369
369
  && String(addState.TELEGRAM_BOT_ROLE_PROFILE || "") === "monitor"
370
- && String(addState.TELEGRAM_BOT_AI_CLIENT || "") === "codex"
370
+ && String(addState.TELEGRAM_BOT_AI_CLIENT || "") === "gpt"
371
371
  && String(addState.TELEGRAM_BOT_AI_PERMISSION_MODE || "") === "read_only"
372
372
  && String(addState.TELEGRAM_BOT_AI_REASONING_EFFORT || "") === "low"
373
373
  && String(addGlobals.TELEGRAM_DEFAULT_BOT_KEY || "") === "monitorselftestbot",
@@ -553,7 +553,7 @@ export async function runSelftestBotCommands(push, deps) {
553
553
  push(
554
554
  "bot_show_returns_selected_telegram_entry",
555
555
  safeObject(showPayload.entry).key === "monitorselftestbot"
556
- && safeObject(showPayload.entry).client === "codex"
556
+ && safeObject(showPayload.entry).client === "gpt"
557
557
  && safeObject(showPayload.serverBinding).mode === "single",
558
558
  `key=${String(safeObject(showPayload.entry).key || "")} client=${String(safeObject(showPayload.entry).client || "")} mode=${String(safeObject(showPayload.serverBinding).mode || "")}`,
559
559
  );
@@ -773,7 +773,7 @@ export async function runSelftestBotCommands(push, deps) {
773
773
  String(aliasAddState.TELEGRAM_BOT_SERVER_BOT_ID || "") === mock.bots[0].id
774
774
  && String(aliasAddState.TELEGRAM_BOT_SERVER_NAME || "") === "MonitorSelftestBot"
775
775
  && String(aliasAddState.TELEGRAM_BOT_SERVER_ROLES || "") === "monitor"
776
- && String(aliasAddState.TELEGRAM_BOT_AI_CLIENT || "") === "codex"
776
+ && String(aliasAddState.TELEGRAM_BOT_AI_CLIENT || "") === "gpt"
777
777
  && String(aliasAddState.TELEGRAM_BOT_AI_MODEL || "") === "gpt-5.4"
778
778
  && String(aliasAddState.TELEGRAM_BOT_AI_PERMISSION_MODE || "") === "read_only"
779
779
  && String(aliasAddState.TELEGRAM_BOT_AI_REASONING_EFFORT || "") === "low",
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.105",
4
4
  "description": "Metheus Governance MCP CLI (setup + stdio proxy)",
5
5
  "type": "module",
6
6
  "files": [
package/postinstall.mjs CHANGED
@@ -75,7 +75,7 @@ function botRunnerTemplate() {
75
75
  },
76
76
  role_profiles: {
77
77
  monitor: {
78
- client: "codex",
78
+ client: "gpt",
79
79
  model: "",
80
80
  permission_mode: "read_only",
81
81
  reasoning_effort: "low",
@@ -87,7 +87,7 @@ function botRunnerTemplate() {
87
87
  reasoning_effort: "medium",
88
88
  },
89
89
  worker: {
90
- client: "codex",
90
+ client: "gpt",
91
91
  model: "",
92
92
  permission_mode: "danger_full_access",
93
93
  reasoning_effort: "medium",
@@ -104,7 +104,7 @@ function botRunnerTemplate() {
104
104
  bot_id: "<server_bot_uuid>",
105
105
  bot_name: "<bot_name>",
106
106
  role_profile: "monitor",
107
- client: "codex",
107
+ client: "gpt",
108
108
  model: "",
109
109
  permission_mode: "read_only",
110
110
  reasoning_effort: "low",