metheus-governance-mcp-cli 0.2.166 → 0.2.168
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 +21 -0
- package/cli.mjs +66 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -441,6 +441,7 @@ Route management:
|
|
|
441
441
|
- `runner route add` creates one executable route by selecting the project, provider, role, server bot, and project chat destination in order.
|
|
442
442
|
- `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.
|
|
443
443
|
- `runner project up` is the shortest practical route bootstrap path for Telegram: it audits one project destination, writes any missing suggested routes, then starts polling for that same destination unless you pass `--start false`.
|
|
444
|
+
- 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.
|
|
444
445
|
- `runner project up --dry-run-delivery true` lets the started runner validate route execution without sending a real provider message.
|
|
445
446
|
- 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.
|
|
446
447
|
- `runner route edit` updates one stored route. Use it when the destination, role, or server bot for an existing route changes.
|
|
@@ -519,6 +520,9 @@ Workspace/source-of-truth model:
|
|
|
519
520
|
- use local tool `runner.start_detached` to launch an existing runner route in a separate local terminal
|
|
520
521
|
- use local tool `runner.status` to inspect detached runner processes launched by this CLI
|
|
521
522
|
- use local tool `runner.stop` to stop detached runner processes launched by this CLI
|
|
523
|
+
- detached runner lifecycle belongs to the local Governance MCP tools, not to the current Codex/Claude/Gemini chat turn
|
|
524
|
+
- client AI should resolve workspace + route and then request `runner.start_detached`; it should not try to keep the polling runner attached to its own session
|
|
525
|
+
- the operational goal is: AI session may exit, but detached runner must continue polling independently on the local machine
|
|
522
526
|
- `runner.start_detached` opens a separate terminal window on Windows, Terminal.app on macOS, and a supported Linux terminal emulator (`x-terminal-emulator`, `gnome-terminal`, `konsole`, `mate-terminal`, `tilix`, `alacritty`, or `xterm`)
|
|
523
527
|
- on Linux, install one of those terminal emulators first; detached runner launch will fail fast if none are available
|
|
524
528
|
- `bot-runner.json` stores executable route config and role profiles; it is not the project workspace registry
|
|
@@ -591,6 +595,23 @@ Mapping behavior:
|
|
|
591
595
|
- `project.workspace.bind` updates the workspace registry directly; it does not need `bot-runner.json` side effects to succeed
|
|
592
596
|
- use `runner.project_up` after workspace binding to prepare executable routes for one project destination
|
|
593
597
|
- use `runner.show` to inspect the selected route before launching it
|
|
598
|
+
- use `runner.start_detached` to hand runner lifecycle over to the local machine after route preparation; do not rely on the current client AI process to keep polling alive
|
|
599
|
+
|
|
600
|
+
Recommended local runner bootstrap:
|
|
601
|
+
|
|
602
|
+
```text
|
|
603
|
+
1. project.workspace
|
|
604
|
+
2. project.workspace.bind # only when the registry binding is missing or wrong
|
|
605
|
+
3. runner.project_up
|
|
606
|
+
4. runner.show
|
|
607
|
+
5. runner.start_detached
|
|
608
|
+
6. runner.status / runner.stop
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
Operational principle:
|
|
612
|
+
- the local Governance MCP tools own runner startup and lifecycle
|
|
613
|
+
- the client AI only decides when to start/inspect/stop the runner
|
|
614
|
+
- the detached runner must keep running even if the current AI tool session exits
|
|
594
615
|
|
|
595
616
|
Runner command contract:
|
|
596
617
|
- stdin: JSON payload containing project, destination, trigger message, and recent context comments
|
package/cli.mjs
CHANGED
|
@@ -4720,7 +4720,16 @@ function resolveRunnerProjectUpRoutes({
|
|
|
4720
4720
|
|
|
4721
4721
|
async function runRunnerProjectUp(flags) {
|
|
4722
4722
|
const result = await buildRunnerProjectUpResult(flags);
|
|
4723
|
-
const {
|
|
4723
|
+
const {
|
|
4724
|
+
summaryPayload,
|
|
4725
|
+
applyRequested,
|
|
4726
|
+
applyResult,
|
|
4727
|
+
shouldStartRunner,
|
|
4728
|
+
matchingRoutes,
|
|
4729
|
+
startDetachedRequested,
|
|
4730
|
+
startFlags,
|
|
4731
|
+
applyFailureBlocksStart,
|
|
4732
|
+
} = result;
|
|
4724
4733
|
if (boolFromRaw(flags.json, false)) {
|
|
4725
4734
|
process.stdout.write(`${JSON.stringify(summaryPayload, null, 2)}\n`);
|
|
4726
4735
|
} else {
|
|
@@ -4746,11 +4755,12 @@ async function runRunnerProjectUp(flags) {
|
|
|
4746
4755
|
`enabled_routes_for_selection: ${summaryPayload.enabled_routes_for_selection.join(", ") || "-"}`,
|
|
4747
4756
|
`start_requested: ${summaryPayload.start_requested ? "true" : "false"}`,
|
|
4748
4757
|
`start_detached_requested: ${summaryPayload.start_detached_requested ? "true" : "false"}`,
|
|
4758
|
+
...(summaryPayload.warning ? [`warning: ${summaryPayload.warning}`] : []),
|
|
4749
4759
|
`next_steps: ${summaryPayload.next_steps.join(" | ") || "-"}`,
|
|
4750
4760
|
].join("\n") + "\n",
|
|
4751
4761
|
);
|
|
4752
4762
|
}
|
|
4753
|
-
if (
|
|
4763
|
+
if (applyFailureBlocksStart) {
|
|
4754
4764
|
process.exitCode = 1;
|
|
4755
4765
|
if (shouldStartRunner) {
|
|
4756
4766
|
throw new Error(String(applyResult.error || "runner project up could not apply runner routes").trim());
|
|
@@ -4775,6 +4785,17 @@ async function runRunnerProjectUp(flags) {
|
|
|
4775
4785
|
await runRunnerStartResolvedRoutes(matchingRoutes, startFlags);
|
|
4776
4786
|
}
|
|
4777
4787
|
|
|
4788
|
+
function canStartRunnerDespiteProjectUpApplyFailure({ applyRequested, applyResult, matchingRoutes }) {
|
|
4789
|
+
if (!applyRequested) return false;
|
|
4790
|
+
const normalizedApplyResult = safeObject(applyResult);
|
|
4791
|
+
if (normalizedApplyResult.ok !== false) return false;
|
|
4792
|
+
const errorText = String(normalizedApplyResult.error || "").trim();
|
|
4793
|
+
if (errorText !== "route apply skipped because the Telegram room visibility probe failed") {
|
|
4794
|
+
return false;
|
|
4795
|
+
}
|
|
4796
|
+
return ensureArray(matchingRoutes).length > 0;
|
|
4797
|
+
}
|
|
4798
|
+
|
|
4778
4799
|
async function buildRunnerProjectUpResult(flags = {}) {
|
|
4779
4800
|
const ui = createPrompter();
|
|
4780
4801
|
try {
|
|
@@ -4855,8 +4876,13 @@ async function buildRunnerProjectUpResult(flags = {}) {
|
|
|
4855
4876
|
...(botNameFilter ? { "bot-name": botNameFilter } : {}),
|
|
4856
4877
|
...(botIDFilter ? { "bot-id": botIDFilter } : {}),
|
|
4857
4878
|
};
|
|
4879
|
+
const applyFailureWarningOnly = canStartRunnerDespiteProjectUpApplyFailure({
|
|
4880
|
+
applyRequested,
|
|
4881
|
+
applyResult,
|
|
4882
|
+
matchingRoutes,
|
|
4883
|
+
});
|
|
4858
4884
|
const summaryPayload = {
|
|
4859
|
-
ok: !applyRequested || applyResult.ok !== false,
|
|
4885
|
+
ok: !applyRequested || applyResult.ok !== false || applyFailureWarningOnly,
|
|
4860
4886
|
provider,
|
|
4861
4887
|
project_id: String(auditPayload.projectID || "").trim(),
|
|
4862
4888
|
destination_label: String(destination.destinationLabel || "").trim(),
|
|
@@ -4889,7 +4915,11 @@ async function buildRunnerProjectUpResult(flags = {}) {
|
|
|
4889
4915
|
summaryPayload.next_steps.push(`${CLI_NAME} runner show --route-name ${summaryPayload.enabled_routes_for_selection[0] || "<route_name>"}`);
|
|
4890
4916
|
}
|
|
4891
4917
|
if (applyRequested && applyResult.ok === false && applyResult.error) {
|
|
4892
|
-
|
|
4918
|
+
if (applyFailureWarningOnly) {
|
|
4919
|
+
summaryPayload.warning = String(applyResult.error || "").trim();
|
|
4920
|
+
} else {
|
|
4921
|
+
summaryPayload.error = String(applyResult.error || "").trim();
|
|
4922
|
+
}
|
|
4893
4923
|
}
|
|
4894
4924
|
return {
|
|
4895
4925
|
summaryPayload,
|
|
@@ -4899,6 +4929,7 @@ async function buildRunnerProjectUpResult(flags = {}) {
|
|
|
4899
4929
|
startDetachedRequested,
|
|
4900
4930
|
matchingRoutes,
|
|
4901
4931
|
startFlags,
|
|
4932
|
+
applyFailureBlocksStart: applyRequested && applyResult.ok === false && !applyFailureWarningOnly,
|
|
4902
4933
|
};
|
|
4903
4934
|
} finally {
|
|
4904
4935
|
ui.close();
|
|
@@ -8609,6 +8640,9 @@ function appendProjectHintToInitialize(responseObj, args, options = {}) {
|
|
|
8609
8640
|
`- Use \`${projectWorkspaceBindTool}\` only when you need to explicitly write/update the local project-workspaces.json registry binding.`,
|
|
8610
8641
|
`- Use \`${runnerProjectUpTool}\` to audit a project destination and create/select runner routes before starting polling. Then use \`${runnerShowTool}\` to inspect the resolved route if needed.`,
|
|
8611
8642
|
`- To run automated polling independently of the current AI session, call \`${runnerStartDetachedTool}\` after the workspace binding and route are ready. Use \`${runnerStatusTool}\` to inspect detached runner processes and \`${runnerStopTool}\` to stop them later.`,
|
|
8643
|
+
"- Treat detached runner lifecycle as owned by the local Governance MCP tools, not by the current AI session.",
|
|
8644
|
+
`- Do not keep a long-running runner attached to the current client AI turn. Use \`${runnerStartDetachedTool}\` so the runner survives after the AI session exits.`,
|
|
8645
|
+
"- The AI should resolve the project workspace, prepare the route, and request detached start; the runner process itself must continue independently in a separate local terminal/process.",
|
|
8612
8646
|
`- After resolving the local workspace, call \`${projectSummaryTool}\` for project overview/agenda/server metadata.`,
|
|
8613
8647
|
`- If user enters a Project ID in text (e.g., "Project ID <uuid>"), pass that exact UUID as \`project_id\` argument when calling \`${projectSummaryTool}\`.`,
|
|
8614
8648
|
`- \`${projectDescribeTool}\` and \`${projectGetTool}\` are aliases of \`${projectSummaryTool}\`.`,
|
|
@@ -9812,6 +9846,34 @@ TELEGRAM_BOT_REVIEW_TOKEN=review-token
|
|
|
9812
9846
|
push("detached_runner_linux_launcher_selects_supported_terminal", false, String(err?.message || err));
|
|
9813
9847
|
}
|
|
9814
9848
|
|
|
9849
|
+
try {
|
|
9850
|
+
push(
|
|
9851
|
+
"runner_project_up_probe_failure_allows_existing_route_start",
|
|
9852
|
+
canStartRunnerDespiteProjectUpApplyFailure({
|
|
9853
|
+
applyRequested: true,
|
|
9854
|
+
applyResult: { ok: false, error: "route apply skipped because the Telegram room visibility probe failed" },
|
|
9855
|
+
matchingRoutes: [{ name: "telegram-monitor-selftest" }],
|
|
9856
|
+
}) === true,
|
|
9857
|
+
"existing_routes=1 probe_failure=warning_only",
|
|
9858
|
+
);
|
|
9859
|
+
} catch (err) {
|
|
9860
|
+
push("runner_project_up_probe_failure_allows_existing_route_start", false, String(err?.message || err));
|
|
9861
|
+
}
|
|
9862
|
+
|
|
9863
|
+
try {
|
|
9864
|
+
push(
|
|
9865
|
+
"runner_project_up_probe_failure_blocks_without_existing_route",
|
|
9866
|
+
canStartRunnerDespiteProjectUpApplyFailure({
|
|
9867
|
+
applyRequested: true,
|
|
9868
|
+
applyResult: { ok: false, error: "route apply skipped because the Telegram room visibility probe failed" },
|
|
9869
|
+
matchingRoutes: [],
|
|
9870
|
+
}) === false,
|
|
9871
|
+
"existing_routes=0 probe_failure=blocked",
|
|
9872
|
+
);
|
|
9873
|
+
} catch (err) {
|
|
9874
|
+
push("runner_project_up_probe_failure_blocks_without_existing_route", false, String(err?.message || err));
|
|
9875
|
+
}
|
|
9876
|
+
|
|
9815
9877
|
try {
|
|
9816
9878
|
const projectUpResponse = await handleLocalProjectToolDispatchImpl(
|
|
9817
9879
|
{
|