metheus-governance-mcp-cli 0.2.266 → 0.2.267

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.
@@ -9,6 +9,73 @@ function ensureArray(value) {
9
9
  return Array.isArray(value) ? value : [];
10
10
  }
11
11
 
12
+ function normalizeConversationHeuristicText(text) {
13
+ return String(text || "")
14
+ .trim()
15
+ .toLowerCase()
16
+ .replace(/\s+/g, " ");
17
+ }
18
+
19
+ function isImplicitSingleBotConversationContribution(taskText = "") {
20
+ const normalizedText = normalizeConversationHeuristicText(taskText);
21
+ if (!normalizedText) {
22
+ return false;
23
+ }
24
+ const workspaceArtifactPatterns = [
25
+ /\bfile\b/,
26
+ /\bfiles\b/,
27
+ /\bcode\b/,
28
+ /\bpatch\b/,
29
+ /\bcommit\b/,
30
+ /\bworkspace\b/,
31
+ /\brepo\b/,
32
+ /\brepository\b/,
33
+ /\bctxpack\b/,
34
+ /\bwork ?item\b/,
35
+ /\bevidence\b/,
36
+ /\bartifact\b/,
37
+ /\bimplement\b/,
38
+ /\bimplementation\b/,
39
+ /\bfix\b/,
40
+ /\bupdate\b/,
41
+ /\bedit\b/,
42
+ /\bcreate\b.*\b(document|doc|guide|plan|readme)\b/,
43
+ /\bwrite\b.*\b(document|doc|guide|plan|readme)\b/,
44
+ /\uD30C\uC77C/,
45
+ /\uCF54\uB4DC/,
46
+ /\uBB38\uC11C/,
47
+ /\uAD6C\uD604/,
48
+ /\uC218\uC815/,
49
+ /\uC791\uC131/,
50
+ /\uC544\uD2F0\uD329\uD2B8/,
51
+ /\uC99D\uAC70/,
52
+ /\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4/,
53
+ /\uCEE4\uBC0B/,
54
+ ];
55
+ if (workspaceArtifactPatterns.some((pattern) => pattern.test(normalizedText))) {
56
+ return false;
57
+ }
58
+ const conversationalPatterns = [
59
+ /\bgreet\b/,
60
+ /\bhello\b/,
61
+ /\bhi\b/,
62
+ /\bsay hello\b/,
63
+ /\bintroduce yourself\b/,
64
+ /\banswer briefly\b/,
65
+ /\breply briefly\b/,
66
+ /\bin this room\b/,
67
+ /\bone line\b/,
68
+ /\uC778\uC0AC/,
69
+ /\uC548\uB155/,
70
+ /\uD558\uC774/,
71
+ /\uC18C\uAC1C/,
72
+ /\uD55C ?\uC904/,
73
+ /\uC9E7\uAC8C/,
74
+ /\uB2F5\uD574/,
75
+ ];
76
+ return conversationalPatterns.some((pattern) => pattern.test(normalizedText));
77
+ }
78
+
12
79
  export function resolveInformationalQueryExecutionPlan(executionPlan, directInformationalReply, route) {
13
80
  const basePlan = safeObject(executionPlan);
14
81
  const override = safeObject(safeObject(directInformationalReply).execution_override);
@@ -151,6 +218,27 @@ export function summarizeCurrentAssignmentExecutionValidation(
151
218
  )
152
219
  && Boolean(implicitExecutionTask);
153
220
  if (!assignments.length) {
221
+ if (shouldUseImplicitSingleBotExecution && isImplicitSingleBotConversationContribution(implicitExecutionTask)) {
222
+ const implicitConversationAssignment = {
223
+ targetBot: currentSelector,
224
+ task: implicitExecutionTask,
225
+ mode: "conversation_contribution",
226
+ artifactsRequired: false,
227
+ workspaceAction: false,
228
+ requiresExecution: false,
229
+ };
230
+ return {
231
+ status: "conversation_assignment",
232
+ reason: "single-bot public conversational contribution does not require planner/worker execution",
233
+ assignmentModes: ["conversation_contribution"],
234
+ assignments: [implicitConversationAssignment],
235
+ executionAssignments: [],
236
+ conversationAssignments: [implicitConversationAssignment],
237
+ executionTasks: [],
238
+ allTasks: [implicitExecutionTask],
239
+ requiresPlanner: false,
240
+ };
241
+ }
154
242
  if (shouldUseImplicitSingleBotExecution) {
155
243
  const implicitAssignment = {
156
244
  targetBot: currentSelector,
@@ -6044,15 +6044,159 @@ export async function runSelftestRunnerScenarios(push, deps) {
6044
6044
  && deliveredText === "I will inspect the project first and come back later.",
6045
6045
  `kind=${String(processed.kind || "(none)")} outcome=${String(processed.result?.outcome || "(none)")} ai_calls=${aiCalls} delivery_calls=${deliveryCalls} delivered=${deliveredText} reason=${String(processed.result?.detail || "(none)")}`,
6046
6046
  );
6047
- } catch (err) {
6048
- push("single_bot_human_work_request_requires_actionable_contract", false, String(err?.message || err));
6049
- }
6050
-
6051
- try {
6052
- let aiCalls = 0;
6053
- let deliveryCalls = 0;
6054
- let deliveredText = "";
6055
- let capturedFailureFacts = null;
6047
+ } catch (err) {
6048
+ push("single_bot_human_work_request_requires_actionable_contract", false, String(err?.message || err));
6049
+ }
6050
+
6051
+ try {
6052
+ let aiCalls = 0;
6053
+ let plannerCalls = 0;
6054
+ let deliveryCalls = 0;
6055
+ let deliveredText = "";
6056
+ const processed = await processRunnerSelectedRecord({
6057
+ routeKey: "single-bot-conversation-greeting-request-key",
6058
+ normalizedRoute: normalizeRunnerRoute({
6059
+ name: "telegram-monitor-single-bot-conversation-greeting",
6060
+ project_id: selftestProjectID,
6061
+ provider: "telegram",
6062
+ role: "monitor",
6063
+ role_profile: "monitor",
6064
+ destination_id: "dest-1",
6065
+ destination_label: "Main Room",
6066
+ server_bot_name: "RyoAI_bot",
6067
+ server_bot_id: "bot-lead-1",
6068
+ trigger_policy: {
6069
+ mentions_only: true,
6070
+ direct_messages: true,
6071
+ reply_to_bot_messages: true,
6072
+ },
6073
+ archive_policy: {
6074
+ mirror_replies: true,
6075
+ dedupe_inbound: true,
6076
+ dedupe_outbound: true,
6077
+ skip_bot_messages: true,
6078
+ },
6079
+ dry_run_delivery: true,
6080
+ }),
6081
+ selectedRecord: {
6082
+ id: "comment-single-bot-conversation-greeting-request",
6083
+ createdAt: "2026-03-31T08:37:56.000Z",
6084
+ parsedArchive: {
6085
+ kind: "telegram_message",
6086
+ chatID: "-100123",
6087
+ chatType: "supergroup",
6088
+ senderIsBot: false,
6089
+ body: "@RyoAI_bot 당신이 @SangHoon01_bot 에게 인사해보세요.",
6090
+ mentionUsernames: ["RyoAI_bot", "SangHoon01_bot"],
6091
+ messageID: 1057,
6092
+ },
6093
+ },
6094
+ pendingOrdered: [],
6095
+ bot: {
6096
+ id: "bot-lead-1",
6097
+ name: "RyoAI_bot",
6098
+ username: "RyoAI_bot",
6099
+ role: "monitor",
6100
+ provider: "telegram",
6101
+ },
6102
+ destination: {
6103
+ id: "dest-1",
6104
+ label: "Main Room",
6105
+ provider: "telegram",
6106
+ chatID: "-100123",
6107
+ },
6108
+ archiveThread: {
6109
+ threadID: "thread-1",
6110
+ workItemID: "work-item-1",
6111
+ },
6112
+ executionPlan: {
6113
+ mode: "role_profile",
6114
+ roleProfileName: "monitor",
6115
+ roleProfile: {
6116
+ client: "sample",
6117
+ model: "",
6118
+ permissionMode: "read_only",
6119
+ reasoningEffort: "low",
6120
+ },
6121
+ workspaceDir: path.join(os.tmpdir(), "metheus-runner-selftest-single-bot-conversation-greeting"),
6122
+ workspaceSource: "selftest",
6123
+ usedCommandFallback: false,
6124
+ },
6125
+ runtime: {
6126
+ baseURL: "https://example.test",
6127
+ token: "selftest-token",
6128
+ timeoutSeconds: 30,
6129
+ actor: { user_id: "user-1" },
6130
+ },
6131
+ deps: {
6132
+ saveRunnerRouteState: () => {},
6133
+ startRunnerTypingHeartbeat: () => ({ async stop() {} }),
6134
+ runRunnerAIExecution: async () => {
6135
+ aiCalls += 1;
6136
+ return {
6137
+ skip: false,
6138
+ reply: "@SangHoon01_bot 안녕하세요.",
6139
+ replyToMessageID: 0,
6140
+ };
6141
+ },
6142
+ performLocalBotDelivery: async ({ text }) => {
6143
+ deliveryCalls += 1;
6144
+ deliveredText = String(text || "").trim();
6145
+ return {
6146
+ delivery: { dryRun: true, body: {} },
6147
+ archive: {},
6148
+ };
6149
+ },
6150
+ serializeRunnerTriggerPolicy: (value) => value,
6151
+ serializeRunnerArchivePolicy: (value) => value,
6152
+ buildRunnerExecutionDeps: () => ({
6153
+ analyzeHumanConversationIntentWithAI: async () => ({
6154
+ mode: "single_bot",
6155
+ lead_bot: "ryoai_bot",
6156
+ participants: ["ryoai_bot"],
6157
+ initial_responders: ["ryoai_bot"],
6158
+ allowed_responders: ["ryoai_bot"],
6159
+ summary_bot: "",
6160
+ allow_bot_to_bot: false,
6161
+ reply_expectation: "actionable",
6162
+ intent_type: "general_execution",
6163
+ }),
6164
+ planRoleExecutionWithAI: async () => {
6165
+ plannerCalls += 1;
6166
+ return {
6167
+ requiresExecution: true,
6168
+ summaryRole: "worker",
6169
+ steps: [{ role: "worker", goal: "unexpected", artifactsRequired: true }],
6170
+ };
6171
+ },
6172
+ }),
6173
+ buildRunnerDeliveryDeps: () => ({}),
6174
+ buildRunnerRuntimeDeps: () => ({}),
6175
+ resolveConversationPeerBots: () => [
6176
+ { id: "bot-lead-1", name: "RyoAI_bot" },
6177
+ ],
6178
+ },
6179
+ });
6180
+ push(
6181
+ "single_bot_conversational_greeting_request_skips_planner_and_worker",
6182
+ processed.kind === "replied"
6183
+ && aiCalls === 1
6184
+ && plannerCalls === 0
6185
+ && deliveryCalls === 1
6186
+ && String(processed.result?.assignment_validation_status || "") === "conversation_assignment"
6187
+ && ensureArray(processed.result?.assignment_validation_modes).includes("conversation_contribution")
6188
+ && deliveredText === "@SangHoon01_bot 안녕하세요.",
6189
+ `kind=${String(processed.kind || "(none)")} ai_calls=${aiCalls} planner_calls=${plannerCalls} delivery_calls=${deliveryCalls} assignment_status=${String(processed.result?.assignment_validation_status || "(none)")} modes=${JSON.stringify(processed.result?.assignment_validation_modes || [])} delivered=${String(deliveredText || "(none)")}`,
6190
+ );
6191
+ } catch (err) {
6192
+ push("single_bot_conversational_greeting_request_skips_planner_and_worker", false, String(err?.message || err));
6193
+ }
6194
+
6195
+ try {
6196
+ let aiCalls = 0;
6197
+ let deliveryCalls = 0;
6198
+ let deliveredText = "";
6199
+ let capturedFailureFacts = null;
6056
6200
  const workspaceDir = fs.mkdtempSync(path.join(os.tmpdir(), "metheus-runner-selftest-ai-failure-explainer-"));
6057
6201
  const processed = await processRunnerSelectedRecord({
6058
6202
  routeKey: "single-bot-human-work-request-ai-failure-explainer-key",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "metheus-governance-mcp-cli",
3
- "version": "0.2.266",
3
+ "version": "0.2.267",
4
4
  "description": "Metheus Governance MCP CLI (setup + stdio proxy)",
5
5
  "type": "module",
6
6
  "files": [