metheus-governance-mcp-cli 0.2.214 → 0.2.215

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
@@ -2364,6 +2364,11 @@ function normalizeBotRunnerRequests(rawRequests, nowMs = Date.now()) {
2364
2364
  ),
2365
2365
  ai_reply_generated_at: firstNonEmptyString([entry.ai_reply_generated_at, entry.aiReplyGeneratedAt]),
2366
2366
  ai_reply_preview: String(entry.ai_reply_preview || entry.aiReplyPreview || "").trim(),
2367
+ response_contract_validation_status: String(entry.response_contract_validation_status || entry.responseContractValidationStatus || "").trim().toLowerCase(),
2368
+ response_contract_validation_reason: String(entry.response_contract_validation_reason || entry.responseContractValidationReason || "").trim(),
2369
+ response_contract_validation_targets: ensureArray(entry.response_contract_validation_targets || entry.responseContractValidationTargets)
2370
+ .map((value) => normalizeTelegramMentionUsername(value))
2371
+ .filter(Boolean),
2367
2372
  delivery_status: String(entry.delivery_status || entry.deliveryStatus || "").trim().toLowerCase(),
2368
2373
  archive_status: String(entry.archive_status || entry.archiveStatus || "").trim().toLowerCase(),
2369
2374
  transport_error: String(entry.transport_error || entry.transportError || "").trim(),
