metheus-governance-mcp-cli 0.2.283 → 0.2.284
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 +23 -17
- package/lib/runner-delivery-archive-handoff.mjs +42 -4
- package/lib/runner-helpers.mjs +21 -0
- package/lib/runner-orchestration-selected-record-preparation.mjs +17 -2
- package/lib/runner-orchestration-selected-record-reply-outcome.mjs +22 -6
- package/lib/runner-recorder-failure-delivery-handoff.mjs +2 -8
- package/lib/runner-recorder-failure-delivery-outcome-handoff.mjs +36 -8
- package/lib/selftest-runner-scenarios.mjs +577 -2
- package/package.json +1 -1
package/cli.mjs
CHANGED
|
@@ -145,10 +145,10 @@ import {
|
|
|
145
145
|
findEarlierProcessableArchiveDuplicate,
|
|
146
146
|
findRecentTelegramMessageEnvelope,
|
|
147
147
|
isTelegramLocalInboundEnvelopeForRoute,
|
|
148
|
-
isInboundArchiveKind,
|
|
149
|
-
normalizeTelegramMessageEnvelope as normalizeRunnerTelegramMessageEnvelope,
|
|
150
|
-
normalizeArchiveCommentRecord,
|
|
151
|
-
selectPendingArchiveComments,
|
|
148
|
+
isInboundArchiveKind,
|
|
149
|
+
normalizeTelegramMessageEnvelope as normalizeRunnerTelegramMessageEnvelope,
|
|
150
|
+
normalizeArchiveCommentRecord,
|
|
151
|
+
selectPendingArchiveComments,
|
|
152
152
|
printRunnerResult,
|
|
153
153
|
} from "./lib/runner-helpers.mjs";
|
|
154
154
|
import {
|
|
@@ -6430,10 +6430,7 @@ function markRunnerRequestLifecycle({
|
|
|
6430
6430
|
const authoritativeDecisionBundle = resolvedDecisionBundleValidation.ok === true
|
|
6431
6431
|
? safeObject(resolvedDecisionBundleValidation.bundle)
|
|
6432
6432
|
: runnerRequestAuthoritativeDecisionBundle(existing);
|
|
6433
|
-
const effectiveReplyToMessageID = intFromRawAllowZero(
|
|
6434
|
-
replyToMessageID,
|
|
6435
|
-
intFromRawAllowZero(existing.last_reply_to_message_id, 0),
|
|
6436
|
-
);
|
|
6433
|
+
const effectiveReplyToMessageID = intFromRawAllowZero(replyToMessageID, 0);
|
|
6437
6434
|
const lastReplyMessageEnvelope = buildTelegramBotReplyEnvelope({
|
|
6438
6435
|
sourceEnvelope: sourceMessageEnvelope,
|
|
6439
6436
|
chatID: existing.chat_id,
|
|
@@ -6454,14 +6451,14 @@ function markRunnerRequestLifecycle({
|
|
|
6454
6451
|
senderUsername: normalizedCurrentBotSelector,
|
|
6455
6452
|
body: aiReplyPreview,
|
|
6456
6453
|
});
|
|
6457
|
-
const shouldRefreshAttemptedDeliveryEnvelope = (
|
|
6458
|
-
aiReplyGenerated === true
|
|
6459
|
-
|| String(aiReplyPreview || "").trim().length > 0
|
|
6460
|
-
|| String(deliveryStatus || "").trim().length > 0
|
|
6461
|
-
|| String(transportError || "").trim().length > 0
|
|
6462
|
-
|| intFromRawAllowZero(replyToMessageID, 0) > 0
|
|
6463
|
-
|| intFromRawAllowZero(lastReplyMessageThreadID, 0) > 0
|
|
6464
|
-
);
|
|
6454
|
+
const shouldRefreshAttemptedDeliveryEnvelope = (
|
|
6455
|
+
aiReplyGenerated === true
|
|
6456
|
+
|| String(aiReplyPreview || "").trim().length > 0
|
|
6457
|
+
|| String(deliveryStatus || "").trim().length > 0
|
|
6458
|
+
|| String(transportError || "").trim().length > 0
|
|
6459
|
+
|| intFromRawAllowZero(replyToMessageID, 0) > 0
|
|
6460
|
+
|| intFromRawAllowZero(lastReplyMessageThreadID, 0) > 0
|
|
6461
|
+
);
|
|
6465
6462
|
const rootEffectiveExecutionContractTargets = uniqueOrderedStrings(
|
|
6466
6463
|
[
|
|
6467
6464
|
...ensureArray(authoritativeDecisionBundle.execution_contract_targets),
|
|
@@ -6504,6 +6501,13 @@ function markRunnerRequestLifecycle({
|
|
|
6504
6501
|
const normalizedOutcome = String(outcome || "").trim().toLowerCase();
|
|
6505
6502
|
const normalizedFailureReplyClassification = String(failureReplyClassification || "").trim().toLowerCase();
|
|
6506
6503
|
const normalizedFailureFacts = safeObject(failureFacts);
|
|
6504
|
+
const shouldPersistReplyAnchor = (
|
|
6505
|
+
aiReplyGenerated === true
|
|
6506
|
+
|| intFromRawAllowZero(lastReplyMessageID, 0) > 0
|
|
6507
|
+
|| ["delivered", "dry_run", "archive_error", "failed_transport"].includes(normalizedDeliveryStatus)
|
|
6508
|
+
|| String(transportError || "").trim().length > 0
|
|
6509
|
+
|| ["replied", "delivery_failed_after_generation"].includes(normalizedOutcome)
|
|
6510
|
+
);
|
|
6507
6511
|
const shouldRemainRunningAfterReply = authoritativeDecisionBundle.should_close_after_reply === true
|
|
6508
6512
|
? false
|
|
6509
6513
|
: authoritativeDecisionBundle.should_close_after_reply === false
|
|
@@ -6907,7 +6911,9 @@ function markRunnerRequestLifecycle({
|
|
|
6907
6911
|
last_source_message_thread_id: intFromRawAllowZero(parsed.messageThreadID, 0) || existing.last_source_message_thread_id,
|
|
6908
6912
|
last_reply_message_id: intFromRawAllowZero(lastReplyMessageID, 0) || existing.last_reply_message_id,
|
|
6909
6913
|
last_reply_message_thread_id: intFromRawAllowZero(lastReplyMessageThreadID, 0) || existing.last_reply_message_thread_id,
|
|
6910
|
-
last_reply_to_message_id:
|
|
6914
|
+
last_reply_to_message_id: shouldPersistReplyAnchor
|
|
6915
|
+
? effectiveReplyToMessageID
|
|
6916
|
+
: existing.last_reply_to_message_id,
|
|
6911
6917
|
last_reply_message_envelope: persistSuccessfulReplyEnvelope
|
|
6912
6918
|
? lastReplyMessageEnvelope
|
|
6913
6919
|
: safeObject(existing.last_reply_message_envelope),
|
|
@@ -13,6 +13,14 @@ function intFromRawAllowZero(value, fallback = 0) {
|
|
|
13
13
|
return Number.isFinite(parsed) ? parsed : fallback;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
function buildReplyAnchorMismatchError(expectedReplyToMessageID, observedReplyToMessageID) {
|
|
17
|
+
return `reply anchor mismatch: expected ${String(expectedReplyToMessageID || 0)}, observed ${String(observedReplyToMessageID || 0)}`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function buildMessageThreadMismatchError(expectedMessageThreadID, observedMessageThreadID) {
|
|
21
|
+
return `message thread mismatch: expected ${String(expectedMessageThreadID || 0)}, observed ${String(observedMessageThreadID || 0)}`;
|
|
22
|
+
}
|
|
23
|
+
|
|
16
24
|
function requireArchiveDependency(deps, key) {
|
|
17
25
|
const candidate = deps?.[key];
|
|
18
26
|
if (typeof candidate !== "function") {
|
|
@@ -83,11 +91,41 @@ export async function finalizeLocalBotDeliveryArchive({
|
|
|
83
91
|
deliveredResult.message_id ?? deliveredBody.message_id ?? deliveredBody.ts,
|
|
84
92
|
0,
|
|
85
93
|
);
|
|
86
|
-
const
|
|
94
|
+
const observedMessageThreadID = intFromRawAllowZero(
|
|
87
95
|
deliveredResult.message_thread_id ?? deliveredBody.message_thread_id ?? delivery.effectiveMessageThreadID,
|
|
88
96
|
intFromRawAllowZero(messageThreadID, 0),
|
|
89
97
|
);
|
|
90
|
-
const
|
|
98
|
+
const expectedMessageThreadID = intFromRawAllowZero(messageThreadID, 0);
|
|
99
|
+
const expectedReplyToMessageID = intFromRawAllowZero(replyToMessageID, 0);
|
|
100
|
+
const observedReplyToMessageID = intFromRawAllowZero(delivery.effectiveReplyToMessageID, 0);
|
|
101
|
+
if (
|
|
102
|
+
(expectedReplyToMessageID > 0 || observedReplyToMessageID > 0)
|
|
103
|
+
&& observedReplyToMessageID !== expectedReplyToMessageID
|
|
104
|
+
) {
|
|
105
|
+
return {
|
|
106
|
+
ok: false,
|
|
107
|
+
error: buildReplyAnchorMismatchError(expectedReplyToMessageID, observedReplyToMessageID),
|
|
108
|
+
reply_anchor_mismatch: true,
|
|
109
|
+
expected_reply_to_message_id: expectedReplyToMessageID,
|
|
110
|
+
observed_reply_to_message_id: observedReplyToMessageID,
|
|
111
|
+
thread_id: thread.threadID,
|
|
112
|
+
work_item_id: thread.workItemID,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
if (
|
|
116
|
+
(expectedMessageThreadID > 0 || observedMessageThreadID > 0)
|
|
117
|
+
&& observedMessageThreadID !== expectedMessageThreadID
|
|
118
|
+
) {
|
|
119
|
+
return {
|
|
120
|
+
ok: false,
|
|
121
|
+
error: buildMessageThreadMismatchError(expectedMessageThreadID, observedMessageThreadID),
|
|
122
|
+
message_thread_mismatch: true,
|
|
123
|
+
expected_message_thread_id: expectedMessageThreadID,
|
|
124
|
+
observed_message_thread_id: observedMessageThreadID,
|
|
125
|
+
thread_id: thread.threadID,
|
|
126
|
+
work_item_id: thread.workItemID,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
91
129
|
if (archiveDedupeOutbound && deliveredMessageID > 0) {
|
|
92
130
|
const existingComments = await listThreadCommentsTail({
|
|
93
131
|
siteBaseURL,
|
|
@@ -119,8 +157,8 @@ export async function finalizeLocalBotDeliveryArchive({
|
|
|
119
157
|
destination,
|
|
120
158
|
replyText: text,
|
|
121
159
|
messageID: deliveredMessageID,
|
|
122
|
-
messageThreadID:
|
|
123
|
-
replyToMessageID:
|
|
160
|
+
messageThreadID: expectedMessageThreadID,
|
|
161
|
+
replyToMessageID: expectedReplyToMessageID,
|
|
124
162
|
conversation: archiveConversation,
|
|
125
163
|
});
|
|
126
164
|
const createdComment = await createThreadComment({
|
package/lib/runner-helpers.mjs
CHANGED
|
@@ -314,6 +314,27 @@ export function buildTelegramMessageEnvelopeFromParsedArchive(parsedArchiveRaw,
|
|
|
314
314
|
});
|
|
315
315
|
}
|
|
316
316
|
|
|
317
|
+
export function resolveTelegramReplyAnchorMessageID({
|
|
318
|
+
replyToMessageID = 0,
|
|
319
|
+
sourceEnvelope: sourceEnvelopeRaw = {},
|
|
320
|
+
fallbackReplyToMessageID = 0,
|
|
321
|
+
} = {}) {
|
|
322
|
+
const explicitReplyToMessageID = intFromRawAllowZero(replyToMessageID, 0);
|
|
323
|
+
if (explicitReplyToMessageID > 0) {
|
|
324
|
+
return explicitReplyToMessageID;
|
|
325
|
+
}
|
|
326
|
+
const sourceEnvelope = normalizeTelegramMessageEnvelope(sourceEnvelopeRaw);
|
|
327
|
+
const sourceMessageID = intFromRawAllowZero(sourceEnvelope.message_id, 0);
|
|
328
|
+
if (sourceMessageID > 0) {
|
|
329
|
+
return sourceMessageID;
|
|
330
|
+
}
|
|
331
|
+
const sourceReplyToMessageID = intFromRawAllowZero(sourceEnvelope.reply_to_message_id, 0);
|
|
332
|
+
if (sourceReplyToMessageID > 0) {
|
|
333
|
+
return sourceReplyToMessageID;
|
|
334
|
+
}
|
|
335
|
+
return intFromRawAllowZero(fallbackReplyToMessageID, 0);
|
|
336
|
+
}
|
|
337
|
+
|
|
317
338
|
export function buildTelegramBotReplyEnvelope({
|
|
318
339
|
sourceEnvelope: sourceEnvelopeRaw = {},
|
|
319
340
|
chatID = "",
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
resolveTelegramReplyAnchorMessageID,
|
|
3
|
+
} from "./runner-helpers.mjs";
|
|
4
|
+
|
|
1
5
|
function safeObject(value) {
|
|
2
6
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
3
7
|
return {};
|
|
@@ -154,9 +158,20 @@ export function prepareRunnerSelectedRecordIngress({
|
|
|
154
158
|
currentBotSelector,
|
|
155
159
|
});
|
|
156
160
|
const replyMessageThreadID = intFromRawAllowZero(sourceMessageEnvelope.message_thread_id, 0);
|
|
157
|
-
const
|
|
161
|
+
const sourceMessageID = intFromRawAllowZero(sourceMessageEnvelope.message_id, 0);
|
|
162
|
+
const sourceReplyToMessageID = intFromRawAllowZero(sourceMessageEnvelope.reply_to_message_id, 0);
|
|
163
|
+
const replyToMessageID = resolveTelegramReplyAnchorMessageID({
|
|
164
|
+
replyToMessageID: sourceMessageID,
|
|
165
|
+
sourceEnvelope: sourceMessageEnvelope,
|
|
166
|
+
});
|
|
158
167
|
const replyAnchorSource = String(sourceMessageEnvelope.source_origin || "").trim()
|
|
159
|
-
|| (replyToMessageID > 0
|
|
168
|
+
|| (replyToMessageID > 0
|
|
169
|
+
? sourceMessageID > 0
|
|
170
|
+
? "source_message_envelope"
|
|
171
|
+
: sourceReplyToMessageID > 0
|
|
172
|
+
? "source_message_envelope_reply_to"
|
|
173
|
+
: ""
|
|
174
|
+
: "");
|
|
160
175
|
|
|
161
176
|
return {
|
|
162
177
|
handledResult: null,
|
|
@@ -29,6 +29,10 @@ function buildConversationSummaryDetail({
|
|
|
29
29
|
].filter(Boolean).join(" | ");
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
function buildMessageThreadMismatchError(expectedMessageThreadID, observedMessageThreadID) {
|
|
33
|
+
return `message thread mismatch: expected ${String(expectedMessageThreadID || 0)}, observed ${String(observedMessageThreadID || 0)}`;
|
|
34
|
+
}
|
|
35
|
+
|
|
32
36
|
function buildSelectedRecordReplyOutcomeBase({
|
|
33
37
|
routeKey,
|
|
34
38
|
normalizedRoute,
|
|
@@ -354,11 +358,19 @@ export async function finalizeRunnerSelectedRecordReplyOutcome({
|
|
|
354
358
|
deliveryBody.result?.message_id ?? deliveryBody.message_id,
|
|
355
359
|
0,
|
|
356
360
|
);
|
|
357
|
-
const
|
|
361
|
+
const expectedReplyMessageThreadID = intFromRawAllowZero(replyMessageThreadID, 0);
|
|
362
|
+
const observedReplyMessageThreadID = intFromRawAllowZero(
|
|
358
363
|
deliveryResult?.delivery?.effectiveMessageThreadID,
|
|
359
|
-
|
|
364
|
+
0,
|
|
365
|
+
);
|
|
366
|
+
const messageThreadMismatch = (
|
|
367
|
+
(expectedReplyMessageThreadID > 0 || observedReplyMessageThreadID > 0)
|
|
368
|
+
&& observedReplyMessageThreadID !== expectedReplyMessageThreadID
|
|
360
369
|
);
|
|
361
|
-
const
|
|
370
|
+
const messageThreadError = messageThreadMismatch
|
|
371
|
+
? buildMessageThreadMismatchError(expectedReplyMessageThreadID, observedReplyMessageThreadID)
|
|
372
|
+
: "";
|
|
373
|
+
const effectiveReplyToMessageID = intFromRawAllowZero(replyToMessageID, 0);
|
|
362
374
|
const conversationDetail = buildConversationSummaryDetail({
|
|
363
375
|
effectiveConversationContext,
|
|
364
376
|
executionContract,
|
|
@@ -371,7 +383,7 @@ export async function finalizeRunnerSelectedRecordReplyOutcome({
|
|
|
371
383
|
...buildRunnerRouteStateFromComment(selectedRecord, {
|
|
372
384
|
last_action: "replied",
|
|
373
385
|
last_reply_message_id: replyMessageID,
|
|
374
|
-
last_reply_message_thread_id:
|
|
386
|
+
last_reply_message_thread_id: expectedReplyMessageThreadID,
|
|
375
387
|
last_reply_anchor_source: replyAnchorSource,
|
|
376
388
|
last_contract_validation_status: String(responseContractValidation?.status || "").trim(),
|
|
377
389
|
last_contract_validation_reason: String(responseContractValidation?.reason || "").trim(),
|
|
@@ -445,17 +457,21 @@ export async function finalizeRunnerSelectedRecordReplyOutcome({
|
|
|
445
457
|
evidence_ids: ensureArray(aiResult?.evidenceItems).map((item) => String(safeObject(item).id || "").trim()).filter(Boolean),
|
|
446
458
|
evidence_paths: ensureArray(aiResult?.evidenceItems).map((item) => String(safeObject(item).path || "").trim()).filter(Boolean),
|
|
447
459
|
last_reply_message_id: replyMessageID,
|
|
448
|
-
last_reply_message_thread_id:
|
|
460
|
+
last_reply_message_thread_id: expectedReplyMessageThreadID,
|
|
449
461
|
reply_to_message_id: effectiveReplyToMessageID,
|
|
450
462
|
last_reply_message_envelope: buildTelegramBotReplyEnvelope({
|
|
451
463
|
sourceEnvelope: sourceMessageEnvelope,
|
|
452
464
|
messageID: replyMessageID,
|
|
453
|
-
messageThreadID:
|
|
465
|
+
messageThreadID: expectedReplyMessageThreadID,
|
|
454
466
|
replyToMessageID: effectiveReplyToMessageID,
|
|
455
467
|
sender: bot?.username ? `@${String(bot.username || "").trim().replace(/^@+/, "")}` : String(bot?.name || "bot").trim(),
|
|
456
468
|
senderUsername: normalizeMentionSelector(bot?.username || bot?.name),
|
|
457
469
|
body: sanitizedReplyText,
|
|
458
470
|
}),
|
|
471
|
+
message_thread_mismatch: messageThreadMismatch,
|
|
472
|
+
expected_message_thread_id: expectedReplyMessageThreadID || undefined,
|
|
473
|
+
observed_message_thread_id: observedReplyMessageThreadID || undefined,
|
|
474
|
+
message_thread_error: messageThreadError,
|
|
459
475
|
reply_anchor_source: replyAnchorSource,
|
|
460
476
|
reply_fallback_used: deliveryResult?.delivery?.replyFallbackUsed === true,
|
|
461
477
|
delivery_status: deliveryResult?.delivery?.dryRun ? "dry_run" : "delivered",
|
|
@@ -36,14 +36,8 @@ export function prepareRunnerFailureReplyDeliveryHandoff({
|
|
|
36
36
|
const sourceMessageEnvelope = Object.keys(safeObject(authoritativeSourceMessageEnvelope)).length > 0
|
|
37
37
|
? safeObject(authoritativeSourceMessageEnvelope)
|
|
38
38
|
: safeObject(result.source_message_envelope);
|
|
39
|
-
const replyToMessageID = intFromRawAllowZero(
|
|
40
|
-
|
|
41
|
-
intFromRawAllowZero(sourceMessageEnvelope.message_id, 0),
|
|
42
|
-
);
|
|
43
|
-
const messageThreadID = intFromRawAllowZero(
|
|
44
|
-
result.reply_message_thread_id,
|
|
45
|
-
intFromRawAllowZero(sourceMessageEnvelope.message_thread_id, 0),
|
|
46
|
-
);
|
|
39
|
+
const replyToMessageID = intFromRawAllowZero(result.reply_to_message_id, 0);
|
|
40
|
+
const messageThreadID = intFromRawAllowZero(result.reply_message_thread_id, 0);
|
|
47
41
|
return {
|
|
48
42
|
siteBaseURL: normalizedRuntime.baseURL,
|
|
49
43
|
token: normalizedRuntime.token,
|
|
@@ -11,6 +11,14 @@ function intFromRawAllowZero(value, fallback = 0) {
|
|
|
11
11
|
return Number.isFinite(parsed) ? parsed : fallback;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
function buildReplyAnchorMismatchError(expectedReplyToMessageID, observedReplyToMessageID) {
|
|
15
|
+
return `reply anchor mismatch: expected ${String(expectedReplyToMessageID || 0)}, observed ${String(observedReplyToMessageID || 0)}`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function buildMessageThreadMismatchError(expectedMessageThreadID, observedMessageThreadID) {
|
|
19
|
+
return `message thread mismatch: expected ${String(expectedMessageThreadID || 0)}, observed ${String(observedMessageThreadID || 0)}`;
|
|
20
|
+
}
|
|
21
|
+
|
|
14
22
|
export function finalizeRunnerFailureReplyDeliveryOutcome({
|
|
15
23
|
processed = {},
|
|
16
24
|
routeKey = "",
|
|
@@ -50,6 +58,24 @@ export function finalizeRunnerFailureReplyDeliveryOutcome({
|
|
|
50
58
|
const delivery = safeObject(normalizedDeliveryResult.delivery);
|
|
51
59
|
const archive = safeObject(normalizedDeliveryResult.archive);
|
|
52
60
|
const handoff = safeObject(deliveryHandoff);
|
|
61
|
+
const expectedReplyToMessageID = intFromRawAllowZero(handoff.replyToMessageID, 0);
|
|
62
|
+
const observedReplyToMessageID = intFromRawAllowZero(delivery.effectiveReplyToMessageID, 0);
|
|
63
|
+
const expectedMessageThreadID = intFromRawAllowZero(handoff.messageThreadID, 0);
|
|
64
|
+
const observedMessageThreadID = intFromRawAllowZero(delivery.effectiveMessageThreadID, 0);
|
|
65
|
+
const replyAnchorMismatch = (
|
|
66
|
+
(expectedReplyToMessageID > 0 || observedReplyToMessageID > 0)
|
|
67
|
+
&& observedReplyToMessageID !== expectedReplyToMessageID
|
|
68
|
+
);
|
|
69
|
+
const replyAnchorError = replyAnchorMismatch
|
|
70
|
+
? buildReplyAnchorMismatchError(expectedReplyToMessageID, observedReplyToMessageID)
|
|
71
|
+
: "";
|
|
72
|
+
const messageThreadMismatch = (
|
|
73
|
+
(expectedMessageThreadID > 0 || observedMessageThreadID > 0)
|
|
74
|
+
&& observedMessageThreadID !== expectedMessageThreadID
|
|
75
|
+
);
|
|
76
|
+
const messageThreadError = messageThreadMismatch
|
|
77
|
+
? buildMessageThreadMismatchError(expectedMessageThreadID, observedMessageThreadID)
|
|
78
|
+
: "";
|
|
53
79
|
const mergedResult = {
|
|
54
80
|
...result,
|
|
55
81
|
failure_reply_sent: true,
|
|
@@ -69,14 +95,16 @@ export function finalizeRunnerFailureReplyDeliveryOutcome({
|
|
|
69
95
|
safeObject(delivery.body).result?.message_id ?? safeObject(delivery.body).message_id,
|
|
70
96
|
intFromRawAllowZero(result.last_reply_message_id, 0),
|
|
71
97
|
),
|
|
72
|
-
last_reply_message_thread_id:
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
98
|
+
last_reply_message_thread_id: expectedMessageThreadID,
|
|
99
|
+
reply_to_message_id: expectedReplyToMessageID,
|
|
100
|
+
reply_anchor_mismatch: replyAnchorMismatch,
|
|
101
|
+
expected_reply_to_message_id: expectedReplyToMessageID || undefined,
|
|
102
|
+
observed_reply_to_message_id: observedReplyToMessageID || undefined,
|
|
103
|
+
reply_anchor_error: replyAnchorError,
|
|
104
|
+
message_thread_mismatch: messageThreadMismatch,
|
|
105
|
+
expected_message_thread_id: expectedMessageThreadID || undefined,
|
|
106
|
+
observed_message_thread_id: observedMessageThreadID || undefined,
|
|
107
|
+
message_thread_error: messageThreadError,
|
|
80
108
|
};
|
|
81
109
|
if (normalizedRouteKey && typeof saveRunnerRouteState === "function") {
|
|
82
110
|
const currentRouteState = typeof loadRouteState === "function"
|
|
@@ -18930,7 +18930,7 @@ export async function runSelftestRunnerScenarios(push, deps) {
|
|
|
18930
18930
|
next_expected_responders: ["beta_bot"],
|
|
18931
18931
|
},
|
|
18932
18932
|
authoritativeSourceMessageEnvelope: {
|
|
18933
|
-
message_id:
|
|
18933
|
+
message_id: 5501,
|
|
18934
18934
|
source_origin: "local_receipt",
|
|
18935
18935
|
},
|
|
18936
18936
|
buildRunnerDeliveryDeps: () => ({
|
|
@@ -18940,12 +18940,13 @@ export async function runSelftestRunnerScenarios(push, deps) {
|
|
|
18940
18940
|
push(
|
|
18941
18941
|
"runner_recorder_failure_delivery_handoff_stays_within_5_to_6_boundary",
|
|
18942
18942
|
String(handoff.text || "") === "I could not finish this request."
|
|
18943
|
+
&& String(handoff.replyToMessageID || "") === "4401"
|
|
18943
18944
|
&& String(handoff.archiveConversationContext?.id || "") === "conversation-failure-handoff-1"
|
|
18944
18945
|
&& String(handoff.archiveExecutionContract?.type || "") === "delegation"
|
|
18945
18946
|
&& !Object.prototype.hasOwnProperty.call(handoff, "archiveConversation")
|
|
18946
18947
|
&& !Object.prototype.hasOwnProperty.call(handoff, "requestKey")
|
|
18947
18948
|
&& !Object.prototype.hasOwnProperty.call(handoff, "status"),
|
|
18948
|
-
`text=${String(handoff.text || "(none)")} conversation=${String(handoff.archiveConversationContext?.id || "(none)")} contract=${String(handoff.archiveExecutionContract?.type || "(none)")} archiveConversation=${String(handoff.archiveConversation || "(none)")}`,
|
|
18949
|
+
`text=${String(handoff.text || "(none)")} replyTo=${String(handoff.replyToMessageID || "(none)")} conversation=${String(handoff.archiveConversationContext?.id || "(none)")} contract=${String(handoff.archiveExecutionContract?.type || "(none)")} archiveConversation=${String(handoff.archiveConversation || "(none)")}`,
|
|
18949
18950
|
);
|
|
18950
18951
|
} catch (err) {
|
|
18951
18952
|
push("runner_recorder_failure_delivery_handoff_stays_within_5_to_6_boundary", false, String(err?.message || err));
|
|
@@ -19003,6 +19004,96 @@ export async function runSelftestRunnerScenarios(push, deps) {
|
|
|
19003
19004
|
push("runner_recorder_failure_delivery_outcome_handoff_stays_within_module_5_boundary", false, String(err?.message || err));
|
|
19004
19005
|
}
|
|
19005
19006
|
|
|
19007
|
+
try {
|
|
19008
|
+
const finalizedFailureDelivery = finalizeRunnerFailureReplyDeliveryOutcome({
|
|
19009
|
+
processed: {
|
|
19010
|
+
kind: "error",
|
|
19011
|
+
result: {
|
|
19012
|
+
failure_reply_text: "I could not finish this request.",
|
|
19013
|
+
last_reply_message_id: 11,
|
|
19014
|
+
},
|
|
19015
|
+
},
|
|
19016
|
+
routeKey: "route-failure-delivery-outcome-mismatch-1",
|
|
19017
|
+
deliveryResult: {
|
|
19018
|
+
delivery: {
|
|
19019
|
+
dryRun: false,
|
|
19020
|
+
effectiveMessageThreadID: 22,
|
|
19021
|
+
effectiveReplyToMessageID: 99,
|
|
19022
|
+
body: {
|
|
19023
|
+
result: {
|
|
19024
|
+
message_id: 44,
|
|
19025
|
+
},
|
|
19026
|
+
},
|
|
19027
|
+
},
|
|
19028
|
+
archive: {
|
|
19029
|
+
ok: true,
|
|
19030
|
+
},
|
|
19031
|
+
},
|
|
19032
|
+
deliveryHandoff: {
|
|
19033
|
+
messageThreadID: 22,
|
|
19034
|
+
replyToMessageID: 33,
|
|
19035
|
+
},
|
|
19036
|
+
loadRouteState: () => ({}),
|
|
19037
|
+
saveRunnerRouteState: () => {},
|
|
19038
|
+
});
|
|
19039
|
+
push(
|
|
19040
|
+
"runner_failure_delivery_outcome_preserves_module_4_reply_anchor_on_mismatch",
|
|
19041
|
+
intFromRawAllowZero(safeSelftestObject(finalizedFailureDelivery.result).reply_to_message_id, 0) === 33
|
|
19042
|
+
&& safeSelftestObject(finalizedFailureDelivery.result).reply_anchor_mismatch === true
|
|
19043
|
+
&& intFromRawAllowZero(safeSelftestObject(finalizedFailureDelivery.result).expected_reply_to_message_id, 0) === 33
|
|
19044
|
+
&& intFromRawAllowZero(safeSelftestObject(finalizedFailureDelivery.result).observed_reply_to_message_id, 0) === 99
|
|
19045
|
+
&& /expected 33, observed 99/i.test(String(safeSelftestObject(finalizedFailureDelivery.result).reply_anchor_error || "")),
|
|
19046
|
+
`reply_to=${String(safeSelftestObject(finalizedFailureDelivery.result).reply_to_message_id || "(none)")} mismatch=${String(safeSelftestObject(finalizedFailureDelivery.result).reply_anchor_mismatch || false)} expected=${String(safeSelftestObject(finalizedFailureDelivery.result).expected_reply_to_message_id || "(none)")} observed=${String(safeSelftestObject(finalizedFailureDelivery.result).observed_reply_to_message_id || "(none)")}`,
|
|
19047
|
+
);
|
|
19048
|
+
} catch (err) {
|
|
19049
|
+
push("runner_failure_delivery_outcome_preserves_module_4_reply_anchor_on_mismatch", false, String(err?.message || err));
|
|
19050
|
+
}
|
|
19051
|
+
|
|
19052
|
+
try {
|
|
19053
|
+
const finalizedFailureDelivery = finalizeRunnerFailureReplyDeliveryOutcome({
|
|
19054
|
+
processed: {
|
|
19055
|
+
kind: "error",
|
|
19056
|
+
result: {
|
|
19057
|
+
failure_reply_text: "I could not finish this request.",
|
|
19058
|
+
last_reply_message_id: 11,
|
|
19059
|
+
},
|
|
19060
|
+
},
|
|
19061
|
+
routeKey: "route-failure-delivery-thread-mismatch-1",
|
|
19062
|
+
deliveryResult: {
|
|
19063
|
+
delivery: {
|
|
19064
|
+
dryRun: false,
|
|
19065
|
+
effectiveMessageThreadID: 99,
|
|
19066
|
+
effectiveReplyToMessageID: 33,
|
|
19067
|
+
body: {
|
|
19068
|
+
result: {
|
|
19069
|
+
message_id: 44,
|
|
19070
|
+
},
|
|
19071
|
+
},
|
|
19072
|
+
},
|
|
19073
|
+
archive: {
|
|
19074
|
+
ok: true,
|
|
19075
|
+
},
|
|
19076
|
+
},
|
|
19077
|
+
deliveryHandoff: {
|
|
19078
|
+
messageThreadID: 22,
|
|
19079
|
+
replyToMessageID: 33,
|
|
19080
|
+
},
|
|
19081
|
+
loadRouteState: () => ({}),
|
|
19082
|
+
saveRunnerRouteState: () => {},
|
|
19083
|
+
});
|
|
19084
|
+
push(
|
|
19085
|
+
"runner_failure_delivery_outcome_preserves_module_4_message_thread_on_mismatch",
|
|
19086
|
+
intFromRawAllowZero(safeSelftestObject(finalizedFailureDelivery.result).last_reply_message_thread_id, 0) === 22
|
|
19087
|
+
&& safeSelftestObject(finalizedFailureDelivery.result).message_thread_mismatch === true
|
|
19088
|
+
&& intFromRawAllowZero(safeSelftestObject(finalizedFailureDelivery.result).expected_message_thread_id, 0) === 22
|
|
19089
|
+
&& intFromRawAllowZero(safeSelftestObject(finalizedFailureDelivery.result).observed_message_thread_id, 0) === 99
|
|
19090
|
+
&& /expected 22, observed 99/i.test(String(safeSelftestObject(finalizedFailureDelivery.result).message_thread_error || "")),
|
|
19091
|
+
`thread=${String(safeSelftestObject(finalizedFailureDelivery.result).last_reply_message_thread_id || "(none)")} mismatch=${String(safeSelftestObject(finalizedFailureDelivery.result).message_thread_mismatch || false)} expected=${String(safeSelftestObject(finalizedFailureDelivery.result).expected_message_thread_id || "(none)")} observed=${String(safeSelftestObject(finalizedFailureDelivery.result).observed_message_thread_id || "(none)")}`,
|
|
19092
|
+
);
|
|
19093
|
+
} catch (err) {
|
|
19094
|
+
push("runner_failure_delivery_outcome_preserves_module_4_message_thread_on_mismatch", false, String(err?.message || err));
|
|
19095
|
+
}
|
|
19096
|
+
|
|
19006
19097
|
try {
|
|
19007
19098
|
const activePatch = buildRunnerRootWorkItemRoutePatch({
|
|
19008
19099
|
syncedRequest: {
|
|
@@ -20260,6 +20351,137 @@ export async function runSelftestRunnerScenarios(push, deps) {
|
|
|
20260
20351
|
push("runner_selected_record_delivery_context_stays_within_module_4_boundary", false, String(err?.message || err));
|
|
20261
20352
|
}
|
|
20262
20353
|
|
|
20354
|
+
try {
|
|
20355
|
+
const savedStates = [];
|
|
20356
|
+
const ingress = prepareRunnerSelectedRecordIngress({
|
|
20357
|
+
routeKey: "route-ingress-reply-fallback-1",
|
|
20358
|
+
routeState: {},
|
|
20359
|
+
selectedRecord: {
|
|
20360
|
+
id: "comment-ingress-reply-fallback-1",
|
|
20361
|
+
parsedArchive: {
|
|
20362
|
+
kind: "telegram_message",
|
|
20363
|
+
senderIsBot: false,
|
|
20364
|
+
messageID: 4703,
|
|
20365
|
+
},
|
|
20366
|
+
},
|
|
20367
|
+
persistedHumanIntentRequest: null,
|
|
20368
|
+
precomputedHumanInboundVisibility: {
|
|
20369
|
+
applies: true,
|
|
20370
|
+
executable: true,
|
|
20371
|
+
visibilityMode: "reply_chain",
|
|
20372
|
+
visibilityStatus: "visible",
|
|
20373
|
+
visibilityReason: "",
|
|
20374
|
+
visibilitySource: "local_receipt",
|
|
20375
|
+
candidateBotUsernames: ["alpha_bot"],
|
|
20376
|
+
sourceMessageEnvelope: {
|
|
20377
|
+
reply_to_message_id: 4702,
|
|
20378
|
+
message_thread_id: 82,
|
|
20379
|
+
source_origin: "local_receipt",
|
|
20380
|
+
},
|
|
20381
|
+
},
|
|
20382
|
+
currentBotSelector: "alpha_bot",
|
|
20383
|
+
triggerDecision: {
|
|
20384
|
+
shouldRespond: true,
|
|
20385
|
+
trigger: "reply_to_bot",
|
|
20386
|
+
candidateBotUsernames: ["alpha_bot"],
|
|
20387
|
+
},
|
|
20388
|
+
saveRunnerRouteState: (_routeKey, patch) => {
|
|
20389
|
+
savedStates.push(patch);
|
|
20390
|
+
},
|
|
20391
|
+
deps: {
|
|
20392
|
+
hasPrecomputedRunnerTriggerDecision: (decision) => typeof decision?.shouldRespond === "boolean",
|
|
20393
|
+
buildRunnerTriggerStatePatch: () => ({ last_trigger_candidate_bot_usernames: ["alpha_bot"] }),
|
|
20394
|
+
buildRunnerRouteStateFromComment: (_comment, patch) => patch,
|
|
20395
|
+
intFromRawAllowZero: (raw, fallback = 0) => {
|
|
20396
|
+
const numeric = Number.parseInt(String(raw ?? ""), 10);
|
|
20397
|
+
return Number.isFinite(numeric) ? numeric : fallback;
|
|
20398
|
+
},
|
|
20399
|
+
shouldRunnerTriggerProceed: (decision) => decision?.shouldRespond === true,
|
|
20400
|
+
resolveRunnerHumanInboundVisibility: () => {
|
|
20401
|
+
throw new Error("ingress helper should use provided visibility before recomputing");
|
|
20402
|
+
},
|
|
20403
|
+
resolveRunnerDeliverySourceMessageEnvelope: () => {
|
|
20404
|
+
throw new Error("ingress helper should not build fallback source when visibility already supplies one");
|
|
20405
|
+
},
|
|
20406
|
+
},
|
|
20407
|
+
});
|
|
20408
|
+
push(
|
|
20409
|
+
"runner_selected_record_ingress_resolves_reply_anchor_once_from_source_reply_to",
|
|
20410
|
+
!ingress.handledResult
|
|
20411
|
+
&& ingress.replyToMessageID === 4702
|
|
20412
|
+
&& ingress.replyMessageThreadID === 82
|
|
20413
|
+
&& ingress.replyAnchorSource === "local_receipt"
|
|
20414
|
+
&& savedStates.length === 0,
|
|
20415
|
+
`replyTo=${String(ingress.replyToMessageID || 0)} thread=${String(ingress.replyMessageThreadID || 0)} anchor=${String(ingress.replyAnchorSource || "(none)")} savedStates=${savedStates.length}`,
|
|
20416
|
+
);
|
|
20417
|
+
} catch (err) {
|
|
20418
|
+
push("runner_selected_record_ingress_resolves_reply_anchor_once_from_source_reply_to", false, String(err?.message || err));
|
|
20419
|
+
}
|
|
20420
|
+
|
|
20421
|
+
try {
|
|
20422
|
+
const prepared = await prepareRunnerSelectedRecordDeliveryContext({
|
|
20423
|
+
aiResult: {
|
|
20424
|
+
reply: "reply without explicit anchor",
|
|
20425
|
+
},
|
|
20426
|
+
bot: {
|
|
20427
|
+
name: "RyoAI_bot",
|
|
20428
|
+
username: "RyoAI_bot",
|
|
20429
|
+
},
|
|
20430
|
+
selectedRecord: {
|
|
20431
|
+
id: "comment-delivery-context-anchor-fallback",
|
|
20432
|
+
},
|
|
20433
|
+
currentBotSelector: "ryoai_bot",
|
|
20434
|
+
executionContract: {
|
|
20435
|
+
type: "direct_result",
|
|
20436
|
+
assignments: [],
|
|
20437
|
+
nextResponders: [],
|
|
20438
|
+
},
|
|
20439
|
+
effectiveTriggerDecision: {
|
|
20440
|
+
trigger: "mention",
|
|
20441
|
+
},
|
|
20442
|
+
effectiveConversationContext: {
|
|
20443
|
+
mode: "single_bot",
|
|
20444
|
+
stage: "human_opening",
|
|
20445
|
+
intentMode: "single_bot",
|
|
20446
|
+
leadBotUsername: "ryoai_bot",
|
|
20447
|
+
},
|
|
20448
|
+
effectiveResolvedIntentMode: "single_bot",
|
|
20449
|
+
directHumanPeerMap: new Map(),
|
|
20450
|
+
responseContractValidation: {
|
|
20451
|
+
ok: true,
|
|
20452
|
+
status: "valid",
|
|
20453
|
+
reason: "",
|
|
20454
|
+
targets: [],
|
|
20455
|
+
},
|
|
20456
|
+
sourceMessageEnvelope: {
|
|
20457
|
+
chat_id: "-1001",
|
|
20458
|
+
message_id: 7001,
|
|
20459
|
+
source_origin: "local_telegram_inbound",
|
|
20460
|
+
},
|
|
20461
|
+
replyToMessageID: 6123,
|
|
20462
|
+
replyMessageThreadID: 0,
|
|
20463
|
+
deps: {
|
|
20464
|
+
normalizeMentionSelector: normalizeSelftestMentionSelector,
|
|
20465
|
+
sanitizeForcedDirectReplyText: ({ replyText }) => String(replyText || "").trim(),
|
|
20466
|
+
buildTelegramBotReplyEnvelope: ({ sourceEnvelope, replyToMessageID, body }) => ({
|
|
20467
|
+
chat_id: sourceEnvelope?.chat_id || "",
|
|
20468
|
+
message_id: sourceEnvelope?.message_id || 0,
|
|
20469
|
+
reply_to_message_id: replyToMessageID,
|
|
20470
|
+
body,
|
|
20471
|
+
}),
|
|
20472
|
+
collectExecutionContractNextResponders: () => [],
|
|
20473
|
+
extractManagedPeerMentionSelectors: () => [],
|
|
20474
|
+
},
|
|
20475
|
+
});
|
|
20476
|
+
push(
|
|
20477
|
+
"runner_selected_record_delivery_context_uses_module_4_resolved_reply_anchor",
|
|
20478
|
+
String(prepared.attemptedDeliveryEnvelope?.reply_to_message_id || "") === "6123",
|
|
20479
|
+
`replyTo=${String(prepared.attemptedDeliveryEnvelope?.reply_to_message_id || "(none)")}`,
|
|
20480
|
+
);
|
|
20481
|
+
} catch (err) {
|
|
20482
|
+
push("runner_selected_record_delivery_context_uses_module_4_resolved_reply_anchor", false, String(err?.message || err));
|
|
20483
|
+
}
|
|
20484
|
+
|
|
20263
20485
|
try {
|
|
20264
20486
|
const prepared = await prepareRunnerSelectedRecordDeliveryContext({
|
|
20265
20487
|
aiResult: {
|
|
@@ -20395,6 +20617,65 @@ export async function runSelftestRunnerScenarios(push, deps) {
|
|
|
20395
20617
|
push("runner_selected_record_delivery_handoff_stays_within_4_to_6_boundary", false, String(err?.message || err));
|
|
20396
20618
|
}
|
|
20397
20619
|
|
|
20620
|
+
try {
|
|
20621
|
+
const handoff = prepareRunnerSelectedRecordDeliveryHandoff({
|
|
20622
|
+
runtime: {
|
|
20623
|
+
baseURL: "https://example.test",
|
|
20624
|
+
token: "selftest-token",
|
|
20625
|
+
timeoutSeconds: 5,
|
|
20626
|
+
actor: { user_id: "user-delivery-handoff-anchor-fallback" },
|
|
20627
|
+
},
|
|
20628
|
+
bot: {
|
|
20629
|
+
id: "bot-delivery-handoff-anchor-fallback",
|
|
20630
|
+
name: "RyoAI_bot",
|
|
20631
|
+
username: "RyoAI_bot",
|
|
20632
|
+
role: "monitor",
|
|
20633
|
+
provider: "telegram",
|
|
20634
|
+
},
|
|
20635
|
+
normalizedRoute: {
|
|
20636
|
+
projectID: "project-delivery-handoff-anchor-fallback",
|
|
20637
|
+
provider: "telegram",
|
|
20638
|
+
dryRunDelivery: true,
|
|
20639
|
+
archivePolicy: {
|
|
20640
|
+
mirrorReplies: true,
|
|
20641
|
+
dedupeOutbound: true,
|
|
20642
|
+
},
|
|
20643
|
+
},
|
|
20644
|
+
destination: {
|
|
20645
|
+
id: "dest-delivery-handoff-anchor-fallback",
|
|
20646
|
+
label: "Main Room",
|
|
20647
|
+
},
|
|
20648
|
+
sanitizedReplyText: "Anchor from source envelope.",
|
|
20649
|
+
replyMessageThreadID: 0,
|
|
20650
|
+
replyToMessageID: 7788,
|
|
20651
|
+
sourceMessageEnvelope: {
|
|
20652
|
+
chat_id: "-2002",
|
|
20653
|
+
message_id: 7002,
|
|
20654
|
+
source_origin: "local_telegram_inbound",
|
|
20655
|
+
},
|
|
20656
|
+
archiveThread: {
|
|
20657
|
+
threadID: "thread-delivery-handoff-anchor-fallback",
|
|
20658
|
+
workItemID: "workitem-delivery-handoff-anchor-fallback",
|
|
20659
|
+
},
|
|
20660
|
+
effectiveConversationContext: {
|
|
20661
|
+
id: "conversation-delivery-handoff-anchor-fallback",
|
|
20662
|
+
mode: "single_bot",
|
|
20663
|
+
stage: "human_opening",
|
|
20664
|
+
},
|
|
20665
|
+
executionContract: {
|
|
20666
|
+
type: "direct_result",
|
|
20667
|
+
},
|
|
20668
|
+
buildRunnerDeliveryDeps: () => ({ test: true }),
|
|
20669
|
+
});
|
|
20670
|
+
push(
|
|
20671
|
+
"runner_selected_record_delivery_handoff_uses_module_4_resolved_reply_anchor",
|
|
20672
|
+
String(handoff.replyToMessageID || "") === "7788",
|
|
20673
|
+
`replyTo=${String(handoff.replyToMessageID || "(none)")}`,
|
|
20674
|
+
);
|
|
20675
|
+
} catch (err) {
|
|
20676
|
+
push("runner_selected_record_delivery_handoff_uses_module_4_resolved_reply_anchor", false, String(err?.message || err));
|
|
20677
|
+
}
|
|
20678
|
+
|
|
20398
20679
|
try {
|
|
20399
20680
|
const savedStates = [];
|
|
20400
20681
|
const finalized = await finalizeRunnerSelectedRecordReplyOutcome({
|
|
@@ -20545,6 +20826,152 @@ export async function runSelftestRunnerScenarios(push, deps) {
|
|
|
20545
20826
|
push("runner_selected_record_reply_outcome_stays_within_module_4_boundary", false, String(err?.message || err));
|
|
20546
20827
|
}
|
|
20547
20828
|
|
|
20829
|
+
try {
|
|
20830
|
+
const savedStates = [];
|
|
20831
|
+
const finalized = await finalizeRunnerSelectedRecordReplyOutcome({
|
|
20832
|
+
routeKey: "route-reply-outcome-thread-mismatch-1",
|
|
20833
|
+
normalizedRoute: {
|
|
20834
|
+
name: "Reply Outcome Thread Mismatch Route",
|
|
20835
|
+
},
|
|
20836
|
+
archiveThread: {
|
|
20837
|
+
threadID: "thread-reply-outcome-thread-mismatch-1",
|
|
20838
|
+
},
|
|
20839
|
+
selectedRecord: {
|
|
20840
|
+
id: "comment-reply-outcome-thread-mismatch-1",
|
|
20841
|
+
parsedArchive: {
|
|
20842
|
+
senderIsBot: false,
|
|
20843
|
+
},
|
|
20844
|
+
},
|
|
20845
|
+
effectiveTriggerDecision: {
|
|
20846
|
+
trigger: "precomputed_human_intent_contract",
|
|
20847
|
+
},
|
|
20848
|
+
effectiveConversationContext: {
|
|
20849
|
+
id: "conversation-reply-outcome-thread-mismatch-1",
|
|
20850
|
+
stage: "lead_kickoff",
|
|
20851
|
+
intentMode: "multi_bot_collab",
|
|
20852
|
+
leadBotUsername: "leadbot",
|
|
20853
|
+
summaryBotUsername: "",
|
|
20854
|
+
participantSelectors: ["leadbot", "peerbot"],
|
|
20855
|
+
initialResponderSelectors: ["leadbot"],
|
|
20856
|
+
allowedResponderSelectors: ["leadbot", "peerbot"],
|
|
20857
|
+
allowBotToBot: true,
|
|
20858
|
+
replyExpectation: "public_reply",
|
|
20859
|
+
},
|
|
20860
|
+
executionContract: {
|
|
20861
|
+
type: "delegation",
|
|
20862
|
+
actionable: true,
|
|
20863
|
+
},
|
|
20864
|
+
normalizedExecutionContractType: "delegation",
|
|
20865
|
+
normalizedExecutionTargets: ["peerbot"],
|
|
20866
|
+
normalizedExecutionNextResponders: ["peerbot"],
|
|
20867
|
+
artifactValidation: {
|
|
20868
|
+
status: "none",
|
|
20869
|
+
},
|
|
20870
|
+
aiResult: {},
|
|
20871
|
+
authoritativeDecisionBundle: {
|
|
20872
|
+
schema_version: "conversation_decision.v1",
|
|
20873
|
+
decision_type: "reply_outcome",
|
|
20874
|
+
},
|
|
20875
|
+
projectContextSuggestion: {},
|
|
20876
|
+
bot: {
|
|
20877
|
+
name: "Lead Bot",
|
|
20878
|
+
username: "leadbot",
|
|
20879
|
+
},
|
|
20880
|
+
sourceMessageEnvelope: {
|
|
20881
|
+
source_origin: "local_telegram_inbound",
|
|
20882
|
+
message_id: 4900,
|
|
20883
|
+
message_thread_id: 93,
|
|
20884
|
+
},
|
|
20885
|
+
attemptedDeliveryEnvelope: {
|
|
20886
|
+
message_id: 4900,
|
|
20887
|
+
},
|
|
20888
|
+
humanInboundVisibility: {
|
|
20889
|
+
visibilityStatus: "local",
|
|
20890
|
+
visibilityReason: "",
|
|
20891
|
+
visibilitySource: "local_receipt",
|
|
20892
|
+
},
|
|
20893
|
+
replyToMessageID: 4900,
|
|
20894
|
+
replyMessageThreadID: 93,
|
|
20895
|
+
replyAnchorSource: "local_receipt",
|
|
20896
|
+
responseContractValidation: {
|
|
20897
|
+
status: "valid",
|
|
20898
|
+
reason: "",
|
|
20899
|
+
targets: [],
|
|
20900
|
+
},
|
|
20901
|
+
assignmentExecutionValidation: {
|
|
20902
|
+
status: "direct_execution",
|
|
20903
|
+
reason: "",
|
|
20904
|
+
assignmentModes: [],
|
|
20905
|
+
},
|
|
20906
|
+
responderStatePatch: {},
|
|
20907
|
+
intentStatePatch: {},
|
|
20908
|
+
visibilityStatePatch: {},
|
|
20909
|
+
effectiveExecutionPlan: {
|
|
20910
|
+
mode: "lookup_only",
|
|
20911
|
+
roleProfileName: "monitor",
|
|
20912
|
+
workspaceDir: "C:\\selftest",
|
|
20913
|
+
usedCommandFallback: false,
|
|
20914
|
+
},
|
|
20915
|
+
executedRolePlan: {},
|
|
20916
|
+
sanitizedReplyText: "bot replied",
|
|
20917
|
+
aiReplyGeneratedAt: "2026-03-30T00:00:00.000Z",
|
|
20918
|
+
aiReplyPreview: "bot replied",
|
|
20919
|
+
deliveryResult: {
|
|
20920
|
+
delivery: {
|
|
20921
|
+
dryRun: false,
|
|
20922
|
+
effectiveMessageThreadID: 199,
|
|
20923
|
+
effectiveReplyToMessageID: 4900,
|
|
20924
|
+
body: {
|
|
20925
|
+
result: {
|
|
20926
|
+
message_id: 4901,
|
|
20927
|
+
},
|
|
20928
|
+
},
|
|
20929
|
+
},
|
|
20930
|
+
archive: {
|
|
20931
|
+
ok: true,
|
|
20932
|
+
},
|
|
20933
|
+
},
|
|
20934
|
+
saveRunnerRouteState: (_routeKey, patch) => {
|
|
20935
|
+
savedStates.push(patch);
|
|
20936
|
+
},
|
|
20937
|
+
emitRunnerStage: () => {},
|
|
20938
|
+
deps: {
|
|
20939
|
+
buildRunnerRouteStateFromComment: (_comment, patch) => patch,
|
|
20940
|
+
summarizeValidatedArtifactPaths: () => [],
|
|
20941
|
+
intFromRawAllowZero: (raw, fallback = 0) => {
|
|
20942
|
+
const numeric = Number.parseInt(String(raw ?? ""), 10);
|
|
20943
|
+
return Number.isFinite(numeric) ? numeric : fallback;
|
|
20944
|
+
},
|
|
20945
|
+
normalizeMentionSelector: normalizeSelftestMentionSelector,
|
|
20946
|
+
formatConversationContractSummary: () => "contract=delegation",
|
|
20947
|
+
maybeCreateSuggestedProjectContext: async () => ({ created: false, reason: "message_is_interrogative" }),
|
|
20948
|
+
buildConversationSessionsPatch: (_routeState, _conversationContext, patch) => patch,
|
|
20949
|
+
normalizeConversationReplyFingerprint: (text) => String(text || "").trim(),
|
|
20950
|
+
buildTelegramBotReplyEnvelope: ({ messageID, messageThreadID, replyToMessageID, body }) => ({
|
|
20951
|
+
message_id: messageID,
|
|
20952
|
+
message_thread_id: messageThreadID,
|
|
20953
|
+
reply_to_message_id: replyToMessageID,
|
|
20954
|
+
body,
|
|
20955
|
+
}),
|
|
20956
|
+
publicMultiBotDefaultMaxTurns: 6,
|
|
20957
|
+
publicMultiBotDefaultTtlMs: 300000,
|
|
20958
|
+
},
|
|
20959
|
+
});
|
|
20960
|
+
push(
|
|
20961
|
+
"runner_selected_record_reply_outcome_preserves_module_4_message_thread_on_mismatch",
|
|
20962
|
+
finalized.kind === "replied"
|
|
20963
|
+
&& savedStates.length === 1
|
|
20964
|
+
&& intFromRawAllowZero(finalized.result?.last_reply_message_thread_id, 0) === 93
|
|
20965
|
+
&& finalized.result?.message_thread_mismatch === true
|
|
20966
|
+
&& intFromRawAllowZero(finalized.result?.expected_message_thread_id, 0) === 93
|
|
20967
|
+
&& intFromRawAllowZero(finalized.result?.observed_message_thread_id, 0) === 199
|
|
20968
|
+
&& /expected 93, observed 199/i.test(String(finalized.result?.message_thread_error || "")),
|
|
20969
|
+
`thread=${String(finalized.result?.last_reply_message_thread_id || "(none)")} mismatch=${String(finalized.result?.message_thread_mismatch || false)} expected=${String(finalized.result?.expected_message_thread_id || "(none)")} observed=${String(finalized.result?.observed_message_thread_id || "(none)")}`,
|
|
20970
|
+
);
|
|
20971
|
+
} catch (err) {
|
|
20972
|
+
push("runner_selected_record_reply_outcome_preserves_module_4_message_thread_on_mismatch", false, String(err?.message || err));
|
|
20973
|
+
}
|
|
20974
|
+
|
|
20548
20975
|
try {
|
|
20549
20976
|
const finalized = finalizeExecutionPlanSteps(
|
|
20550
20977
|
{
|
|
@@ -21113,6 +21540,154 @@ export async function runSelftestRunnerScenarios(push, deps) {
|
|
|
21113
21540
|
push("runner_delivery_archive_handoff_stays_within_module_6_boundary", false, String(err?.message || err));
|
|
21114
21541
|
}
|
|
21115
21542
|
|
|
21543
|
+
try {
|
|
21544
|
+
let createCommentCalls = 0;
|
|
21545
|
+
const archivedReply = await finalizeLocalBotDeliveryArchive({
|
|
21546
|
+
siteBaseURL: "https://example.test",
|
|
21547
|
+
token: "token-delivery-archive-mismatch-1",
|
|
21548
|
+
timeoutSeconds: 10,
|
|
21549
|
+
actorUserID: "actor-delivery-archive-mismatch-1",
|
|
21550
|
+
projectID: "project-delivery-archive-mismatch-1",
|
|
21551
|
+
provider: "telegram",
|
|
21552
|
+
destination: {
|
|
21553
|
+
id: "dest-delivery-archive-mismatch-1",
|
|
21554
|
+
provider: "telegram",
|
|
21555
|
+
label: "Delivery Archive Mismatch",
|
|
21556
|
+
chatID: "-100558",
|
|
21557
|
+
},
|
|
21558
|
+
bot: {
|
|
21559
|
+
id: "bot-delivery-archive-mismatch-1",
|
|
21560
|
+
name: "DeliveryArchiveMismatchBot",
|
|
21561
|
+
username: "deliveryarchivemismatchbot",
|
|
21562
|
+
role: "monitor",
|
|
21563
|
+
},
|
|
21564
|
+
text: "archive mismatch delivery",
|
|
21565
|
+
messageThreadID: 77,
|
|
21566
|
+
replyToMessageID: 55,
|
|
21567
|
+
archiveReplies: true,
|
|
21568
|
+
archiveDedupeOutbound: true,
|
|
21569
|
+
archiveThreadID: "thread-delivery-archive-mismatch-1",
|
|
21570
|
+
archiveWorkItemID: "workitem-delivery-archive-mismatch-1",
|
|
21571
|
+
archiveConversation: {
|
|
21572
|
+
id: "delivery-archive-mismatch-conversation",
|
|
21573
|
+
},
|
|
21574
|
+
dryRun: false,
|
|
21575
|
+
delivery: {
|
|
21576
|
+
body: {
|
|
21577
|
+
result: {
|
|
21578
|
+
message_id: 502,
|
|
21579
|
+
message_thread_id: 77,
|
|
21580
|
+
},
|
|
21581
|
+
},
|
|
21582
|
+
effectiveReplyToMessageID: 66,
|
|
21583
|
+
effectiveMessageThreadID: 77,
|
|
21584
|
+
},
|
|
21585
|
+
formatBotReplyArchiveComment,
|
|
21586
|
+
findArchivedBotReplyRecord,
|
|
21587
|
+
deps: {
|
|
21588
|
+
discoverArchiveThreadForDestination: async () => ({
|
|
21589
|
+
threadID: "thread-delivery-archive-mismatch-1",
|
|
21590
|
+
workItemID: "workitem-delivery-archive-mismatch-1",
|
|
21591
|
+
}),
|
|
21592
|
+
listThreadComments: async () => [],
|
|
21593
|
+
listThreadCommentsTail: async () => [],
|
|
21594
|
+
createThreadComment: async () => {
|
|
21595
|
+
createCommentCalls += 1;
|
|
21596
|
+
return {
|
|
21597
|
+
id: "comment-delivery-archive-mismatch-1",
|
|
21598
|
+
};
|
|
21599
|
+
},
|
|
21600
|
+
parseArchivedChatComment,
|
|
21601
|
+
},
|
|
21602
|
+
});
|
|
21603
|
+
push(
|
|
21604
|
+
"runner_delivery_archive_reveals_reply_anchor_mismatch_instead_of_masking",
|
|
21605
|
+
archivedReply.ok === false
|
|
21606
|
+
&& archivedReply.reply_anchor_mismatch === true
|
|
21607
|
+
&& intFromRawAllowZero(archivedReply.expected_reply_to_message_id, 0) === 55
|
|
21608
|
+
&& intFromRawAllowZero(archivedReply.observed_reply_to_message_id, 0) === 66
|
|
21609
|
+
&& createCommentCalls === 0
|
|
21610
|
+
&& /expected 55, observed 66/i.test(String(archivedReply.error || "")),
|
|
21611
|
+
`ok=${String(archivedReply.ok)} mismatch=${String(archivedReply.reply_anchor_mismatch || false)} expected=${String(archivedReply.expected_reply_to_message_id || "(none)")} observed=${String(archivedReply.observed_reply_to_message_id || "(none)")} created=${createCommentCalls}`,
|
|
21612
|
+
);
|
|
21613
|
+
} catch (err) {
|
|
21614
|
+
push("runner_delivery_archive_reveals_reply_anchor_mismatch_instead_of_masking", false, String(err?.message || err));
|
|
21615
|
+
}
|
|
21616
|
+
|
|
21617
|
+
try {
|
|
21618
|
+
let createCommentCalls = 0;
|
|
21619
|
+
const archivedReply = await finalizeLocalBotDeliveryArchive({
|
|
21620
|
+
siteBaseURL: "https://example.test",
|
|
21621
|
+
token: "token-delivery-thread-mismatch-1",
|
|
21622
|
+
timeoutSeconds: 10,
|
|
21623
|
+
actorUserID: "actor-delivery-thread-mismatch-1",
|
|
21624
|
+
projectID: "project-delivery-thread-mismatch-1",
|
|
21625
|
+
provider: "telegram",
|
|
21626
|
+
destination: {
|
|
21627
|
+
id: "dest-delivery-thread-mismatch-1",
|
|
21628
|
+
provider: "telegram",
|
|
21629
|
+
label: "Delivery Thread Mismatch",
|
|
21630
|
+
chatID: "-100559",
|
|
21631
|
+
},
|
|
21632
|
+
bot: {
|
|
21633
|
+
id: "bot-delivery-thread-mismatch-1",
|
|
21634
|
+
name: "DeliveryThreadMismatchBot",
|
|
21635
|
+
username: "deliverythreadmismatchbot",
|
|
21636
|
+
role: "monitor",
|
|
21637
|
+
},
|
|
21638
|
+
text: "archive thread mismatch delivery",
|
|
21639
|
+
messageThreadID: 77,
|
|
21640
|
+
replyToMessageID: 55,
|
|
21641
|
+
archiveReplies: true,
|
|
21642
|
+
archiveDedupeOutbound: true,
|
|
21643
|
+
archiveThreadID: "thread-delivery-thread-mismatch-1",
|
|
21644
|
+
archiveWorkItemID: "workitem-delivery-thread-mismatch-1",
|
|
21645
|
+
archiveConversation: {
|
|
21646
|
+
id: "delivery-thread-mismatch-conversation",
|
|
21647
|
+
},
|
|
21648
|
+
dryRun: false,
|
|
21649
|
+
delivery: {
|
|
21650
|
+
body: {
|
|
21651
|
+
result: {
|
|
21652
|
+
message_id: 503,
|
|
21653
|
+
message_thread_id: 88,
|
|
21654
|
+
},
|
|
21655
|
+
},
|
|
21656
|
+
effectiveReplyToMessageID: 55,
|
|
21657
|
+
effectiveMessageThreadID: 88,
|
|
21658
|
+
},
|
|
21659
|
+
formatBotReplyArchiveComment,
|
|
21660
|
+
findArchivedBotReplyRecord,
|
|
21661
|
+
deps: {
|
|
21662
|
+
discoverArchiveThreadForDestination: async () => ({
|
|
21663
|
+
threadID: "thread-delivery-thread-mismatch-1",
|
|
21664
|
+
workItemID: "workitem-delivery-thread-mismatch-1",
|
|
21665
|
+
}),
|
|
21666
|
+
listThreadComments: async () => [],
|
|
21667
|
+
listThreadCommentsTail: async () => [],
|
|
21668
|
+
createThreadComment: async () => {
|
|
21669
|
+
createCommentCalls += 1;
|
|
21670
|
+
return {
|
|
21671
|
+
id: "comment-delivery-thread-mismatch-1",
|
|
21672
|
+
};
|
|
21673
|
+
},
|
|
21674
|
+
parseArchivedChatComment,
|
|
21675
|
+
},
|
|
21676
|
+
});
|
|
21677
|
+
push(
|
|
21678
|
+
"runner_delivery_archive_reveals_message_thread_mismatch_instead_of_masking",
|
|
21679
|
+
archivedReply.ok === false
|
|
21680
|
+
&& archivedReply.message_thread_mismatch === true
|
|
21681
|
+
&& intFromRawAllowZero(archivedReply.expected_message_thread_id, 0) === 77
|
|
21682
|
+
&& intFromRawAllowZero(archivedReply.observed_message_thread_id, 0) === 88
|
|
21683
|
+
&& createCommentCalls === 0
|
|
21684
|
+
&& /expected 77, observed 88/i.test(String(archivedReply.error || "")),
|
|
21685
|
+
`ok=${String(archivedReply.ok)} mismatch=${String(archivedReply.message_thread_mismatch || false)} expected=${String(archivedReply.expected_message_thread_id || "(none)")} observed=${String(archivedReply.observed_message_thread_id || "(none)")} created=${createCommentCalls}`,
|
|
21686
|
+
);
|
|
21687
|
+
} catch (err) {
|
|
21688
|
+
push("runner_delivery_archive_reveals_message_thread_mismatch_instead_of_masking", false, String(err?.message || err));
|
|
21689
|
+
}
|
|
21690
|
+
|
|
21116
21691
|
try {
|
|
21117
21692
|
const finalizedDeliveryResult = finalizeLocalBotDeliveryResult({
|
|
21118
21693
|
provider: "telegram",
|