metheus-governance-mcp-cli 0.2.208 → 0.2.209
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 +161 -47
- package/lib/local-ai-adapters.mjs +13 -0
- package/lib/runner-orchestration.mjs +287 -138
- package/lib/runner-trigger.mjs +8 -2
- package/lib/selftest-runner-scenarios.mjs +12320 -12209
- package/package.json +1 -1
package/cli.mjs
CHANGED
|
@@ -2634,7 +2634,8 @@ function resolveRunnerRequestClaimIntent({
|
|
|
2634
2634
|
if (explicitIntent) {
|
|
2635
2635
|
return explicitIntent;
|
|
2636
2636
|
}
|
|
2637
|
-
|
|
2637
|
+
const inferredIntent = inferRunnerRequestClaimIntent(selectedRecord);
|
|
2638
|
+
return inferredIntent === "status_query" ? inferredIntent : "";
|
|
2638
2639
|
}
|
|
2639
2640
|
|
|
2640
2641
|
function buildSyntheticReplyChainConversationID(normalizedRoute, chatID, anchorMessageID) {
|
|
@@ -3339,8 +3340,6 @@ async function claimRunnerRequestForHumanComment({
|
|
|
3339
3340
|
).trim();
|
|
3340
3341
|
const preferredNormalizedIntent = String(
|
|
3341
3342
|
normalizedSharedHumanIntent.intentType
|
|
3342
|
-
|| sharedConversationSource.normalized_intent
|
|
3343
|
-
|| referencedRequest.normalized_intent
|
|
3344
3343
|
|| resolvedNormalizedIntent
|
|
3345
3344
|
|| "",
|
|
3346
3345
|
).trim().toLowerCase();
|
|
@@ -3381,50 +3380,70 @@ async function claimRunnerRequestForHumanComment({
|
|
|
3381
3380
|
conversation_id: resolvedConversationID,
|
|
3382
3381
|
selected_bot_usernames: uniqueOrderedStrings(selectedBotUsernames, normalizeTelegramMentionUsername),
|
|
3383
3382
|
conversation_intent_mode: String(
|
|
3384
|
-
|
|
3383
|
+
normalizedSharedHumanIntent.intentMode
|
|
3384
|
+
|| existing.conversation_intent_mode
|
|
3385
|
+
|| sharedConversationSource.conversation_intent_mode
|
|
3386
|
+
|| referencedRequest.conversation_intent_mode
|
|
3387
|
+
|| "",
|
|
3385
3388
|
).trim().toLowerCase(),
|
|
3386
3389
|
conversation_lead_bot: normalizeTelegramMentionUsername(
|
|
3387
|
-
|
|
3390
|
+
normalizedSharedHumanIntent.leadBotSelector
|
|
3391
|
+
|| existing.conversation_lead_bot
|
|
3392
|
+
|| sharedConversationSource.conversation_lead_bot
|
|
3393
|
+
|| referencedRequest.conversation_lead_bot,
|
|
3388
3394
|
),
|
|
3389
3395
|
conversation_summary_bot: normalizeTelegramMentionUsername(
|
|
3390
|
-
|
|
3396
|
+
normalizedSharedHumanIntent.summaryBotSelector
|
|
3397
|
+
|| existing.conversation_summary_bot
|
|
3398
|
+
|| sharedConversationSource.conversation_summary_bot
|
|
3399
|
+
|| referencedRequest.conversation_summary_bot,
|
|
3391
3400
|
),
|
|
3392
3401
|
conversation_participants: uniqueOrderedStrings(
|
|
3393
|
-
ensureArray(
|
|
3394
|
-
?
|
|
3395
|
-
: ensureArray(
|
|
3396
|
-
?
|
|
3397
|
-
: ensureArray(
|
|
3398
|
-
?
|
|
3399
|
-
:
|
|
3402
|
+
ensureArray(normalizedSharedHumanIntent.participantSelectors).length
|
|
3403
|
+
? normalizedSharedHumanIntent.participantSelectors
|
|
3404
|
+
: ensureArray(existing.conversation_participants).length
|
|
3405
|
+
? existing.conversation_participants
|
|
3406
|
+
: ensureArray(sharedConversationSource.conversation_participants).length
|
|
3407
|
+
? sharedConversationSource.conversation_participants
|
|
3408
|
+
: ensureArray(referencedRequest.conversation_participants).length
|
|
3409
|
+
? referencedRequest.conversation_participants
|
|
3410
|
+
: [],
|
|
3400
3411
|
normalizeTelegramMentionUsername,
|
|
3401
3412
|
),
|
|
3402
3413
|
conversation_initial_responders: uniqueOrderedStrings(
|
|
3403
|
-
ensureArray(
|
|
3404
|
-
?
|
|
3405
|
-
: ensureArray(
|
|
3406
|
-
?
|
|
3407
|
-
: ensureArray(
|
|
3408
|
-
?
|
|
3409
|
-
:
|
|
3414
|
+
ensureArray(normalizedSharedHumanIntent.initialResponderSelectors).length
|
|
3415
|
+
? normalizedSharedHumanIntent.initialResponderSelectors
|
|
3416
|
+
: ensureArray(existing.conversation_initial_responders).length
|
|
3417
|
+
? existing.conversation_initial_responders
|
|
3418
|
+
: ensureArray(sharedConversationSource.conversation_initial_responders).length
|
|
3419
|
+
? sharedConversationSource.conversation_initial_responders
|
|
3420
|
+
: ensureArray(referencedRequest.conversation_initial_responders).length
|
|
3421
|
+
? referencedRequest.conversation_initial_responders
|
|
3422
|
+
: [],
|
|
3410
3423
|
normalizeTelegramMentionUsername,
|
|
3411
3424
|
),
|
|
3412
3425
|
conversation_allowed_responders: uniqueOrderedStrings(
|
|
3413
|
-
ensureArray(
|
|
3414
|
-
?
|
|
3415
|
-
: ensureArray(
|
|
3416
|
-
?
|
|
3417
|
-
: ensureArray(
|
|
3418
|
-
?
|
|
3419
|
-
:
|
|
3426
|
+
ensureArray(normalizedSharedHumanIntent.allowedResponderSelectors).length
|
|
3427
|
+
? normalizedSharedHumanIntent.allowedResponderSelectors
|
|
3428
|
+
: ensureArray(existing.conversation_allowed_responders).length
|
|
3429
|
+
? existing.conversation_allowed_responders
|
|
3430
|
+
: ensureArray(sharedConversationSource.conversation_allowed_responders).length
|
|
3431
|
+
? sharedConversationSource.conversation_allowed_responders
|
|
3432
|
+
: ensureArray(referencedRequest.conversation_allowed_responders).length
|
|
3433
|
+
? referencedRequest.conversation_allowed_responders
|
|
3434
|
+
: [],
|
|
3420
3435
|
normalizeTelegramMentionUsername,
|
|
3421
3436
|
),
|
|
3422
|
-
conversation_allow_bot_to_bot:
|
|
3437
|
+
conversation_allow_bot_to_bot: normalizedSharedHumanIntent.allowBotToBot === true
|
|
3438
|
+
|| existing.conversation_allow_bot_to_bot === true
|
|
3423
3439
|
|| sharedConversationSource.conversation_allow_bot_to_bot === true
|
|
3424
|
-
|| referencedRequest.conversation_allow_bot_to_bot === true
|
|
3425
|
-
|| normalizedSharedHumanIntent.allowBotToBot === true,
|
|
3440
|
+
|| referencedRequest.conversation_allow_bot_to_bot === true,
|
|
3426
3441
|
conversation_reply_expectation: String(
|
|
3427
|
-
|
|
3442
|
+
normalizedSharedHumanIntent.replyExpectation
|
|
3443
|
+
|| existing.conversation_reply_expectation
|
|
3444
|
+
|| sharedConversationSource.conversation_reply_expectation
|
|
3445
|
+
|| referencedRequest.conversation_reply_expectation
|
|
3446
|
+
|| "",
|
|
3428
3447
|
).trim().toLowerCase(),
|
|
3429
3448
|
execution_contract_type: String(
|
|
3430
3449
|
existing.execution_contract_type || sharedConversationSource.execution_contract_type || referencedRequest.execution_contract_type || "",
|
|
@@ -3450,7 +3469,7 @@ async function claimRunnerRequestForHumanComment({
|
|
|
3450
3469
|
: [],
|
|
3451
3470
|
normalizeTelegramMentionUsername,
|
|
3452
3471
|
),
|
|
3453
|
-
normalized_intent: preferredNormalizedIntent,
|
|
3472
|
+
normalized_intent: String(preferredNormalizedIntent || existing.normalized_intent || "").trim().toLowerCase(),
|
|
3454
3473
|
status: "claimed",
|
|
3455
3474
|
claimed_by_route: String(routeKey || "").trim(),
|
|
3456
3475
|
claimed_at: firstNonEmptyString([existing.claimed_at, nowISO]) || nowISO,
|
|
@@ -3501,6 +3520,89 @@ function isActionableRunnerRequestIntent(rawIntent) {
|
|
|
3501
3520
|
return Boolean(normalizedIntent) && !isInformationalRunnerRequestIntent(normalizedIntent);
|
|
3502
3521
|
}
|
|
3503
3522
|
|
|
3523
|
+
function runnerRequestHasConversationContract(requestRaw) {
|
|
3524
|
+
const request = safeObject(requestRaw);
|
|
3525
|
+
return Boolean(
|
|
3526
|
+
String(request.conversation_id || "").trim()
|
|
3527
|
+
|| String(request.conversation_intent_mode || "").trim()
|
|
3528
|
+
|| String(request.conversation_reply_expectation || "").trim()
|
|
3529
|
+
|| ensureArray(request.conversation_participants).length
|
|
3530
|
+
|| ensureArray(request.conversation_initial_responders).length
|
|
3531
|
+
|| ensureArray(request.conversation_allowed_responders).length
|
|
3532
|
+
);
|
|
3533
|
+
}
|
|
3534
|
+
|
|
3535
|
+
function runnerRequestHasCompleteConversationContract(requestRaw) {
|
|
3536
|
+
const request = safeObject(requestRaw);
|
|
3537
|
+
const intentMode = String(request.conversation_intent_mode || "").trim().toLowerCase();
|
|
3538
|
+
const conversationID = String(request.conversation_id || "").trim();
|
|
3539
|
+
const replyExpectation = String(request.conversation_reply_expectation || "").trim().toLowerCase();
|
|
3540
|
+
const participants = ensureArray(request.conversation_participants);
|
|
3541
|
+
const initialResponders = ensureArray(request.conversation_initial_responders);
|
|
3542
|
+
const allowedResponders = ensureArray(request.conversation_allowed_responders);
|
|
3543
|
+
if (!runnerRequestHasConversationContract(request)) {
|
|
3544
|
+
return false;
|
|
3545
|
+
}
|
|
3546
|
+
if (!conversationID || !intentMode || !replyExpectation) {
|
|
3547
|
+
return false;
|
|
3548
|
+
}
|
|
3549
|
+
if (intentMode === "single_bot") {
|
|
3550
|
+
return allowedResponders.length > 0 || participants.length > 0;
|
|
3551
|
+
}
|
|
3552
|
+
return participants.length > 0 && initialResponders.length > 0 && allowedResponders.length > 0;
|
|
3553
|
+
}
|
|
3554
|
+
|
|
3555
|
+
function runnerRequestHasExecutionContract(requestRaw) {
|
|
3556
|
+
const request = safeObject(requestRaw);
|
|
3557
|
+
return Boolean(
|
|
3558
|
+
String(request.execution_contract_type || "").trim()
|
|
3559
|
+
|| request.execution_contract_actionable === true
|
|
3560
|
+
|| ensureArray(request.execution_contract_targets).length
|
|
3561
|
+
|| ensureArray(request.next_expected_responders).length
|
|
3562
|
+
);
|
|
3563
|
+
}
|
|
3564
|
+
|
|
3565
|
+
function runnerRequestHasCompleteExecutionContract(requestRaw) {
|
|
3566
|
+
const request = safeObject(requestRaw);
|
|
3567
|
+
const executionContractType = String(request.execution_contract_type || "").trim().toLowerCase();
|
|
3568
|
+
const executionTargets = ensureArray(request.execution_contract_targets);
|
|
3569
|
+
const nextExpectedResponders = ensureArray(request.next_expected_responders);
|
|
3570
|
+
if (!runnerRequestHasExecutionContract(request)) {
|
|
3571
|
+
return false;
|
|
3572
|
+
}
|
|
3573
|
+
if (!executionContractType) {
|
|
3574
|
+
return false;
|
|
3575
|
+
}
|
|
3576
|
+
if (executionContractType === "delegation") {
|
|
3577
|
+
return executionTargets.length > 0 || nextExpectedResponders.length > 0;
|
|
3578
|
+
}
|
|
3579
|
+
if (executionContractType === "summary_request") {
|
|
3580
|
+
return nextExpectedResponders.length > 0 || executionTargets.length > 0;
|
|
3581
|
+
}
|
|
3582
|
+
return true;
|
|
3583
|
+
}
|
|
3584
|
+
|
|
3585
|
+
function runnerRequestHasContractSignals(requestRaw) {
|
|
3586
|
+
const request = safeObject(requestRaw);
|
|
3587
|
+
return runnerRequestHasConversationContract(request) || runnerRequestHasExecutionContract(request);
|
|
3588
|
+
}
|
|
3589
|
+
|
|
3590
|
+
function runnerRequestRequiresActionableContract(requestRaw) {
|
|
3591
|
+
const request = safeObject(requestRaw);
|
|
3592
|
+
const replyExpectation = String(request.conversation_reply_expectation || "").trim().toLowerCase();
|
|
3593
|
+
const executionContractType = String(request.execution_contract_type || "").trim().toLowerCase();
|
|
3594
|
+
if (request.execution_contract_actionable === true) {
|
|
3595
|
+
return true;
|
|
3596
|
+
}
|
|
3597
|
+
if (replyExpectation === "actionable") {
|
|
3598
|
+
return true;
|
|
3599
|
+
}
|
|
3600
|
+
if (["delegation", "direct_result"].includes(executionContractType)) {
|
|
3601
|
+
return true;
|
|
3602
|
+
}
|
|
3603
|
+
return false;
|
|
3604
|
+
}
|
|
3605
|
+
|
|
3504
3606
|
function loadRunnerRequestByKey(requestKey) {
|
|
3505
3607
|
const key = String(requestKey || "").trim();
|
|
3506
3608
|
if (!key) {
|
|
@@ -3512,7 +3614,7 @@ function loadRunnerRequestByKey(requestKey) {
|
|
|
3512
3614
|
function actionableRunnerRequestMissingRootWorkItem(requestRaw) {
|
|
3513
3615
|
const request = safeObject(requestRaw);
|
|
3514
3616
|
return (
|
|
3515
|
-
|
|
3617
|
+
runnerRequestRequiresActionableContract(request)
|
|
3516
3618
|
&& !String(request.root_work_item_id || "").trim()
|
|
3517
3619
|
);
|
|
3518
3620
|
}
|
|
@@ -3824,7 +3926,7 @@ async function ensureRunnerRootWorkItemForRequest({
|
|
|
3824
3926
|
requestKey: key,
|
|
3825
3927
|
};
|
|
3826
3928
|
}
|
|
3827
|
-
if (!
|
|
3929
|
+
if (!runnerRequestRequiresActionableContract(existing)) {
|
|
3828
3930
|
return {
|
|
3829
3931
|
ok: true,
|
|
3830
3932
|
requestKey: key,
|
|
@@ -4216,7 +4318,7 @@ function resolveRunnerContinuationRequestForBotReply({
|
|
|
4216
4318
|
execution_contract_actionable: session.last_execution_contract_actionable === true,
|
|
4217
4319
|
execution_contract_targets: ensureArray(session.last_execution_contract_targets),
|
|
4218
4320
|
next_expected_responders: ensureArray(session.next_expected_responders),
|
|
4219
|
-
normalized_intent: String(
|
|
4321
|
+
normalized_intent: String(fallbackRequest.normalized_intent || "").trim().toLowerCase(),
|
|
4220
4322
|
status: "running",
|
|
4221
4323
|
claimed_by_route: String(sessionMatch.routeKey || "").trim(),
|
|
4222
4324
|
claimed_at: firstNonEmptyString([session.started_at, nowISO]),
|
|
@@ -4333,6 +4435,26 @@ function markRunnerRequestLifecycle({
|
|
|
4333
4435
|
normalizeTelegramMentionUsername,
|
|
4334
4436
|
).filter((selector) => selector && selector !== normalizedCurrentBotSelector);
|
|
4335
4437
|
const shouldRemainRunningAfterReply = continuationSelectors.length > 0;
|
|
4438
|
+
const nextConversationIntentMode = String(
|
|
4439
|
+
conversationIntentMode
|
|
4440
|
+
|| existing.conversation_intent_mode
|
|
4441
|
+
|| "",
|
|
4442
|
+
).trim().toLowerCase();
|
|
4443
|
+
const nextExecutionContractType = String(
|
|
4444
|
+
executionContractType
|
|
4445
|
+
|| existing.execution_contract_type
|
|
4446
|
+
|| "",
|
|
4447
|
+
).trim().toLowerCase();
|
|
4448
|
+
const nextNormalizedIntent = (() => {
|
|
4449
|
+
const explicitIntent = String(normalizedIntent || "").trim().toLowerCase();
|
|
4450
|
+
if (explicitIntent) {
|
|
4451
|
+
return explicitIntent;
|
|
4452
|
+
}
|
|
4453
|
+
if (nextConversationIntentMode && !nextExecutionContractType) {
|
|
4454
|
+
return "";
|
|
4455
|
+
}
|
|
4456
|
+
return String(existing.normalized_intent || "").trim().toLowerCase();
|
|
4457
|
+
})();
|
|
4336
4458
|
const normalizedOutcome = String(outcome || "").trim().toLowerCase();
|
|
4337
4459
|
const nextStatus = (() => {
|
|
4338
4460
|
if (normalizedOutcome === "claimed") return "claimed";
|
|
@@ -4364,11 +4486,7 @@ function markRunnerRequestLifecycle({
|
|
|
4364
4486
|
ensureArray(allowedResponders).length ? allowedResponders : existing.conversation_allowed_responders,
|
|
4365
4487
|
normalizeTelegramMentionUsername,
|
|
4366
4488
|
),
|
|
4367
|
-
conversation_intent_mode:
|
|
4368
|
-
conversationIntentMode
|
|
4369
|
-
|| existing.conversation_intent_mode
|
|
4370
|
-
|| "",
|
|
4371
|
-
).trim().toLowerCase(),
|
|
4489
|
+
conversation_intent_mode: nextConversationIntentMode,
|
|
4372
4490
|
conversation_lead_bot: normalizeTelegramMentionUsername(
|
|
4373
4491
|
conversationLeadBot
|
|
4374
4492
|
|| existing.conversation_lead_bot
|
|
@@ -4386,11 +4504,7 @@ function markRunnerRequestLifecycle({
|
|
|
4386
4504
|
|| existing.conversation_reply_expectation
|
|
4387
4505
|
|| "",
|
|
4388
4506
|
).trim().toLowerCase(),
|
|
4389
|
-
execution_contract_type:
|
|
4390
|
-
executionContractType
|
|
4391
|
-
|| existing.execution_contract_type
|
|
4392
|
-
|| "",
|
|
4393
|
-
).trim().toLowerCase(),
|
|
4507
|
+
execution_contract_type: nextExecutionContractType,
|
|
4394
4508
|
execution_contract_actionable: executionContractActionable === true
|
|
4395
4509
|
|| existing.execution_contract_actionable === true,
|
|
4396
4510
|
execution_contract_targets: uniqueOrderedStrings(
|
|
@@ -4401,7 +4515,7 @@ function markRunnerRequestLifecycle({
|
|
|
4401
4515
|
ensureArray(nextExpectedResponders).length ? nextExpectedResponders : existing.next_expected_responders,
|
|
4402
4516
|
normalizeTelegramMentionUsername,
|
|
4403
4517
|
),
|
|
4404
|
-
normalized_intent:
|
|
4518
|
+
normalized_intent: nextNormalizedIntent,
|
|
4405
4519
|
status: nextStatus,
|
|
4406
4520
|
started_at: firstNonEmptyString([existing.started_at, nowISO]),
|
|
4407
4521
|
completed_at: nextStatus === "completed" ? nowISO : String(existing.completed_at || "").trim(),
|
|
@@ -4842,7 +4956,7 @@ async function syncRunnerRequestLedgerForProjectToServer({ normalizedRoute, runt
|
|
|
4842
4956
|
})[String(request.request_key || "").trim()]
|
|
4843
4957
|
: request;
|
|
4844
4958
|
if (
|
|
4845
|
-
|
|
4959
|
+
runnerRequestRequiresActionableContract(recoveredRequest)
|
|
4846
4960
|
&& !String(recoveredRequest.root_work_item_id || "").trim()
|
|
4847
4961
|
) {
|
|
4848
4962
|
continue;
|
|
@@ -2085,7 +2085,9 @@ export function serializeLocalAIResult(result) {
|
|
|
2085
2085
|
function buildConversationIntentAnalysisPrompt({
|
|
2086
2086
|
messageText,
|
|
2087
2087
|
managedBots,
|
|
2088
|
+
contractGuardrail = null,
|
|
2088
2089
|
}) {
|
|
2090
|
+
const guardrail = safeObject(contractGuardrail);
|
|
2089
2091
|
const bots = ensureArray(managedBots).map((item) => {
|
|
2090
2092
|
const bot = safeObject(item);
|
|
2091
2093
|
return {
|
|
@@ -2129,6 +2131,15 @@ function buildConversationIntentAnalysisPrompt({
|
|
|
2129
2131
|
"- If the human asks bots to discuss, debate, review, brainstorm, compare opinions, or hold a conversation about a topic, default to reply_expectation=informational unless they explicitly ask for concrete execution/output now.",
|
|
2130
2132
|
"- reply_expectation=actionable when the human is asking the bot(s) to actually do work now, produce concrete results, create/update files, delegate concrete tasks, or otherwise execute immediately.",
|
|
2131
2133
|
"- reply_expectation=informational when the human is only asking for explanation, status, location, clarification, discussion, review, brainstorming, or other non-execution information.",
|
|
2134
|
+
guardrail.require_complete_contract === true
|
|
2135
|
+
? "- Contract guardrail: do not leave intent_type, reply_expectation, participants, initial_responders, or allowed_responders empty when the message clearly addresses managed bots."
|
|
2136
|
+
: "",
|
|
2137
|
+
guardrail.require_explicit_actionable_intent === true
|
|
2138
|
+
? "- Contract guardrail: if reply_expectation=actionable, intent_type must be exactly one of ctxpack_mutation, workitem_mutation, or general_execution."
|
|
2139
|
+
: "",
|
|
2140
|
+
String(guardrail.reason || "").trim()
|
|
2141
|
+
? `- Contract guardrail reason: ${String(guardrail.reason || "").trim()}`
|
|
2142
|
+
: "",
|
|
2132
2143
|
"",
|
|
2133
2144
|
`managed_bots=${JSON.stringify(bots)}`,
|
|
2134
2145
|
`human_message=${JSON.stringify(String(messageText || "").trim())}`,
|
|
@@ -2471,6 +2482,7 @@ export function analyzeHumanConversationIntentWithAI({
|
|
|
2471
2482
|
messageText,
|
|
2472
2483
|
managedBots,
|
|
2473
2484
|
workspaceDir,
|
|
2485
|
+
contractGuardrail = null,
|
|
2474
2486
|
client = "",
|
|
2475
2487
|
model = "",
|
|
2476
2488
|
env = process.env,
|
|
@@ -2498,6 +2510,7 @@ export function analyzeHumanConversationIntentWithAI({
|
|
|
2498
2510
|
promptText: buildConversationIntentAnalysisPrompt({
|
|
2499
2511
|
messageText,
|
|
2500
2512
|
managedBots: bots,
|
|
2513
|
+
contractGuardrail,
|
|
2501
2514
|
}),
|
|
2502
2515
|
workspaceDir,
|
|
2503
2516
|
model: parserModel,
|