@@ -4495,6 +4500,9 @@ function markRunnerRequestLifecycle({
4495
4500
  aiReplyGenerated = false,
4496
4501
  aiReplyGeneratedAt = "",
4497
4502
  aiReplyPreview = "",
4503
+ responseContractValidationStatus = "",
4504
+ responseContractValidationReason = "",
4505
+ responseContractValidationTargets = [],
4498
4506
  deliveryStatus = "",
4499
4507
  archiveStatus = "",
4500
4508
  transportError = "",
@@ -4610,6 +4618,18 @@ function markRunnerRequestLifecycle({
4610
4618
  ? firstNonEmptyString([aiReplyGeneratedAt, existing.ai_reply_generated_at, nowISO])
4611
4619
  : String(existing.ai_reply_generated_at || "").trim(),
4612
4620
  ai_reply_preview: String(aiReplyPreview || existing.ai_reply_preview || "").trim(),
4621
+ response_contract_validation_status: String(
4622
+ responseContractValidationStatus || existing.response_contract_validation_status || "",
4623
+ ).trim().toLowerCase(),
4624
+ response_contract_validation_reason: String(
4625
+ responseContractValidationReason || existing.response_contract_validation_reason || "",
4626
+ ).trim(),
4627
+ response_contract_validation_targets: uniqueOrderedStrings(
4628
+ ensureArray(responseContractValidationTargets).length
4629
+ ? responseContractValidationTargets
4630
+ : existing.response_contract_validation_targets,
4631
+ normalizeTelegramMentionUsername,
4632
+ ),
4613
4633
  delivery_status: String(deliveryStatus || existing.delivery_status || "").trim().toLowerCase(),
4614
4634
  archive_status: String(archiveStatus || existing.archive_status || "").trim().toLowerCase(),
4615
4635
  transport_error: String(transportError || existing.transport_error || "").trim(),
@@ -8789,6 +8809,9 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
8789
8809
  aiReplyGenerated: processed.result?.ai_reply_generated === true,
8790
8810
  aiReplyGeneratedAt: String(processed.result?.ai_reply_generated_at || "").trim(),
8791
8811
  aiReplyPreview: String(processed.result?.ai_reply_preview || "").trim(),
8812
+ responseContractValidationStatus: String(processed.result?.response_contract_validation_status || "").trim(),
8813
+ responseContractValidationReason: String(processed.result?.response_contract_validation_reason || "").trim(),
8814
+ responseContractValidationTargets: ensureArray(processed.result?.response_contract_validation_targets),
8792
8815
  deliveryStatus: String(processed.result?.delivery_status || "").trim(),
8793
8816
  archiveStatus: String(processed.result?.archive_status || "").trim(),
8794
8817
  transportError: String(processed.result?.transport_error || "").trim(),
@@ -11204,6 +11227,9 @@ async function runRunnerStartResolvedRoutes(routes, flags, options = {}) {
11204
11227
  aiReplyGenerated: processed.result?.ai_reply_generated === true,
11205
11228
  aiReplyGeneratedAt: String(processed.result?.ai_reply_generated_at || "").trim(),
11206
11229
  aiReplyPreview: String(processed.result?.ai_reply_preview || "").trim(),
11230
+ responseContractValidationStatus: String(processed.result?.response_contract_validation_status || "").trim(),
11231
+ responseContractValidationReason: String(processed.result?.response_contract_validation_reason || "").trim(),
11232
+ responseContractValidationTargets: ensureArray(processed.result?.response_contract_validation_targets),
11207
11233
  deliveryStatus: String(processed.result?.delivery_status || "").trim(),
11208
11234
  archiveStatus: String(processed.result?.archive_status || "").trim(),
11209
11235
  transportError: String(processed.result?.transport_error || "").trim(),
@@ -5009,25 +5009,11 @@ export async function processRunnerSelectedRecord({
5009
5009
  const directHumanPeerMap = humanIntentContext?.peerMap instanceof Map
5010
5010
  ? humanIntentContext.peerMap
5011
5011
  : buildConversationPeerMap(bot, normalizedRoute, executionDeps);
5012
- const delegatedBotMentions = extractManagedPeerMentionSelectors(
5013
- String(aiResult.reply || "").trim(),
5014
- directHumanPeerMap,
5015
- currentBotSelector,
5016
- );
5017
5012
  const requiredDelegationTargets = uniqueOrdered(
5018
- (
5019
- delegatedBotMentions.length > 0
5020
- ? delegatedBotMentions
5021
- : requiresPeerDelegationContract
5022
- ? peerAllowedResponders
5023
- : []
5024
- )
5013
+ (requiresPeerDelegationContract ? peerAllowedResponders : [])
5025
5014
  .map((item) => normalizeMentionSelector(item))
5026
5015
  .filter(Boolean),
5027
5016
  );
5028
- if (delegatedBotMentions.length > 0) {
5029
- allowedActionableTypes = new Set(["delegation"]);
5030
- }
5031
5017
  if (requiresPeerDelegationContract) {
5032
5018
  allowedActionableTypes = new Set(["delegation"]);
5033
5019
  requiresActionableContract = true;
@@ -5037,97 +5023,24 @@ export async function processRunnerSelectedRecord({
5037
5023
  && executionContract.actionable === true
5038
5024
  && (!allowedActionableTypes.size || allowedActionableTypes.has(String(executionContract.type || "").trim().toLowerCase())),
5039
5025
  );
5040
- if (!requiresActionableContract && requiredDelegationTargets.length > 0) {
5041
- requiresActionableContract = true;
5042
- }
5043
- if (
5044
- !requiresActionableContract
5045
- && !hasValidActionableContract
5046
- && effectiveTriggerDecision.requiresDirectReply === true
5047
- && !conversationContext
5048
- && !safeObject(selectedRecord?.parsedArchive).senderIsBot
5049
- && typeof executionDeps?.auditDirectHumanReplyWithAI === "function"
5050
- ) {
5051
- const auditPeerMap = humanIntentContext?.peerMap instanceof Map
5052
- ? humanIntentContext.peerMap
5053
- : buildConversationPeerMap(bot, normalizedRoute, executionDeps);
5054
- try {
5055
- const audit = await executionDeps.auditDirectHumanReplyWithAI({
5056
- humanMessageText: String(safeObject(selectedRecord?.parsedArchive).body || "").trim(),
5057
- botReplyText: String(aiResult.reply || "").trim(),
5058
- currentBotUsername: String(bot?.username || bot?.name || "").trim(),
5059
- managedBots: buildConversationParticipantViews(Array.from(auditPeerMap.keys()), auditPeerMap),
5060
- workspaceDir: String(effectiveExecutionPlan.workspaceDir || process.cwd()).trim() || process.cwd(),
5061
- });
5062
- if (audit?.requires_actionable_contract === true && audit?.reply_satisfies_request !== true) {
5063
- requiresActionableContract = true;
5064
- }
5065
- } catch {}
5066
- }
5067
- if (requiresActionableContract && !hasValidActionableContract) {
5068
- const forcedContractPayload = {
5069
- ...aiPayload,
5070
- response_contract: {
5071
- ...effectiveResponseContractPayload,
5072
- allow_skip: false,
5073
- must_reply: true,
5074
- require_actionable_contract: true,
5075
- human_intent_mode: String(effectiveResponseContractPayload.human_intent_mode || "").trim(),
5076
- human_lead_bot: String(effectiveResponseContractPayload.human_lead_bot || "").trim(),
5077
- human_summary_bot: String(effectiveResponseContractPayload.human_summary_bot || "").trim(),
5078
- human_allowed_responders: ensureArray(effectiveResponseContractPayload.human_allowed_responders).length
5079
- ? ensureArray(effectiveResponseContractPayload.human_allowed_responders)
5080
- : uniqueOrdered([
5081
- currentBotSelector,
5082
- ...requiredDelegationTargets,
5083
- ].filter(Boolean)),
5084
- allow_bot_to_bot: requiredDelegationTargets.length > 0
5085
- || requiresPeerDelegationContract
5086
- || effectiveResponseContractPayload.human_intent_mode === "delegated_single_lead",
5087
- allowed_contract_types: requiredDelegationTargets.length > 0 || requiresPeerDelegationContract
5088
- ? ["delegation"]
5089
- : ensureArray(effectiveResponseContractPayload.allowed_contract_types).length
5090
- ? ensureArray(effectiveResponseContractPayload.allowed_contract_types)
5091
- : ["direct_result", "summary_request", "final_summary"],
5092
- required_delegation_targets: requiredDelegationTargets,
5093
- contract_hint: requiredDelegationTargets.length > 0
5094
- ? `Your previous reply mentioned ${requiredDelegationTargets.map((item) => `@${String(item || "").trim().replace(/^@+/, "")}`).join(", ")} without a delegation contract. Return contract.type=\"delegation\" with actionable=true, assignments for those exact bots, and matching next_responders.`
5095
- : "",
5096
- },
5026
+ const responseContractValidation = (() => {
5027
+ if (requiresActionableContract && !hasValidActionableContract) {
5028
+ return {
5029
+ ok: false,
5030
+ status: "missing_required_contract",
5031
+ reason: requiredDelegationTargets.length > 0
5032
+ ? `reply mentioned managed peer bot(s) ${requiredDelegationTargets.map((item) => `@${String(item || "").trim().replace(/^@+/, "")}`).join(", ")} without a matching delegation contract`
5033
+ : "reply did not produce a required execution contract",
5034
+ targets: requiredDelegationTargets,
5035
+ };
5036
+ }
5037
+ return {
5038
+ ok: true,
5039
+ status: "valid",
5040
+ reason: "",
5041
+ targets: requiredDelegationTargets,
5097
5042
  };
5098
- effectiveResponseContractPayload = safeObject(forcedContractPayload.response_contract);
5099
- allowedActionableTypes = new Set(
5100
- ensureArray(effectiveResponseContractPayload.allowed_contract_types)
5101
- .map((item) => String(item || "").trim().toLowerCase())
5102
- .filter(Boolean),
5103
- );
5104
- aiResult = await runRunnerAIExecution({
5105
- inputPayload: forcedContractPayload,
5106
- route: normalizedRoute,
5107
- destination,
5108
- executionPlan: effectiveExecutionPlan,
5109
- deps: executionDeps,
5110
- });
5111
- executionContract = conversationContext?.mode === "public_multi_bot"
5112
- ? normalizeConversationExecutionContract(
5113
- aiResult.contract,
5114
- {
5115
- allowedResponderSelectors: conversationContext.allowedResponderSelectors,
5116
- summaryBotUsername: conversationContext.summaryBotUsername,
5117
- },
5118
- { currentBotSelector, excludeCurrentTargetAssignments: true },
5119
- )
5120
- : normalizeResponseExecutionContract(
5121
- aiResult.contract,
5122
- effectiveResponseContractPayload,
5123
- { currentBotSelector },
5124
- );
5125
- hasValidActionableContract = Boolean(
5126
- executionContract
5127
- && executionContract.actionable === true
5128
- && (!allowedActionableTypes.size || allowedActionableTypes.has(String(executionContract.type || "").trim().toLowerCase())),
5129
- );
5130
- }
5043
+ })();
5131
5044
  directHumanResponseContract = mergeDirectHumanResponseContract({
5132
5045
  baseContract: directHumanResponseContract,
5133
5046
  responseContract: effectiveResponseContractPayload,
@@ -5153,56 +5066,6 @@ export async function processRunnerSelectedRecord({
5153
5066
  directHumanResponseContract,
5154
5067
  executionContract,
5155
5068
  });
5156
- if (requiresActionableContract) {
5157
- const validContract = hasValidActionableContract;
5158
- if (!validContract) {
5159
- const reason = requiredDelegationTargets.length > 0
5160
- ? `reply mentioned managed peer bot(s) ${requiredDelegationTargets.map((item) => `@${String(item || "").trim().replace(/^@+/, "")}`).join(", ")} without a required delegation contract`
5161
- : "reply did not produce an actionable execution contract";
5162
- const directHumanExecutionFailure = effectiveTriggerDecision.requiresDirectReply === true
5163
- && !conversationContext
5164
- && !safeObject(selectedRecord?.parsedArchive).senderIsBot;
5165
- saveRunnerRouteState(
5166
- routeKey,
5167
- buildRunnerRouteStateFromComment(selectedRecord, {
5168
- last_action: directHumanExecutionFailure
5169
- ? "execution_failed"
5170
- : conversationContext?.mode === "public_multi_bot"
5171
- ? "conversation_skipped"
5172
- : "policy_violation",
5173
- last_reason: reason,
5174
- last_conversation_id: String(conversationContext?.id || "").trim(),
5175
- last_conversation_stage: String(conversationContext?.stage || "").trim(),
5176
- last_workspace_dir: String(effectiveExecutionPlan.workspaceDir || "").trim(),
5177
- ...intentStatePatch,
5178
- }),
5179
- );
5180
- if (directHumanExecutionFailure) {
5181
- const failureDelivery = await maybeDeliverFailureReply(reason);
5182
- return {
5183
- kind: "error",
5184
- result: {
5185
- route_key: routeKey,
5186
- route_name: normalizedRoute.name,
5187
- outcome: "execution_failed",
5188
- detail: reason,
5189
- thread_id: archiveThread.threadID,
5190
- comment_id: selectedRecord.id,
5191
- trigger_kind: String(effectiveTriggerDecision.trigger || "").trim(),
5192
- failure_reply_sent: Boolean(failureDelivery),
5193
- },
5194
- };
5195
- }
5196
- return {
5197
- kind: "skipped",
5198
- skippedRecord: {
5199
- id: selectedRecord.id,
5200
- reason,
5201
- messageID: intFromRawAllowZero(selectedRecord?.parsedArchive?.messageID, 0),
5202
- },
5203
- };
5204
- }
5205
- }
5206
5069
  const normalizedExecutionContractType = String(executionContract?.type || "").trim().toLowerCase();
5207
5070
  const effectiveResolvedIntentType = normalizeHumanIntentType(
5208
5071
  directHumanResponseContract.intentType || resolvedIntentType,
@@ -5333,17 +5196,7 @@ export async function processRunnerSelectedRecord({
5333
5196
  },
5334
5197
  };
5335
5198
  }
5336
- if (
5337
- conversationContext?.mode === "public_multi_bot"
5338
- && String(conversationContext.intentMode || "").trim() === "delegated_single_lead"
5339
- && currentBotSelector
5340
- && currentBotSelector !== normalizeMentionSelector(conversationContext.leadBotUsername)
5341
- && (!executionContract || executionContract.actionable !== true)
5342
- ) {
5343
- executionContract = buildImplicitSummaryRequestContract(conversationContext, currentBotSelector);
5344
- }
5345
-
5346
- const replyToMessageID = aiResult.replyToMessageID > 0
5199
+ const replyToMessageID = aiResult.replyToMessageID > 0
5347
5200
  ? aiResult.replyToMessageID
5348
5201
  : intFromRawAllowZero(selectedRecord.parsedArchive?.messageID, 0);
5349
5202
  const sanitizedReplyText = sanitizeForcedDirectReplyText({
@@ -5469,6 +5322,9 @@ export async function processRunnerSelectedRecord({
5469
5322
  last_trigger: String(effectiveTriggerDecision.trigger || "").trim(),
5470
5323
  last_conversation_id: String(effectiveConversationContext?.id || "").trim(),
5471
5324
  last_conversation_stage: String(effectiveConversationContext?.stage || "").trim(),
5325
+ last_contract_validation_status: String(responseContractValidation.status || "").trim(),
5326
+ last_contract_validation_reason: String(responseContractValidation.reason || "").trim(),
5327
+ last_contract_validation_targets: ensureArray(responseContractValidation.targets),
5472
5328
  last_speaker_bot_username: normalizeMentionSelector(bot?.username || bot?.name),
5473
5329
  last_workspace_dir: String(effectiveExecutionPlan.workspaceDir || "").trim(),
5474
5330
  ...intentStatePatch,
@@ -5507,6 +5363,9 @@ export async function processRunnerSelectedRecord({
5507
5363
  archive_status: "not_attempted",
5508
5364
  transport_error: transportError,
5509
5365
  archive_error: "",
5366
+ response_contract_validation_status: String(responseContractValidation.status || "").trim(),
5367
+ response_contract_validation_reason: String(responseContractValidation.reason || "").trim(),
5368
+ response_contract_validation_targets: ensureArray(responseContractValidation.targets),
5510
5369
  reply_chars: String(sanitizedReplyText || "").length,
5511
5370
  execution_mode: effectiveExecutionPlan.mode,
5512
5371
  role_profile: effectiveExecutionPlan.roleProfileName,
@@ -5593,7 +5452,10 @@ export async function processRunnerSelectedRecord({
5593
5452
  last_reply_message_id: intFromRawAllowZero(
5594
5453
  safeObject(deliveryResult.delivery.body).result?.message_id ?? safeObject(deliveryResult.delivery.body).message_id,
5595
5454
  0,
5596
- ),
5455
+ ),
5456
+ last_contract_validation_status: String(responseContractValidation.status || "").trim(),
5457
+ last_contract_validation_reason: String(responseContractValidation.reason || "").trim(),
5458
+ last_contract_validation_targets: ensureArray(responseContractValidation.targets),
5597
5459
  last_trigger: String(effectiveTriggerDecision.trigger || "").trim(),
5598
5460
  last_reason: effectiveConversationContext?.mode === "public_multi_bot"
5599
5461
  ? [
@@ -5691,6 +5553,9 @@ export async function processRunnerSelectedRecord({
5691
5553
  ai_reply_generated: true,
5692
5554
  ai_reply_generated_at: aiReplyGeneratedAt,
5693
5555
  ai_reply_preview: aiReplyPreview,
5556
+ response_contract_validation_status: String(responseContractValidation.status || "").trim(),
5557
+ response_contract_validation_reason: String(responseContractValidation.reason || "").trim(),
5558
+ response_contract_validation_targets: ensureArray(responseContractValidation.targets),
5694
5559
  delivery_status: deliveryResult.delivery.dryRun ? "dry_run" : "delivered",
5695
5560
  execution_mode: effectiveExecutionPlan.mode,
5696
5561
  role_profile: effectiveExecutionPlan.roleProfileName,
@@ -4567,13 +4567,15 @@ export async function runSelftestRunnerScenarios(push, deps) {
4567
4567
  push(
4568
4568
  "direct_human_public_delegate_reply_is_upgraded_to_actionable_contract",
4569
4569
  processed.kind === "replied"
4570
- && aiCalls >= 1
4570
+ && aiCalls === 1
4571
4571
  && String(deliveredConversation[0]?.mode || "") === "public_multi_bot"
4572
4572
  && String(deliveredConversation[0]?.leadBotUsername || "") === "ryoai_bot"
4573
4573
  && Array.isArray(deliveredConversation[0]?.allowedResponderSelectors)
4574
4574
  && deliveredConversation[0].allowedResponderSelectors.includes("ryoai3_bot")
4575
- && String(deliveredConversation[0]?.executionContract?.type || "") === "delegation",
4576
- `kind=${String(processed.kind || "(none)")} ai_calls=${aiCalls} mode=${String(deliveredConversation[0]?.mode || "(none)")} contract=${String(deliveredConversation[0]?.executionContract?.type || "(none)")} required_targets=${JSON.stringify(safeObject(forcedContractPayload?.response_contract).required_delegation_targets || [])}`,
4575
+ && String(deliveredConversation[0]?.executionContract?.type || "") === "delegation"
4576
+ && String(processed.result?.response_contract_validation_status || "") === "valid"
4577
+ && ensureArray(processed.result?.response_contract_validation_targets).includes("ryoai3_bot"),
4578
+ `kind=${String(processed.kind || "(none)")} ai_calls=${aiCalls} mode=${String(deliveredConversation[0]?.mode || "(none)")} contract=${String(deliveredConversation[0]?.executionContract?.type || "(none)")} validation=${String(processed.result?.response_contract_validation_status || "(none)")} targets=${JSON.stringify(processed.result?.response_contract_validation_targets || [])}`,
4577
4579
  );
4578
4580
  } catch (err) {
4579
4581
  push("direct_human_public_delegate_reply_is_upgraded_to_actionable_contract", false, String(err?.message || err));
@@ -4715,17 +4717,18 @@ export async function runSelftestRunnerScenarios(push, deps) {
4715
4717
  ],
4716
4718
  },
4717
4719
  });
4718
- push(
4719
- "direct_human_public_delegate_repairs_lead_bot_selector_for_archive_contract",
4720
- processed.kind === "replied"
4721
- && aiCalls >= 1
4722
- && String(deliveredConversation[0]?.mode || "") === "public_multi_bot"
4723
- && String(deliveredConversation[0]?.leadBotUsername || "") === "ryoai_bot"
4724
- && Array.isArray(deliveredConversation[0]?.allowedResponderSelectors)
4725
- && deliveredConversation[0].allowedResponderSelectors.includes("ryoai3_bot")
4726
- && String(deliveredConversation[0]?.executionContract?.type || "") === "delegation",
4727
- `kind=${String(processed.kind || "(none)")} ai_calls=${aiCalls} lead=${String(deliveredConversation[0]?.leadBotUsername || "(none)")} mode=${String(deliveredConversation[0]?.mode || "(none)")}`,
4728
- );
4720
+ push(
4721
+ "direct_human_public_delegate_repairs_lead_bot_selector_for_archive_contract",
4722
+ processed.kind === "replied"
4723
+ && aiCalls === 1
4724
+ && String(deliveredConversation[0]?.mode || "") === "public_multi_bot"
4725
+ && String(deliveredConversation[0]?.leadBotUsername || "") === "ryoai_bot"
4726
+ && Array.isArray(deliveredConversation[0]?.allowedResponderSelectors)
4727
+ && deliveredConversation[0].allowedResponderSelectors.includes("ryoai3_bot")
4728
+ && String(deliveredConversation[0]?.executionContract?.type || "") === "delegation"
4729
+ && String(processed.result?.response_contract_validation_status || "") === "valid",
4730
+ `kind=${String(processed.kind || "(none)")} ai_calls=${aiCalls} lead=${String(deliveredConversation[0]?.leadBotUsername || "(none)")} mode=${String(deliveredConversation[0]?.mode || "(none)")} validation=${String(processed.result?.response_contract_validation_status || "(none)")}`,
4731
+ );
4729
4732
  } catch (err) {
4730
4733
  push("direct_human_public_delegate_repairs_lead_bot_selector_for_archive_contract", false, String(err?.message || err));
4731
4734
  }
@@ -4864,13 +4867,14 @@ export async function runSelftestRunnerScenarios(push, deps) {
4864
4867
  push(
4865
4868
  "direct_human_public_delegate_fallback_uses_response_allowed_responders",
4866
4869
  processed.kind === "replied"
4867
- && aiCalls >= 1
4870
+ && aiCalls === 1
4868
4871
  && String(deliveredConversation[0]?.mode || "") === "public_multi_bot"
4869
4872
  && Array.isArray(deliveredConversation[0]?.allowedResponderSelectors)
4870
4873
  && deliveredConversation[0].allowedResponderSelectors.includes("ryoai3_bot")
4871
- && String(deliveredConversation[0]?.executionContract?.type || "") === "delegation",
4872
- `kind=${String(processed.kind || "(none)")} ai_calls=${aiCalls} mode=${String(deliveredConversation[0]?.mode || "(none)")} allowed=${JSON.stringify(deliveredConversation[0]?.allowedResponderSelectors || [])} contract=${String(deliveredConversation[0]?.executionContract?.type || "(none)")}`,
4873
- );
4874
+ && String(deliveredConversation[0]?.executionContract?.type || "") === "delegation"
4875
+ && String(processed.result?.response_contract_validation_status || "") === "valid",
4876
+ `kind=${String(processed.kind || "(none)")} ai_calls=${aiCalls} mode=${String(deliveredConversation[0]?.mode || "(none)")} allowed=${JSON.stringify(deliveredConversation[0]?.allowedResponderSelectors || [])} contract=${String(deliveredConversation[0]?.executionContract?.type || "(none)")} validation=${String(processed.result?.response_contract_validation_status || "(none)")}`,
4877
+ );
4874
4878
  } catch (err) {
4875
4879
  push("direct_human_public_delegate_fallback_uses_response_allowed_responders", false, String(err?.message || err));
4876
4880
  }
@@ -5012,13 +5016,12 @@ export async function runSelftestRunnerScenarios(push, deps) {
5012
5016
  });
5013
5017
  push(
5014
5018
  "direct_human_public_peer_mention_rejects_summary_request_without_delegation",
5015
- processed.kind === "skipped"
5016
- && aiCalls >= 1
5017
- && deliveredConversation.length === 0
5018
- && ensureArray(safeObject(forcedContractPayload?.response_contract).required_delegation_targets).includes("ryoai3_bot")
5019
- && String(safeObject(forcedContractPayload?.response_contract).contract_hint || "").trim().length > 0
5020
- && String(processed.skippedRecord?.reason || "").includes("delegation contract"),
5021
- `kind=${String(processed.kind || "(none)")} ai_calls=${aiCalls} required_targets=${JSON.stringify(safeObject(forcedContractPayload?.response_contract).required_delegation_targets || [])} reason=${String(processed.skippedRecord?.reason || "(none)")}`,
5019
+ processed.kind === "replied"
5020
+ && aiCalls === 1
5021
+ && deliveredConversation.length === 1
5022
+ && String(processed.result?.response_contract_validation_status || "") === "missing_required_contract"
5023
+ && ensureArray(processed.result?.response_contract_validation_targets).includes("ryoai3_bot"),
5024
+ `kind=${String(processed.kind || "(none)")} ai_calls=${aiCalls} validation=${String(processed.result?.response_contract_validation_status || "(none)")} targets=${JSON.stringify(processed.result?.response_contract_validation_targets || [])}`,
5022
5025
  );
5023
5026
  } catch (err) {
5024
5027
  push("direct_human_public_peer_mention_rejects_summary_request_without_delegation", false, String(err?.message || err));
@@ -5152,12 +5155,10 @@ export async function runSelftestRunnerScenarios(push, deps) {
5152
5155
  });
5153
5156
  push(
5154
5157
  "delegated_single_lead_lead_opening_requires_delegation_contract_for_peer_followup",
5155
- processed.kind === "skipped"
5156
- && aiCalls === 2
5157
- && !String(deliveredText || "").trim()
5158
- && ensureArray(safeObject(forcedContractPayload?.response_contract).required_delegation_targets).includes("ryoai2_bot")
5159
- && ensureArray(safeObject(forcedContractPayload?.response_contract).required_delegation_targets).includes("ryoai3_bot")
5160
- && String(safeObject(forcedContractPayload?.response_contract).contract_hint || "").trim().length > 0,
5158
+ processed.kind === "replied"
5159
+ && aiCalls === 1
5160
+ && String(deliveredText || "").trim() === "I will analyze first and come back later."
5161
+ && !safeObject(forcedContractPayload?.response_contract).required_delegation_targets,
5161
5162
  `kind=${String(processed.kind || "(none)")} ai_calls=${aiCalls} reply=${String(deliveredText || "(none)")} required_targets=${JSON.stringify(safeObject(forcedContractPayload?.response_contract).required_delegation_targets || [])} hint=${String(safeObject(forcedContractPayload?.response_contract).contract_hint || "(none)")}`,
5162
5163
  );
5163
5164
  } catch (err) {
@@ -5284,26 +5285,26 @@ export async function runSelftestRunnerScenarios(push, deps) {
5284
5285
  ],
5285
5286
  },
5286
5287
  });
5287
- push(
5288
- "single_bot_human_work_request_requires_actionable_contract",
5289
- processed.kind === "error"
5290
- && aiCalls === 2
5291
- && deliveryCalls === 1
5292
- && String(processed.result?.outcome || "") === "execution_failed"
5293
- && /actionable execution contract/i.test(String(processed.result?.detail || ""))
5294
- && /could not complete this request/i.test(deliveredText),
5295
- `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)")}`,
5296
- );
5288
+ push(
5289
+ "single_bot_human_work_request_requires_actionable_contract",
5290
+ processed.kind === "replied"
5291
+ && aiCalls === 1
5292
+ && deliveryCalls === 1
5293
+ && String(processed.result?.outcome || "") === "dry_run"
5294
+ && deliveredText === "I will inspect the project first and come back later.",
5295
+ `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)")}`,
5296
+ );
5297
5297
  } catch (err) {
5298
5298
  push("single_bot_human_work_request_requires_actionable_contract", false, String(err?.message || err));
5299
5299
  }
5300
5300
 
5301
- try {
5302
- let aiCalls = 0;
5303
- let deliveryCalls = 0;
5304
- let deliveredText = "";
5305
- let capturedFailureFacts = null;
5306
- const processed = await processRunnerSelectedRecord({
5301
+ try {
5302
+ let aiCalls = 0;
5303
+ let deliveryCalls = 0;
5304
+ let deliveredText = "";
5305
+ let capturedFailureFacts = null;
5306
+ const workspaceDir = fs.mkdtempSync(path.join(os.tmpdir(), "metheus-runner-selftest-ai-failure-explainer-"));
5307
+ const processed = await processRunnerSelectedRecord({
5307
5308
  routeKey: "single-bot-human-work-request-ai-failure-explainer-key",
5308
5309
  normalizedRoute: normalizeRunnerRoute({
5309
5310
  name: "telegram-monitor-single-bot-human-work-request-ai-failure-explainer",
@@ -5368,7 +5369,7 @@ export async function runSelftestRunnerScenarios(push, deps) {
5368
5369
  permissionMode: "read_only",
5369
5370
  reasoningEffort: "low",
5370
5371
  },
5371
- workspaceDir: process.cwd(),
5372
+ workspaceDir,
5372
5373
  workspaceSource: "selftest",
5373
5374
  usedCommandFallback: false,
5374
5375
  },
@@ -5381,14 +5382,27 @@ export async function runSelftestRunnerScenarios(push, deps) {
5381
5382
  deps: {
5382
5383
  saveRunnerRouteState: () => {},
5383
5384
  startRunnerTypingHeartbeat: () => ({ async stop() {} }),
5384
- runRunnerAIExecution: async () => {
5385
- aiCalls += 1;
5386
- return {
5387
- skip: false,
5388
- reply: "I reviewed the request but did not produce a contract.",
5389
- contract: null,
5390
- };
5391
- },
5385
+ runRunnerAIExecution: async ({ inputPayload }) => {
5386
+ aiCalls += 1;
5387
+ const stepRole = String(inputPayload?.execution_step?.role || "").trim();
5388
+ if (stepRole === "monitor") {
5389
+ return {
5390
+ skip: false,
5391
+ reply: "Inspected the implementation guide request.",
5392
+ };
5393
+ }
5394
+ if (stepRole === "worker") {
5395
+ return {
5396
+ skip: false,
5397
+ reply: "Started the implementation guide update.",
5398
+ artifacts: [],
5399
+ };
5400
+ }
5401
+ return {
5402
+ skip: false,
5403
+ reply: "Preparing the implementation guide update.",
5404
+ };
5405
+ },
5392
5406
  explainExecutionFailureWithAI: ({ failureFacts }) => {
5393
5407
  capturedFailureFacts = safeObject(failureFacts);
5394
5408
  return {
@@ -5407,7 +5421,8 @@ export async function runSelftestRunnerScenarios(push, deps) {
5407
5421
  },
5408
5422
  serializeRunnerTriggerPolicy: (value) => value,
5409
5423
  serializeRunnerArchivePolicy: (value) => value,
5410
- buildRunnerExecutionDeps: () => ({
5424
+ buildRunnerExecutionDeps: () => ({
5425
+ validateWorkspaceArtifacts,
5411
5426
  analyzeHumanConversationIntentWithAI: async () => ({
5412
5427
  mode: "single_bot",
5413
5428
  lead_bot: "ryoai_bot",
@@ -5417,9 +5432,36 @@ export async function runSelftestRunnerScenarios(push, deps) {
5417
5432
  summary_bot: "",
5418
5433
  allow_bot_to_bot: false,
5419
5434
  reply_expectation: "actionable",
5420
- intent_type: "ctxpack_mutation",
5435
+ intent_type: "general_execution",
5421
5436
  }),
5422
- }),
5437
+ planRoleExecutionWithAI: async () => ({
5438
+ requiresExecution: true,
5439
+ summaryRole: "monitor",
5440
+ steps: [
5441
+ { role: "monitor", goal: "Inspect request" },
5442
+ { role: "worker", goal: "Update implementation guide", artifactsRequired: true },
5443
+ ],
5444
+ }),
5445
+ resolveRunnerExecutionPlanForRole: (_route, _bot, roleName) => ({
5446
+ mode: "role_profile",
5447
+ roleProfileName: String(roleName || "").trim(),
5448
+ roleProfile: {
5449
+ client: "sample",
5450
+ model: "",
5451
+ permissionMode: String(roleName || "").trim() === "worker" ? "workspace_write" : "read_only",
5452
+ reasoningEffort: "low",
5453
+ },
5454
+ workspaceDir,
5455
+ workspaceSource: "selftest",
5456
+ usedCommandFallback: false,
5457
+ }),
5458
+ loadBotRunnerConfig: () => ({
5459
+ roleProfiles: {},
5460
+ botBindings: {},
5461
+ routes: [],
5462
+ projectMappings: {},
5463
+ }),
5464
+ }),
5423
5465
  buildRunnerDeliveryDeps: () => ({}),
5424
5466
  buildRunnerRuntimeDeps: () => ({}),
5425
5467
  resolveConversationPeerBots: () => [
@@ -5433,8 +5475,8 @@ export async function runSelftestRunnerScenarios(push, deps) {
5433
5475
  && aiCalls >= 1
5434
5476
  && deliveryCalls === 1
5435
5477
  && deliveredText === "AI failure summary"
5436
- && String(capturedFailureFacts?.error_type || "") === "missing_actionable_contract"
5437
- && String(capturedFailureFacts?.stage || "") === "execution_contract",
5478
+ && String(capturedFailureFacts?.error_type || "") === "artifact_validation_failed"
5479
+ && String(capturedFailureFacts?.stage || "") === "artifact_validation",
5438
5480
  `kind=${String(processed.kind || "(none)")} outcome=${String(processed.result?.outcome || "(none)")} ai_calls=${aiCalls} delivery_calls=${deliveryCalls} delivered=${deliveredText} failure_type=${String(capturedFailureFacts?.error_type || "(none)")} stage=${String(capturedFailureFacts?.stage || "(none)")}`,
5439
5481
  );
5440
5482
  } catch (err) {
@@ -5694,17 +5736,17 @@ export async function runSelftestRunnerScenarios(push, deps) {
5694
5736
  ],
5695
5737
  },
5696
5738
  });
5697
- push(
5698
- "single_bot_human_request_guardrail_audit_upgrades_to_actionable",
5699
- processed.kind === "error"
5700
- && aiCalls === 2
5701
- && auditCalls === 1
5702
- && deliveryCalls === 1
5703
- && String(processed.result?.outcome || "") === "execution_failed"
5704
- && /actionable execution contract/i.test(String(processed.result?.detail || ""))
5705
- && /could not complete this request/i.test(deliveredText),
5706
- `kind=${String(processed.kind || "(none)")} outcome=${String(processed.result?.outcome || "(none)")} ai_calls=${aiCalls} audit_calls=${auditCalls} delivery_calls=${deliveryCalls} delivered=${deliveredText} reason=${String(processed.result?.detail || "(none)")}`,
5707
- );
5739
+ push(
5740
+ "single_bot_human_request_guardrail_audit_upgrades_to_actionable",
5741
+ processed.kind === "replied"
5742
+ && aiCalls === 1
5743
+ && auditCalls === 0
5744
+ && deliveryCalls === 1
5745
+ && String(processed.result?.outcome || "") === "dry_run"
5746
+ && String(processed.result?.response_contract_validation_status || "") === "valid"
5747
+ && String(deliveredText || "").trim().length > 0,
5748
+ `kind=${String(processed.kind || "(none)")} outcome=${String(processed.result?.outcome || "(none)")} ai_calls=${aiCalls} audit_calls=${auditCalls} delivery_calls=${deliveryCalls} delivered=${deliveredText} validation=${String(processed.result?.response_contract_validation_status || "(none)")}`,
5749
+ );
5708
5750
  } catch (err) {
5709
5751
  push("single_bot_human_request_guardrail_audit_upgrades_to_actionable", false, String(err?.message || err));
5710
5752
  }
@@ -9305,13 +9347,13 @@ export async function runSelftestRunnerScenarios(push, deps) {
9305
9347
  ],
9306
9348
  },
9307
9349
  });
9308
- push(
9309
- "delegated_single_lead_peer_to_peer_reply_reaches_ai_decision",
9310
- processed.kind === "replied"
9311
- && aiCalls === 1
9312
- && String(processed.result?.execution_contract_type || "") === "summary_request",
9313
- `kind=${String(processed.kind || "(none)")} ai_calls=${aiCalls} contract=${String(processed.result?.execution_contract_type || "(none)")} reason=${String(processed.skippedRecord?.reason || "(none)")}`,
9314
- );
9350
+ push(
9351
+ "delegated_single_lead_peer_to_peer_reply_reaches_ai_decision",
9352
+ processed.kind === "replied"
9353
+ && aiCalls === 1
9354
+ && !processed.skippedRecord,
9355
+ `kind=${String(processed.kind || "(none)")} ai_calls=${aiCalls} contract=${String(processed.result?.execution_contract_type || "(none)")} reason=${String(processed.skippedRecord?.reason || "(none)")}`,
9356
+ );
9315
9357
  } catch (err) {
9316
9358
  push("delegated_single_lead_peer_to_peer_reply_reaches_ai_decision", false, String(err?.message || err));
9317
9359
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "metheus-governance-mcp-cli",
3
- "version": "0.2.214",
3
+ "version": "0.2.215",
4
4
  "description": "Metheus Governance MCP CLI (setup + stdio proxy)",
5
5
  "type": "module",
6
6
  "files": [