metheus-governance-mcp-cli 0.2.218 → 0.2.220

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,31 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
8287
8288
  executionPlan,
8288
8289
  deps: routingExecutionDeps,
8289
8290
  });
8290
- const adjudication = await resolveRunnerResponderAdjudication({
8291
+ if (safeObject(sharedHumanIntentContext).contractNeedsResolution === true) {
8292
+ const reason = "human intent contract is incomplete and requires regeneration";
8293
+ saveRunnerRouteState(
8294
+ routeKey,
8295
+ buildRunnerRouteStateFromComment(selectedRecord, {
8296
+ last_action: "needs_contract",
8297
+ last_reason: reason,
8298
+ last_trigger: "human_intent_contract",
8299
+ }),
8300
+ );
8301
+ skippedRecords.push({
8302
+ id: selectedRecord.id,
8303
+ reason,
8304
+ messageID: intFromRawAllowZero(selectedRecord?.parsedArchive?.messageID, 0),
8305
+ });
8306
+ continue;
8307
+ }
8308
+ const precomputedAdjudication = buildRunnerResponderAdjudicationFromHumanIntent({
8309
+ selectedRecord,
8310
+ normalizedRoute,
8311
+ bot,
8312
+ deps: routingExecutionDeps,
8313
+ precomputedHumanIntent: safeObject(sharedHumanIntentContext).humanIntent || null,
8314
+ });
8315
+ const adjudication = precomputedAdjudication || await resolveRunnerResponderAdjudication({
8291
8316
  selectedRecord,
8292
8317
  pendingOrdered: pending.ordered,
8293
8318
  normalizedRoute,
@@ -8540,7 +8565,31 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
8540
8565
  executionPlan,
8541
8566
  deps: routingExecutionDeps,
8542
8567
  });
8543
- const inlineAdjudication = await resolveRunnerResponderAdjudication({
8568
+ if (safeObject(sharedHumanIntentContext).contractNeedsResolution === true) {
8569
+ const reason = "human intent contract is incomplete and requires regeneration";
8570
+ saveRunnerRouteState(
8571
+ routeKey,
8572
+ buildRunnerRouteStateFromComment(selectedRecord, {
8573
+ last_action: "needs_contract",
8574
+ last_reason: reason,
8575
+ last_trigger: "human_intent_contract",
8576
+ }),
8577
+ );
8578
+ skippedRecords.push({
8579
+ id: selectedRecord.id,
8580
+ reason,
8581
+ messageID: intFromRawAllowZero(selectedRecord?.parsedArchive?.messageID, 0),
8582
+ });
8583
+ continue;
8584
+ }
8585
+ const precomputedInlineAdjudication = buildRunnerResponderAdjudicationFromHumanIntent({
8586
+ selectedRecord,
8587
+ normalizedRoute,
8588
+ bot,
8589
+ deps: routingExecutionDeps,
8590
+ precomputedHumanIntent: safeObject(sharedHumanIntentContext).humanIntent || null,
8591
+ });
8592
+ const inlineAdjudication = precomputedInlineAdjudication || await resolveRunnerResponderAdjudication({
8544
8593
  selectedRecord,
8545
8594
  pendingOrdered: pending.ordered,
8546
8595
  normalizedRoute,
@@ -1310,6 +1310,7 @@ function buildDirectHumanResponseContract({
1310
1310
  conversationContext,
1311
1311
  currentBotSelector,
1312
1312
  }) {
1313
+ void currentBotSelector;
1313
1314
  const humanIntent = safeObject(humanIntentContext?.humanIntent);
1314
1315
  const conversation = safeObject(conversationContext);
1315
1316
  const preferConversationContract = Boolean(
@@ -1320,8 +1321,7 @@ function buildDirectHumanResponseContract({
1320
1321
  || String(conversation.summaryBotUsername || "").trim()
1321
1322
  || String(conversation.replyExpectation || "").trim(),
1322
1323
  );
1323
- const source = preferConversationContract ? conversation : humanIntent;
1324
- const secondary = preferConversationContract ? humanIntent : conversation;
1324
+ const source = safeObject(preferConversationContract ? conversation : humanIntent);
1325
1325
  const normalizedAllowedResponderSelectors = uniqueOrdered(
1326
1326
  ensureArray(source.allowedResponderSelectors)
1327
1327
  .map((item) => normalizeMentionSelector(item))
@@ -1332,35 +1332,29 @@ function buildDirectHumanResponseContract({
1332
1332
  .map((item) => normalizeMentionSelector(item))
1333
1333
  .filter(Boolean),
1334
1334
  );
1335
- const intentMode = String(source.intentMode || secondary.intentMode || "").trim();
1336
- const allowBotToBot = source.allowBotToBot === true
1337
- || (source.allowBotToBot !== false && secondary.allowBotToBot === true);
1335
+ const intentMode = String(source.intentMode || "").trim();
1336
+ const allowBotToBot = source.allowBotToBot === true;
1338
1337
  const leadBotSelector = normalizeMentionSelector(
1339
- source.leadBotUsername || source.leadBotSelector || secondary.leadBotUsername || secondary.leadBotSelector,
1338
+ source.leadBotUsername || source.leadBotSelector,
1340
1339
  );
1341
1340
  const summaryBotSelector = normalizeMentionSelector(
1342
- source.summaryBotUsername || source.summaryBotSelector || secondary.summaryBotUsername || secondary.summaryBotSelector,
1341
+ source.summaryBotUsername || source.summaryBotSelector,
1343
1342
  );
1344
1343
  const replyExpectation = normalizeReplyExpectation(
1345
- source.replyExpectation || secondary.replyExpectation,
1344
+ source.replyExpectation,
1346
1345
  "",
1347
1346
  );
1348
1347
  const intentType = normalizeHumanIntentType(
1349
- source.intentType || secondary.intentType,
1348
+ source.intentType,
1350
1349
  "",
1351
1350
  );
1352
1351
  const allowedContractTypes = uniqueOrdered(
1353
- ensureArray(source.allowedContractTypes || secondary.allowedContractTypes)
1352
+ ensureArray(source.allowedContractTypes)
1354
1353
  .map((item) => String(item || "").trim().toLowerCase())
1355
1354
  .filter(Boolean),
1356
1355
  );
1357
1356
  const requiresActionableContract = source.requiresActionableContract === true
1358
- || source.require_actionable_contract === true
1359
- || (
1360
- source.requiresActionableContract !== false
1361
- && source.require_actionable_contract !== false
1362
- && (secondary.requiresActionableContract === true || secondary.require_actionable_contract === true)
1363
- );
1357
+ || source.require_actionable_contract === true;
1364
1358
  return {
1365
1359
  intentMode,
1366
1360
  allowBotToBot,
@@ -4285,17 +4279,20 @@ export async function resolveRunnerResponderAdjudication({
4285
4279
  ? deps.adjudicateRunnerRespondersWithAI
4286
4280
  : null;
4287
4281
  const promise = (async () => {
4288
- const managedBots = buildResponderAdjudicationManagedBots({
4282
+ const managedBots = buildResponderAdjudicationManagedBots({
4289
4283
  selectedRecord,
4290
4284
  normalizedRoute,
4291
4285
  bot,
4292
4286
  deps,
4293
4287
  });
4294
- const managedBotSelectors = new Set(
4295
- managedBots
4296
- .map((entry) => normalizeMentionSelector(entry.username))
4297
- .filter(Boolean),
4298
- );
4288
+ const contractAdjudication = buildRunnerResponderAdjudicationFromHumanIntent({
4289
+ selectedRecord,
4290
+ managedBots,
4291
+ precomputedHumanIntent,
4292
+ });
4293
+ if (contractAdjudication) {
4294
+ return contractAdjudication;
4295
+ }
4299
4296
  const triggerFacts = {
4300
4297
  message_kind: String(safeObject(selectedRecord?.parsedArchive).kind || "").trim(),
4301
4298
  chat_type: String(safeObject(selectedRecord?.parsedArchive).chatType || "").trim(),
@@ -4311,60 +4308,6 @@ export async function resolveRunnerResponderAdjudication({
4311
4308
  trigger_reason: String(entry.trigger_reason || "").trim(),
4312
4309
  })),
4313
4310
  };
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
4311
  if (!adjudicator) {
4369
4312
  const fallbackSelected = managedBots
4370
4313
  .filter((entry) => entry.trigger_eligible === true)
@@ -4422,6 +4365,90 @@ export async function resolveRunnerResponderAdjudication({
4422
4365
  runnerResponderAdjudicationPromises.set(cacheKey, promise);
4423
4366
  return promise;
4424
4367
  }
4368
+
4369
+ export function buildRunnerResponderAdjudicationFromHumanIntent({
4370
+ selectedRecord,
4371
+ managedBots = [],
4372
+ normalizedRoute = null,
4373
+ bot = null,
4374
+ deps = null,
4375
+ precomputedHumanIntent = null,
4376
+ }) {
4377
+ const humanIntent = safeObject(precomputedHumanIntent);
4378
+ if (!hasHumanIntentContractSignals(humanIntent)) {
4379
+ return null;
4380
+ }
4381
+ const fallbackManagedBots = ensureArray(managedBots).length
4382
+ ? managedBots
4383
+ : buildResponderAdjudicationManagedBots({
4384
+ selectedRecord,
4385
+ normalizedRoute,
4386
+ bot,
4387
+ deps,
4388
+ });
4389
+ const normalizedManagedBots = ensureArray(fallbackManagedBots)
4390
+ .map((entry) => safeObject(entry))
4391
+ .filter((entry) => normalizeMentionSelector(entry.username));
4392
+ const managedBotSelectors = new Set(
4393
+ normalizedManagedBots
4394
+ .map((entry) => normalizeMentionSelector(entry.username))
4395
+ .filter(Boolean),
4396
+ );
4397
+ const referencedBotUsernames = ensureArray(safeObject(selectedRecord?.parsedArchive).mentionUsernames)
4398
+ .map((value) => normalizeMentionSelector(value))
4399
+ .filter(Boolean);
4400
+ const contractInitialResponders = uniqueOrdered(
4401
+ ensureArray(humanIntent.initialResponderSelectors)
4402
+ .map((value) => normalizeMentionSelector(value))
4403
+ .filter((value) => value && managedBotSelectors.has(value)),
4404
+ );
4405
+ const contractAllowedResponders = uniqueOrdered(
4406
+ ensureArray(humanIntent.allowedResponderSelectors)
4407
+ .map((value) => normalizeMentionSelector(value))
4408
+ .filter((value) => value && managedBotSelectors.has(value)),
4409
+ );
4410
+ const contractParticipants = uniqueOrdered(
4411
+ ensureArray(humanIntent.participantSelectors)
4412
+ .map((value) => normalizeMentionSelector(value))
4413
+ .filter((value) => value && managedBotSelectors.has(value)),
4414
+ );
4415
+ const contractLeadBot = normalizeMentionSelector(humanIntent.leadBotSelector);
4416
+ const selectedFromContract = uniqueOrdered(
4417
+ (
4418
+ contractInitialResponders.length
4419
+ ? contractInitialResponders
4420
+ : contractAllowedResponders.length
4421
+ ? contractAllowedResponders
4422
+ : contractParticipants.length
4423
+ ? contractParticipants
4424
+ : contractLeadBot && managedBotSelectors.has(contractLeadBot)
4425
+ ? [contractLeadBot]
4426
+ : []
4427
+ ).filter(Boolean),
4428
+ );
4429
+ if (selectedFromContract.length > 0) {
4430
+ return {
4431
+ decision: selectedFromContract.length > 1 ? "multiple_responders" : "single_responder",
4432
+ selected_bot_usernames: selectedFromContract,
4433
+ referenced_bot_usernames: referencedBotUsernames,
4434
+ confidence: "high",
4435
+ reason_code: "precomputed_human_intent_contract",
4436
+ clarification: "",
4437
+ managed_bots: normalizedManagedBots,
4438
+ };
4439
+ }
4440
+ return {
4441
+ decision: "no_responder",
4442
+ selected_bot_usernames: [],
4443
+ referenced_bot_usernames: referencedBotUsernames,
4444
+ confidence: "high",
4445
+ reason_code: isCompleteHumanIntentContract(humanIntent)
4446
+ ? "precomputed_human_intent_contract_no_responder"
4447
+ : "incomplete_human_intent_contract",
4448
+ clarification: "",
4449
+ managed_bots: normalizedManagedBots,
4450
+ };
4451
+ }
4425
4452
 
4426
4453
  export function selectRunnerPendingWork({
4427
4454
  comments,
@@ -4582,17 +4609,29 @@ export async function processRunnerSelectedRecord({
4582
4609
  const normalizedPrecomputedHumanIntent = safeObject(
4583
4610
  resolvedPreAdjudicationHumanIntentContext?.humanIntent || normalizedPrecomputedHumanIntentContext.humanIntent,
4584
4611
  );
4585
- const responderAdjudication = Object.keys(safeObject(precomputedResponderAdjudication)).length > 0
4586
- ? safeObject(precomputedResponderAdjudication)
4587
- : await resolveRunnerResponderAdjudication({
4612
+ const precomputedResponderSelection = buildRunnerResponderAdjudicationFromHumanIntent({
4613
+ selectedRecord,
4614
+ managedBots: buildResponderAdjudicationManagedBots({
4588
4615
  selectedRecord,
4589
- pendingOrdered,
4590
4616
  normalizedRoute,
4591
4617
  bot,
4592
- executionPlan,
4593
4618
  deps: executionDeps,
4594
- precomputedHumanIntent: normalizedPrecomputedHumanIntent,
4595
- });
4619
+ }),
4620
+ precomputedHumanIntent: normalizedPrecomputedHumanIntent,
4621
+ });
4622
+ const responderAdjudication = Object.keys(safeObject(precomputedResponderAdjudication)).length > 0
4623
+ ? safeObject(precomputedResponderAdjudication)
4624
+ : precomputedResponderSelection
4625
+ ? precomputedResponderSelection
4626
+ : await resolveRunnerResponderAdjudication({
4627
+ selectedRecord,
4628
+ pendingOrdered,
4629
+ normalizedRoute,
4630
+ bot,
4631
+ executionPlan,
4632
+ deps: executionDeps,
4633
+ precomputedHumanIntent: normalizedPrecomputedHumanIntent,
4634
+ });
4596
4635
  const selectedResponderSelectors = ensureArray(responderAdjudication.selected_bot_usernames)
4597
4636
  .map((value) => normalizeMentionSelector(value))
4598
4637
  .filter(Boolean);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "metheus-governance-mcp-cli",
3
- "version": "0.2.218",
3
+ "version": "0.2.220",
4
4
  "description": "Metheus Governance MCP CLI (setup + stdio proxy)",
5
5
  "type": "module",
6
6
  "files": [