metheus-governance-mcp-cli 0.2.217 → 0.2.219

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/cli.mjs CHANGED
@@ -184,6 +184,7 @@ import {
184
184
  runRunnerAIExecution,
185
185
  } from "./lib/runner-execution.mjs";
186
186
  import {
187
+ buildRunnerResponderAdjudicationFromHumanIntent,
187
188
  processRunnerSelectedRecord,
188
189
  resolveHumanIntentContext,
189
190
  resolveRunnerResponderAdjudication,
@@ -8287,7 +8288,14 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
8287
8288
  executionPlan,
8288
8289
  deps: routingExecutionDeps,
8289
8290
  });
8290
- const adjudication = await resolveRunnerResponderAdjudication({
8291
+ const precomputedAdjudication = buildRunnerResponderAdjudicationFromHumanIntent({
8292
+ selectedRecord,
8293
+ normalizedRoute,
8294
+ bot,
8295
+ deps: routingExecutionDeps,
8296
+ precomputedHumanIntent: safeObject(sharedHumanIntentContext).humanIntent || null,
8297
+ });
8298
+ const adjudication = precomputedAdjudication || await resolveRunnerResponderAdjudication({
8291
8299
  selectedRecord,
8292
8300
  pendingOrdered: pending.ordered,
8293
8301
  normalizedRoute,
@@ -8540,7 +8548,14 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
8540
8548
  executionPlan,
8541
8549
  deps: routingExecutionDeps,
8542
8550
  });
8543
- const inlineAdjudication = await resolveRunnerResponderAdjudication({
8551
+ const precomputedInlineAdjudication = buildRunnerResponderAdjudicationFromHumanIntent({
8552
+ selectedRecord,
8553
+ normalizedRoute,
8554
+ bot,
8555
+ deps: routingExecutionDeps,
8556
+ precomputedHumanIntent: safeObject(sharedHumanIntentContext).humanIntent || null,
8557
+ });
8558
+ const inlineAdjudication = precomputedInlineAdjudication || await resolveRunnerResponderAdjudication({
8544
8559
  selectedRecord,
8545
8560
  pendingOrdered: pending.ordered,
8546
8561
  normalizedRoute,
@@ -4285,17 +4285,20 @@ export async function resolveRunnerResponderAdjudication({
4285
4285
  ? deps.adjudicateRunnerRespondersWithAI
4286
4286
  : null;
4287
4287
  const promise = (async () => {
4288
- const managedBots = buildResponderAdjudicationManagedBots({
4288
+ const managedBots = buildResponderAdjudicationManagedBots({
4289
4289
  selectedRecord,
4290
4290
  normalizedRoute,
4291
4291
  bot,
4292
4292
  deps,
4293
4293
  });
4294
- const managedBotSelectors = new Set(
4295
- managedBots
4296
- .map((entry) => normalizeMentionSelector(entry.username))
4297
- .filter(Boolean),
4298
- );
4294
+ const contractAdjudication = buildRunnerResponderAdjudicationFromHumanIntent({
4295
+ selectedRecord,
4296
+ managedBots,
4297
+ precomputedHumanIntent,
4298
+ });
4299
+ if (contractAdjudication) {
4300
+ return contractAdjudication;
4301
+ }
4299
4302
  const triggerFacts = {
4300
4303
  message_kind: String(safeObject(selectedRecord?.parsedArchive).kind || "").trim(),
4301
4304
  chat_type: String(safeObject(selectedRecord?.parsedArchive).chatType || "").trim(),
@@ -4311,60 +4314,6 @@ export async function resolveRunnerResponderAdjudication({
4311
4314
  trigger_reason: String(entry.trigger_reason || "").trim(),
4312
4315
  })),
4313
4316
  };
4314
- const humanIntent = safeObject(precomputedHumanIntent);
4315
- const contractInitialResponders = uniqueOrdered(
4316
- ensureArray(humanIntent.initialResponderSelectors)
4317
- .map((value) => normalizeMentionSelector(value))
4318
- .filter((value) => value && managedBotSelectors.has(value)),
4319
- );
4320
- const contractAllowedResponders = uniqueOrdered(
4321
- ensureArray(humanIntent.allowedResponderSelectors)
4322
- .map((value) => normalizeMentionSelector(value))
4323
- .filter((value) => value && managedBotSelectors.has(value)),
4324
- );
4325
- const contractParticipants = uniqueOrdered(
4326
- ensureArray(humanIntent.participantSelectors)
4327
- .map((value) => normalizeMentionSelector(value))
4328
- .filter((value) => value && managedBotSelectors.has(value)),
4329
- );
4330
- const contractLeadBot = normalizeMentionSelector(humanIntent.leadBotSelector);
4331
- const selectedFromContract = uniqueOrdered(
4332
- (
4333
- contractInitialResponders.length
4334
- ? contractInitialResponders
4335
- : contractAllowedResponders.length
4336
- ? contractAllowedResponders
4337
- : contractParticipants.length
4338
- ? contractParticipants
4339
- : contractLeadBot && managedBotSelectors.has(contractLeadBot)
4340
- ? [contractLeadBot]
4341
- : []
4342
- ).filter(Boolean),
4343
- );
4344
- if (selectedFromContract.length > 0) {
4345
- return {
4346
- decision: selectedFromContract.length > 1 ? "multiple_responders" : "single_responder",
4347
- selected_bot_usernames: selectedFromContract,
4348
- referenced_bot_usernames: triggerFacts.mentioned_bot_usernames,
4349
- confidence: "high",
4350
- reason_code: "precomputed_human_intent_contract",
4351
- clarification: "",
4352
- managed_bots: managedBots,
4353
- };
4354
- }
4355
- if (hasHumanIntentContractSignals(humanIntent)) {
4356
- return {
4357
- decision: "no_responder",
4358
- selected_bot_usernames: [],
4359
- referenced_bot_usernames: triggerFacts.mentioned_bot_usernames,
4360
- confidence: "high",
4361
- reason_code: isCompleteHumanIntentContract(humanIntent)
4362
- ? "precomputed_human_intent_contract_no_responder"
4363
- : "incomplete_human_intent_contract",
4364
- clarification: "",
4365
- managed_bots: managedBots,
4366
- };
4367
- }
4368
4317
  if (!adjudicator) {
4369
4318
  const fallbackSelected = managedBots
4370
4319
  .filter((entry) => entry.trigger_eligible === true)
@@ -4422,6 +4371,90 @@ export async function resolveRunnerResponderAdjudication({
4422
4371
  runnerResponderAdjudicationPromises.set(cacheKey, promise);
4423
4372
  return promise;
4424
4373
  }
4374
+
4375
+ export function buildRunnerResponderAdjudicationFromHumanIntent({
4376
+ selectedRecord,
4377
+ managedBots = [],
4378
+ normalizedRoute = null,
4379
+ bot = null,
4380
+ deps = null,
4381
+ precomputedHumanIntent = null,
4382
+ }) {
4383
+ const humanIntent = safeObject(precomputedHumanIntent);
4384
+ if (!hasHumanIntentContractSignals(humanIntent)) {
4385
+ return null;
4386
+ }
4387
+ const fallbackManagedBots = ensureArray(managedBots).length
4388
+ ? managedBots
4389
+ : buildResponderAdjudicationManagedBots({
4390
+ selectedRecord,
4391
+ normalizedRoute,
4392
+ bot,
4393
+ deps,
4394
+ });
4395
+ const normalizedManagedBots = ensureArray(fallbackManagedBots)
4396
+ .map((entry) => safeObject(entry))
4397
+ .filter((entry) => normalizeMentionSelector(entry.username));
4398
+ const managedBotSelectors = new Set(
4399
+ normalizedManagedBots
4400
+ .map((entry) => normalizeMentionSelector(entry.username))
4401
+ .filter(Boolean),
4402
+ );
4403
+ const referencedBotUsernames = ensureArray(safeObject(selectedRecord?.parsedArchive).mentionUsernames)
4404
+ .map((value) => normalizeMentionSelector(value))
4405
+ .filter(Boolean);
4406
+ const contractInitialResponders = uniqueOrdered(
4407
+ ensureArray(humanIntent.initialResponderSelectors)
4408
+ .map((value) => normalizeMentionSelector(value))
4409
+ .filter((value) => value && managedBotSelectors.has(value)),
4410
+ );
4411
+ const contractAllowedResponders = uniqueOrdered(
4412
+ ensureArray(humanIntent.allowedResponderSelectors)
4413
+ .map((value) => normalizeMentionSelector(value))
4414
+ .filter((value) => value && managedBotSelectors.has(value)),
4415
+ );
4416
+ const contractParticipants = uniqueOrdered(
4417
+ ensureArray(humanIntent.participantSelectors)
4418
+ .map((value) => normalizeMentionSelector(value))
4419
+ .filter((value) => value && managedBotSelectors.has(value)),
4420
+ );
4421
+ const contractLeadBot = normalizeMentionSelector(humanIntent.leadBotSelector);
4422
+ const selectedFromContract = uniqueOrdered(
4423
+ (
4424
+ contractInitialResponders.length
4425
+ ? contractInitialResponders
4426
+ : contractAllowedResponders.length
4427
+ ? contractAllowedResponders
4428
+ : contractParticipants.length
4429
+ ? contractParticipants
4430
+ : contractLeadBot && managedBotSelectors.has(contractLeadBot)
4431
+ ? [contractLeadBot]
4432
+ : []
4433
+ ).filter(Boolean),
4434
+ );
4435
+ if (selectedFromContract.length > 0) {
4436
+ return {
4437
+ decision: selectedFromContract.length > 1 ? "multiple_responders" : "single_responder",
4438
+ selected_bot_usernames: selectedFromContract,
4439
+ referenced_bot_usernames: referencedBotUsernames,
4440
+ confidence: "high",
4441
+ reason_code: "precomputed_human_intent_contract",
4442
+ clarification: "",
4443
+ managed_bots: normalizedManagedBots,
4444
+ };
4445
+ }
4446
+ return {
4447
+ decision: "no_responder",
4448
+ selected_bot_usernames: [],
4449
+ referenced_bot_usernames: referencedBotUsernames,
4450
+ confidence: "high",
4451
+ reason_code: isCompleteHumanIntentContract(humanIntent)
4452
+ ? "precomputed_human_intent_contract_no_responder"
4453
+ : "incomplete_human_intent_contract",
4454
+ clarification: "",
4455
+ managed_bots: normalizedManagedBots,
4456
+ };
4457
+ }
4425
4458
 
4426
4459
  export function selectRunnerPendingWork({
4427
4460
  comments,
@@ -4511,7 +4544,6 @@ export async function processRunnerSelectedRecord({
4511
4544
  ? executionDeps.explainExecutionFailureWithAI
4512
4545
  : null;
4513
4546
  const normalizedPrecomputedHumanIntentContext = safeObject(precomputedHumanIntentContext);
4514
- const normalizedPrecomputedHumanIntent = safeObject(normalizedPrecomputedHumanIntentContext.humanIntent);
4515
4547
  const validateWorkspaceArtifacts = typeof executionDeps.validateWorkspaceArtifacts === "function"
4516
4548
  ? executionDeps.validateWorkspaceArtifacts
4517
4549
  : null;
@@ -4547,17 +4579,65 @@ export async function processRunnerSelectedRecord({
4547
4579
  },
4548
4580
  };
4549
4581
  }
4550
- const responderAdjudication = Object.keys(safeObject(precomputedResponderAdjudication)).length > 0
4551
- ? safeObject(precomputedResponderAdjudication)
4552
- : await resolveRunnerResponderAdjudication({
4582
+ const selectedRecordKind = String(safeObject(selectedRecord?.parsedArchive).kind || "").trim();
4583
+ const shouldResolveHumanIntentFirst = ["telegram_message", "telegram_edited_message"].includes(selectedRecordKind)
4584
+ && safeObject(selectedRecord?.parsedArchive).senderIsBot !== true;
4585
+ const resolvedPreAdjudicationHumanIntentContext = Object.keys(normalizedPrecomputedHumanIntentContext).length > 0
4586
+ ? normalizedPrecomputedHumanIntentContext
4587
+ : shouldResolveHumanIntentFirst
4588
+ ? await resolveHumanIntentContext({
4589
+ selectedRecord,
4590
+ normalizedRoute,
4591
+ bot,
4592
+ executionPlan,
4593
+ deps: executionDeps,
4594
+ persistedRequest: persistedHumanIntentRequest,
4595
+ })
4596
+ : null;
4597
+ if (resolvedPreAdjudicationHumanIntentContext?.contractNeedsResolution === true) {
4598
+ const reason = "human intent contract is incomplete and requires regeneration";
4599
+ saveRunnerRouteState(
4600
+ routeKey,
4601
+ buildRunnerRouteStateFromComment(selectedRecord, {
4602
+ last_action: "needs_contract",
4603
+ last_reason: reason,
4604
+ }),
4605
+ );
4606
+ return {
4607
+ kind: "skipped",
4608
+ skippedRecord: {
4609
+ id: selectedRecord.id,
4610
+ reason,
4611
+ messageID: intFromRawAllowZero(selectedRecord?.parsedArchive?.messageID, 0),
4612
+ },
4613
+ };
4614
+ }
4615
+ const normalizedPrecomputedHumanIntent = safeObject(
4616
+ resolvedPreAdjudicationHumanIntentContext?.humanIntent || normalizedPrecomputedHumanIntentContext.humanIntent,
4617
+ );
4618
+ const precomputedResponderSelection = buildRunnerResponderAdjudicationFromHumanIntent({
4619
+ selectedRecord,
4620
+ managedBots: buildResponderAdjudicationManagedBots({
4553
4621
  selectedRecord,
4554
- pendingOrdered,
4555
4622
  normalizedRoute,
4556
4623
  bot,
4557
- executionPlan,
4558
4624
  deps: executionDeps,
4559
- precomputedHumanIntent: normalizedPrecomputedHumanIntent,
4560
- });
4625
+ }),
4626
+ precomputedHumanIntent: normalizedPrecomputedHumanIntent,
4627
+ });
4628
+ const responderAdjudication = Object.keys(safeObject(precomputedResponderAdjudication)).length > 0
4629
+ ? safeObject(precomputedResponderAdjudication)
4630
+ : precomputedResponderSelection
4631
+ ? precomputedResponderSelection
4632
+ : await resolveRunnerResponderAdjudication({
4633
+ selectedRecord,
4634
+ pendingOrdered,
4635
+ normalizedRoute,
4636
+ bot,
4637
+ executionPlan,
4638
+ deps: executionDeps,
4639
+ precomputedHumanIntent: normalizedPrecomputedHumanIntent,
4640
+ });
4561
4641
  const selectedResponderSelectors = ensureArray(responderAdjudication.selected_bot_usernames)
4562
4642
  .map((value) => normalizeMentionSelector(value))
4563
4643
  .filter(Boolean);
@@ -4586,8 +4666,8 @@ export async function processRunnerSelectedRecord({
4586
4666
  };
4587
4667
  }
4588
4668
 
4589
- const humanIntentContext = Object.keys(normalizedPrecomputedHumanIntentContext).length > 0
4590
- ? normalizedPrecomputedHumanIntentContext
4669
+ const humanIntentContext = Object.keys(safeObject(resolvedPreAdjudicationHumanIntentContext)).length > 0
4670
+ ? safeObject(resolvedPreAdjudicationHumanIntentContext)
4591
4671
  : await resolveHumanIntentContext({
4592
4672
  selectedRecord,
4593
4673
  normalizedRoute,
@@ -12579,16 +12579,15 @@ export async function runSelftestRunnerScenarios(push, deps) {
12579
12579
  resolveConversationPeerBots: () => [],
12580
12580
  },
12581
12581
  });
12582
- push(
12583
- "runner_responder_adjudication_skips_unselected_bot",
12584
- processed.kind === "skipped"
12585
- && /selected_primary_addressee/i.test(String(processed.skippedRecord?.reason || ""))
12586
- && executionCalls === 0,
12587
- `kind=${String(processed.kind || "(none)")} reason=${String(processed.skippedRecord?.reason || "(none)")} execution_calls=${executionCalls}`,
12588
- );
12589
- } catch (err) {
12590
- push("runner_responder_adjudication_skips_unselected_bot", false, String(err?.message || err));
12591
- }
12582
+ push(
12583
+ "runner_contract_first_selection_overrides_responder_adjudicator_for_human_message",
12584
+ processed.kind === "replied"
12585
+ && executionCalls === 1,
12586
+ `kind=${String(processed.kind || "(none)")} reason=${String(processed.skippedRecord?.reason || "(none)")} execution_calls=${executionCalls}`,
12587
+ );
12588
+ } catch (err) {
12589
+ push("runner_contract_first_selection_overrides_responder_adjudicator_for_human_message", false, String(err?.message || err));
12590
+ }
12592
12591
 
12593
12592
  try {
12594
12593
  let executionCalls = 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "metheus-governance-mcp-cli",
3
- "version": "0.2.217",
3
+ "version": "0.2.219",
4
4
  "description": "Metheus Governance MCP CLI (setup + stdio proxy)",
5
5
  "type": "module",
6
6
  "files": [