ARCH: прикрепить debug MCP discovery
This commit is contained in:
parent
76db8ef012
commit
75e665e836
|
|
@ -891,6 +891,36 @@ Validation:
|
|||
- `npm test -- assistantMcpDiscoveryRuntimeEntryPoint.test.ts assistantMcpDiscoveryTurnInputAdapter.test.ts assistantMcpDiscoveryPolicy.test.ts assistantMcpCatalogIndex.test.ts assistantMcpDiscoveryPlanner.test.ts assistantMcpDiscoveryRuntimeAdapter.test.ts assistantMcpDiscoveryPilotExecutor.test.ts assistantMcpDiscoveryAnswerAdapter.test.ts assistantMcpDiscoveryRuntimeBridge.test.ts` passed 40/40;
|
||||
- `npm run build` passed.
|
||||
|
||||
## Progress Update - 2026-04-20 MCP Discovery Debug Attachment
|
||||
|
||||
The tenth implementation slice of Big Block 5 added a debug/evidence attachment layer:
|
||||
|
||||
- `assistantMcpDiscoveryDebugAttachment.ts`
|
||||
- `assistantMcpDiscoveryDebugAttachment.test.ts`
|
||||
|
||||
It is now attached to:
|
||||
|
||||
- address-lane response runtime debug;
|
||||
- deep-analysis debug payloads.
|
||||
|
||||
This still does not execute MCP discovery automatically and still does not change the user-facing answer.
|
||||
|
||||
It gives runtime and replay review a stable observable surface:
|
||||
|
||||
- `assistant_mcp_discovery_entry_point_v1`;
|
||||
- `mcp_discovery_entry_status`;
|
||||
- `mcp_discovery_attempted`;
|
||||
- `mcp_discovery_hot_runtime_wired=false`;
|
||||
- `mcp_discovery_bridge_status`;
|
||||
- `mcp_discovery_answer_mode`;
|
||||
- business-fact/user-facing authorization flags;
|
||||
- clarification flag.
|
||||
|
||||
Validation:
|
||||
|
||||
- `npm test -- assistantMcpDiscoveryDebugAttachment.test.ts assistantDebugPayloadAssembler.test.ts assistantAddressLaneResponseRuntimeAdapter.test.ts assistantMcpDiscoveryRuntimeEntryPoint.test.ts` passed 13/13;
|
||||
- `npm run build` passed.
|
||||
|
||||
## Execution Rule
|
||||
|
||||
Do not implement this plan as:
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ exports.runAssistantAddressLaneResponseRuntime = runAssistantAddressLaneResponse
|
|||
const assistantAddressTurnFinalizeRuntimeAdapter_1 = require("./assistantAddressTurnFinalizeRuntimeAdapter");
|
||||
const assistantCapabilityBindingResponseGuard_1 = require("./assistantCapabilityBindingResponseGuard");
|
||||
const assistantCapabilityRuntimeBindingAdapter_1 = require("./assistantCapabilityRuntimeBindingAdapter");
|
||||
const assistantMcpDiscoveryDebugAttachment_1 = require("./assistantMcpDiscoveryDebugAttachment");
|
||||
const assistantRuntimeContractResolver_1 = require("./assistantRuntimeContractResolver");
|
||||
const assistantStateTransitionRuntimeAdapter_1 = require("./assistantStateTransitionRuntimeAdapter");
|
||||
const assistantTruthAnswerPolicyRuntimeAdapter_1 = require("./assistantTruthAnswerPolicyRuntimeAdapter");
|
||||
|
|
@ -208,13 +209,16 @@ function runAssistantAddressLaneResponseRuntime(input) {
|
|||
addressRuntimeMeta: input.llmPreDecomposeMeta,
|
||||
replyType: normalizeAddressReplyType(input.addressLane.reply_type)
|
||||
});
|
||||
const debugWithMcpDiscovery = (0, assistantMcpDiscoveryDebugAttachment_1.attachAssistantMcpDiscoveryDebug)(debugWithCapabilityBinding, {
|
||||
addressRuntimeMeta: input.llmPreDecomposeMeta
|
||||
});
|
||||
const guardedResponse = (0, assistantCapabilityBindingResponseGuard_1.applyAssistantCapabilityBindingResponseGuard)({
|
||||
assistantReply: safeAddressReply,
|
||||
replyType: normalizeAddressReplyType(input.addressLane.reply_type),
|
||||
capabilityBinding: debugWithCapabilityBinding.assistant_capability_binding_v1
|
||||
capabilityBinding: debugWithMcpDiscovery.assistant_capability_binding_v1
|
||||
});
|
||||
const debugWithResponseGuard = {
|
||||
...debugWithCapabilityBinding,
|
||||
...debugWithMcpDiscovery,
|
||||
capability_binding_response_guard: guardedResponse.audit
|
||||
};
|
||||
const finalization = finalizeAddressTurnSafe({
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ exports.buildAssistantBackendErrorDebugPayload = buildAssistantBackendErrorDebug
|
|||
exports.buildAddressRuntimeDebugPayload = buildAddressRuntimeDebugPayload;
|
||||
exports.buildDeepAnalysisDebugPayload = buildDeepAnalysisDebugPayload;
|
||||
const assistantCapabilityRuntimeBindingAdapter_1 = require("./assistantCapabilityRuntimeBindingAdapter");
|
||||
const assistantMcpDiscoveryDebugAttachment_1 = require("./assistantMcpDiscoveryDebugAttachment");
|
||||
const assistantRuntimeContractResolver_1 = require("./assistantRuntimeContractResolver");
|
||||
const assistantStateTransitionRuntimeAdapter_1 = require("./assistantStateTransitionRuntimeAdapter");
|
||||
const assistantTruthAnswerPolicyRuntimeAdapter_1 = require("./assistantTruthAnswerPolicyRuntimeAdapter");
|
||||
|
|
@ -240,6 +241,7 @@ function buildDeepAnalysisDebugPayload(input) {
|
|||
address_llm_predecompose_contract: input.addressRuntimeMetaForDeep?.predecomposeContract ?? null,
|
||||
address_semantic_extraction_contract: input.addressRuntimeMetaForDeep?.semanticExtractionContract ?? null,
|
||||
orchestration_contract_v1: input.addressRuntimeMetaForDeep?.orchestrationContract ?? null,
|
||||
assistant_mcp_discovery_entry_point_v1: input.addressRuntimeMetaForDeep?.mcpDiscoveryRuntimeEntryPoint ?? null,
|
||||
assistant_outcome_class_v1: input.outcomeClassV1,
|
||||
assistant_orchestration_contracts_v1: input.assistantOrchestrationContractsV1,
|
||||
answer_contract_stage4_v1: answerContractStage4Audit,
|
||||
|
|
@ -263,10 +265,13 @@ function buildDeepAnalysisDebugPayload(input) {
|
|||
coverageReport: input.coverageReport,
|
||||
replyType: "deep_analysis"
|
||||
});
|
||||
return (0, assistantCapabilityRuntimeBindingAdapter_1.attachAssistantCapabilityRuntimeBinding)(debugWithStateTransition, {
|
||||
const debugWithCapabilityBinding = (0, assistantCapabilityRuntimeBindingAdapter_1.attachAssistantCapabilityRuntimeBinding)(debugWithStateTransition, {
|
||||
addressRuntimeMeta: input.addressRuntimeMetaForDeep,
|
||||
groundingStatus: input.groundingCheck.status,
|
||||
coverageReport: input.coverageReport,
|
||||
replyType: "deep_analysis"
|
||||
});
|
||||
return (0, assistantMcpDiscoveryDebugAttachment_1.attachAssistantMcpDiscoveryDebug)(debugWithCapabilityBinding, {
|
||||
addressRuntimeMeta: input.addressRuntimeMetaForDeep
|
||||
});
|
||||
}
|
||||
|
|
|
|||
53
llm_normalizer/backend/dist/services/assistantMcpDiscoveryDebugAttachment.js
vendored
Normal file
53
llm_normalizer/backend/dist/services/assistantMcpDiscoveryDebugAttachment.js
vendored
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.buildAssistantMcpDiscoveryDebugAttachmentFields = buildAssistantMcpDiscoveryDebugAttachmentFields;
|
||||
exports.attachAssistantMcpDiscoveryDebug = attachAssistantMcpDiscoveryDebug;
|
||||
function toRecordObject(value) {
|
||||
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
||||
return null;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
function toNonEmptyString(value) {
|
||||
if (value === null || value === undefined) {
|
||||
return null;
|
||||
}
|
||||
const text = String(value).trim();
|
||||
return text.length > 0 ? text : null;
|
||||
}
|
||||
function isMcpDiscoveryEntryPointContract(value) {
|
||||
const record = toRecordObject(value);
|
||||
return (record?.schema_version === "assistant_mcp_discovery_runtime_entry_point_v1" &&
|
||||
record?.policy_owner === "assistantMcpDiscoveryRuntimeEntryPoint");
|
||||
}
|
||||
function resolveEntryPoint(input) {
|
||||
if (isMcpDiscoveryEntryPointContract(input.entryPoint)) {
|
||||
return input.entryPoint;
|
||||
}
|
||||
const runtimeMetaEntryPoint = input.addressRuntimeMeta?.mcpDiscoveryRuntimeEntryPoint ??
|
||||
input.addressRuntimeMeta?.assistantMcpDiscoveryRuntimeEntryPoint ??
|
||||
input.addressRuntimeMeta?.assistant_mcp_discovery_entry_point_v1;
|
||||
return isMcpDiscoveryEntryPointContract(runtimeMetaEntryPoint) ? runtimeMetaEntryPoint : null;
|
||||
}
|
||||
function buildAssistantMcpDiscoveryDebugAttachmentFields(input) {
|
||||
const entryPoint = resolveEntryPoint(input);
|
||||
const bridge = toRecordObject(entryPoint?.bridge);
|
||||
const answerDraft = toRecordObject(bridge?.answer_draft);
|
||||
return {
|
||||
assistant_mcp_discovery_entry_point_v1: entryPoint,
|
||||
mcp_discovery_entry_status: toNonEmptyString(entryPoint?.entry_status),
|
||||
mcp_discovery_attempted: Boolean(entryPoint?.discovery_attempted),
|
||||
mcp_discovery_hot_runtime_wired: false,
|
||||
mcp_discovery_bridge_status: toNonEmptyString(bridge?.bridge_status),
|
||||
mcp_discovery_answer_mode: toNonEmptyString(answerDraft?.answer_mode),
|
||||
mcp_discovery_business_fact_answer_allowed: bridge?.business_fact_answer_allowed === true,
|
||||
mcp_discovery_user_facing_response_allowed: bridge?.user_facing_response_allowed === true,
|
||||
mcp_discovery_requires_clarification: bridge?.requires_user_clarification === true
|
||||
};
|
||||
}
|
||||
function attachAssistantMcpDiscoveryDebug(debugPayload, input) {
|
||||
return {
|
||||
...debugPayload,
|
||||
...buildAssistantMcpDiscoveryDebugAttachmentFields(input)
|
||||
};
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ import {
|
|||
} from "./assistantAddressTurnFinalizeRuntimeAdapter";
|
||||
import { applyAssistantCapabilityBindingResponseGuard } from "./assistantCapabilityBindingResponseGuard";
|
||||
import { attachAssistantCapabilityRuntimeBinding } from "./assistantCapabilityRuntimeBindingAdapter";
|
||||
import { attachAssistantMcpDiscoveryDebug } from "./assistantMcpDiscoveryDebugAttachment";
|
||||
import { attachAssistantRuntimeContractShadow } from "./assistantRuntimeContractResolver";
|
||||
import { attachAssistantStateTransition } from "./assistantStateTransitionRuntimeAdapter";
|
||||
import { attachAssistantTruthAnswerPolicy } from "./assistantTruthAnswerPolicyRuntimeAdapter";
|
||||
|
|
@ -267,13 +268,16 @@ export function runAssistantAddressLaneResponseRuntime<ResponseType = AssistantM
|
|||
addressRuntimeMeta: input.llmPreDecomposeMeta,
|
||||
replyType: normalizeAddressReplyType(input.addressLane.reply_type)
|
||||
});
|
||||
const debugWithMcpDiscovery = attachAssistantMcpDiscoveryDebug(debugWithCapabilityBinding, {
|
||||
addressRuntimeMeta: input.llmPreDecomposeMeta
|
||||
});
|
||||
const guardedResponse = applyAssistantCapabilityBindingResponseGuard({
|
||||
assistantReply: safeAddressReply,
|
||||
replyType: normalizeAddressReplyType(input.addressLane.reply_type),
|
||||
capabilityBinding: debugWithCapabilityBinding.assistant_capability_binding_v1
|
||||
capabilityBinding: debugWithMcpDiscovery.assistant_capability_binding_v1
|
||||
});
|
||||
const debugWithResponseGuard = {
|
||||
...debugWithCapabilityBinding,
|
||||
...debugWithMcpDiscovery,
|
||||
capability_binding_response_guard: guardedResponse.audit
|
||||
};
|
||||
const finalization = finalizeAddressTurnSafe({
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import type {
|
|||
TemporalGuardAudit
|
||||
} from "./assistantRuntimeGuards";
|
||||
import { attachAssistantCapabilityRuntimeBinding } from "./assistantCapabilityRuntimeBindingAdapter";
|
||||
import { attachAssistantMcpDiscoveryDebug } from "./assistantMcpDiscoveryDebugAttachment";
|
||||
import { attachAssistantRuntimeContractShadow } from "./assistantRuntimeContractResolver";
|
||||
import { attachAssistantStateTransition } from "./assistantStateTransitionRuntimeAdapter";
|
||||
import { attachAssistantTruthAnswerPolicy } from "./assistantTruthAnswerPolicyRuntimeAdapter";
|
||||
|
|
@ -333,6 +334,7 @@ export function buildDeepAnalysisDebugPayload(input: DeepAnalysisDebugPayloadInp
|
|||
address_llm_predecompose_contract: input.addressRuntimeMetaForDeep?.predecomposeContract ?? null,
|
||||
address_semantic_extraction_contract: input.addressRuntimeMetaForDeep?.semanticExtractionContract ?? null,
|
||||
orchestration_contract_v1: input.addressRuntimeMetaForDeep?.orchestrationContract ?? null,
|
||||
assistant_mcp_discovery_entry_point_v1: input.addressRuntimeMetaForDeep?.mcpDiscoveryRuntimeEntryPoint ?? null,
|
||||
assistant_outcome_class_v1: input.outcomeClassV1,
|
||||
assistant_orchestration_contracts_v1: input.assistantOrchestrationContractsV1,
|
||||
answer_contract_stage4_v1: answerContractStage4Audit,
|
||||
|
|
@ -356,10 +358,13 @@ export function buildDeepAnalysisDebugPayload(input: DeepAnalysisDebugPayloadInp
|
|||
coverageReport: input.coverageReport as unknown as Record<string, unknown>,
|
||||
replyType: "deep_analysis"
|
||||
});
|
||||
return attachAssistantCapabilityRuntimeBinding(debugWithStateTransition, {
|
||||
const debugWithCapabilityBinding = attachAssistantCapabilityRuntimeBinding(debugWithStateTransition, {
|
||||
addressRuntimeMeta: input.addressRuntimeMetaForDeep as unknown as Record<string, unknown> | null | undefined,
|
||||
groundingStatus: input.groundingCheck.status,
|
||||
coverageReport: input.coverageReport as unknown as Record<string, unknown>,
|
||||
replyType: "deep_analysis"
|
||||
});
|
||||
return attachAssistantMcpDiscoveryDebug(debugWithCapabilityBinding, {
|
||||
addressRuntimeMeta: input.addressRuntimeMetaForDeep as unknown as Record<string, unknown> | null | undefined
|
||||
}) as unknown as AssistantDebugPayload;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,82 @@
|
|||
import type { AssistantMcpDiscoveryRuntimeEntryPointContract } from "./assistantMcpDiscoveryRuntimeEntryPoint";
|
||||
|
||||
export interface AssistantMcpDiscoveryDebugAttachmentFields {
|
||||
assistant_mcp_discovery_entry_point_v1: AssistantMcpDiscoveryRuntimeEntryPointContract | null;
|
||||
mcp_discovery_entry_status: string | null;
|
||||
mcp_discovery_attempted: boolean;
|
||||
mcp_discovery_hot_runtime_wired: false;
|
||||
mcp_discovery_bridge_status: string | null;
|
||||
mcp_discovery_answer_mode: string | null;
|
||||
mcp_discovery_business_fact_answer_allowed: boolean;
|
||||
mcp_discovery_user_facing_response_allowed: boolean;
|
||||
mcp_discovery_requires_clarification: boolean;
|
||||
}
|
||||
|
||||
export interface AttachAssistantMcpDiscoveryDebugInput {
|
||||
entryPoint?: unknown;
|
||||
addressRuntimeMeta?: Record<string, unknown> | null;
|
||||
}
|
||||
|
||||
function toRecordObject(value: unknown): Record<string, unknown> | null {
|
||||
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
||||
return null;
|
||||
}
|
||||
return value as Record<string, unknown>;
|
||||
}
|
||||
|
||||
function toNonEmptyString(value: unknown): string | null {
|
||||
if (value === null || value === undefined) {
|
||||
return null;
|
||||
}
|
||||
const text = String(value).trim();
|
||||
return text.length > 0 ? text : null;
|
||||
}
|
||||
|
||||
function isMcpDiscoveryEntryPointContract(value: unknown): value is AssistantMcpDiscoveryRuntimeEntryPointContract {
|
||||
const record = toRecordObject(value);
|
||||
return (
|
||||
record?.schema_version === "assistant_mcp_discovery_runtime_entry_point_v1" &&
|
||||
record?.policy_owner === "assistantMcpDiscoveryRuntimeEntryPoint"
|
||||
);
|
||||
}
|
||||
|
||||
function resolveEntryPoint(input: AttachAssistantMcpDiscoveryDebugInput): AssistantMcpDiscoveryRuntimeEntryPointContract | null {
|
||||
if (isMcpDiscoveryEntryPointContract(input.entryPoint)) {
|
||||
return input.entryPoint;
|
||||
}
|
||||
const runtimeMetaEntryPoint =
|
||||
input.addressRuntimeMeta?.mcpDiscoveryRuntimeEntryPoint ??
|
||||
input.addressRuntimeMeta?.assistantMcpDiscoveryRuntimeEntryPoint ??
|
||||
input.addressRuntimeMeta?.assistant_mcp_discovery_entry_point_v1;
|
||||
return isMcpDiscoveryEntryPointContract(runtimeMetaEntryPoint) ? runtimeMetaEntryPoint : null;
|
||||
}
|
||||
|
||||
export function buildAssistantMcpDiscoveryDebugAttachmentFields(
|
||||
input: AttachAssistantMcpDiscoveryDebugInput
|
||||
): AssistantMcpDiscoveryDebugAttachmentFields {
|
||||
const entryPoint = resolveEntryPoint(input);
|
||||
const bridge = toRecordObject(entryPoint?.bridge);
|
||||
const answerDraft = toRecordObject(bridge?.answer_draft);
|
||||
|
||||
return {
|
||||
assistant_mcp_discovery_entry_point_v1: entryPoint,
|
||||
mcp_discovery_entry_status: toNonEmptyString(entryPoint?.entry_status),
|
||||
mcp_discovery_attempted: Boolean(entryPoint?.discovery_attempted),
|
||||
mcp_discovery_hot_runtime_wired: false,
|
||||
mcp_discovery_bridge_status: toNonEmptyString(bridge?.bridge_status),
|
||||
mcp_discovery_answer_mode: toNonEmptyString(answerDraft?.answer_mode),
|
||||
mcp_discovery_business_fact_answer_allowed: bridge?.business_fact_answer_allowed === true,
|
||||
mcp_discovery_user_facing_response_allowed: bridge?.user_facing_response_allowed === true,
|
||||
mcp_discovery_requires_clarification: bridge?.requires_user_clarification === true
|
||||
};
|
||||
}
|
||||
|
||||
export function attachAssistantMcpDiscoveryDebug<T extends Record<string, unknown>>(
|
||||
debugPayload: T,
|
||||
input: AttachAssistantMcpDiscoveryDebugInput
|
||||
): T & AssistantMcpDiscoveryDebugAttachmentFields {
|
||||
return {
|
||||
...debugPayload,
|
||||
...buildAssistantMcpDiscoveryDebugAttachmentFields(input)
|
||||
};
|
||||
}
|
||||
|
|
@ -86,6 +86,7 @@ export interface AssistantAddressRuntimeMetaForDeep {
|
|||
predecomposeContract?: Record<string, unknown> | null;
|
||||
semanticExtractionContract?: Record<string, unknown> | null;
|
||||
orchestrationContract?: Record<string, unknown> | null;
|
||||
mcpDiscoveryRuntimeEntryPoint?: Record<string, unknown> | null;
|
||||
}
|
||||
|
||||
export interface AssistantRequirement {
|
||||
|
|
|
|||
|
|
@ -92,7 +92,72 @@ describe("assistant address lane response runtime adapter", () => {
|
|||
capability_binding_response_guard: expect.objectContaining({
|
||||
schema_version: "assistant_capability_binding_response_guard_v1",
|
||||
applied: false
|
||||
}),
|
||||
assistant_mcp_discovery_entry_point_v1: null,
|
||||
mcp_discovery_attempted: false,
|
||||
mcp_discovery_hot_runtime_wired: false
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it("attaches MCP discovery summary from predecompose runtime meta without changing the reply", () => {
|
||||
const runtime = runAssistantAddressLaneResponseRuntime({
|
||||
sessionId: "asst-mcp",
|
||||
userMessage: "raw",
|
||||
effectiveAddressUserMessage: "raw",
|
||||
addressLane: {
|
||||
handled: true,
|
||||
reply_text: "answer",
|
||||
reply_type: "partial_coverage",
|
||||
debug: {}
|
||||
},
|
||||
llmPreDecomposeMeta: {
|
||||
mcpDiscoveryRuntimeEntryPoint: {
|
||||
schema_version: "assistant_mcp_discovery_runtime_entry_point_v1",
|
||||
policy_owner: "assistantMcpDiscoveryRuntimeEntryPoint",
|
||||
entry_status: "bridge_executed",
|
||||
hot_runtime_wired: false,
|
||||
discovery_attempted: true,
|
||||
turn_input: { adapter_status: "ready" },
|
||||
bridge: {
|
||||
bridge_status: "answer_draft_ready",
|
||||
user_facing_response_allowed: true,
|
||||
business_fact_answer_allowed: true,
|
||||
requires_user_clarification: false,
|
||||
answer_draft: { answer_mode: "confirmed_with_bounded_inference" }
|
||||
},
|
||||
reason_codes: ["runtime_entry_point_bridge_executed"]
|
||||
}
|
||||
},
|
||||
knownOrganizations: [],
|
||||
activeOrganization: null,
|
||||
sanitizeOutgoingAssistantText: (text) => String(text ?? ""),
|
||||
buildAddressDebugPayload: () => ({}),
|
||||
buildAddressFollowupOffer: () => null,
|
||||
mergeKnownOrganizations: (items) => items,
|
||||
toNonEmptyString: () => null,
|
||||
appendItem: () => {},
|
||||
getSession: () => ({ session_id: "asst-mcp", updated_at: "", items: [], investigation_state: null } as any),
|
||||
persistSession: () => {},
|
||||
cloneConversation: (items) => items,
|
||||
logEvent: () => {},
|
||||
messageIdFactory: () => "msg-mcp",
|
||||
finalizeAddressTurn: () => ({
|
||||
response: {
|
||||
ok: true
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
expect(runtime.response).toEqual({ ok: true });
|
||||
expect(runtime.debug).toEqual(
|
||||
expect.objectContaining({
|
||||
mcp_discovery_entry_status: "bridge_executed",
|
||||
mcp_discovery_attempted: true,
|
||||
mcp_discovery_bridge_status: "answer_draft_ready",
|
||||
mcp_discovery_answer_mode: "confirmed_with_bounded_inference",
|
||||
mcp_discovery_business_fact_answer_allowed: true,
|
||||
mcp_discovery_hot_runtime_wired: false
|
||||
})
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -154,6 +154,9 @@ describe("assistant debug payload assembler", () => {
|
|||
binding_action: "observe_only"
|
||||
})
|
||||
);
|
||||
expect(payload.assistant_mcp_discovery_entry_point_v1).toBeNull();
|
||||
expect(payload.mcp_discovery_attempted).toBe(false);
|
||||
expect(payload.mcp_discovery_hot_runtime_wired).toBe(false);
|
||||
});
|
||||
|
||||
it("omits optional fields when they are not provided", () => {
|
||||
|
|
@ -188,4 +191,35 @@ describe("assistant debug payload assembler", () => {
|
|||
expect(payload.answer_contract_stage4_v1?.legacy_blocks_present).toContain("Что сломано");
|
||||
expect(payload.answer_contract_stage4_v1?.legacy_blocks_present).toContain("Ограничения");
|
||||
});
|
||||
|
||||
it("attaches MCP discovery entry point summary when runtime meta provides it", () => {
|
||||
const input = baseInput();
|
||||
input.addressRuntimeMetaForDeep = {
|
||||
...input.addressRuntimeMetaForDeep,
|
||||
mcpDiscoveryRuntimeEntryPoint: {
|
||||
schema_version: "assistant_mcp_discovery_runtime_entry_point_v1",
|
||||
policy_owner: "assistantMcpDiscoveryRuntimeEntryPoint",
|
||||
entry_status: "bridge_executed",
|
||||
hot_runtime_wired: false,
|
||||
discovery_attempted: true,
|
||||
turn_input: { adapter_status: "ready" },
|
||||
bridge: {
|
||||
bridge_status: "answer_draft_ready",
|
||||
user_facing_response_allowed: true,
|
||||
business_fact_answer_allowed: true,
|
||||
requires_user_clarification: false,
|
||||
answer_draft: { answer_mode: "confirmed_with_bounded_inference" }
|
||||
},
|
||||
reason_codes: ["runtime_entry_point_bridge_executed"]
|
||||
}
|
||||
};
|
||||
|
||||
const payload = buildDeepAnalysisDebugPayload(input);
|
||||
|
||||
expect(payload.mcp_discovery_entry_status).toBe("bridge_executed");
|
||||
expect(payload.mcp_discovery_attempted).toBe(true);
|
||||
expect(payload.mcp_discovery_bridge_status).toBe("answer_draft_ready");
|
||||
expect(payload.mcp_discovery_answer_mode).toBe("confirmed_with_bounded_inference");
|
||||
expect(payload.mcp_discovery_business_fact_answer_allowed).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { attachAssistantMcpDiscoveryDebug } from "../src/services/assistantMcpDiscoveryDebugAttachment";
|
||||
|
||||
function entryPointContract(overrides: Record<string, unknown> = {}) {
|
||||
return {
|
||||
schema_version: "assistant_mcp_discovery_runtime_entry_point_v1",
|
||||
policy_owner: "assistantMcpDiscoveryRuntimeEntryPoint",
|
||||
entry_status: "bridge_executed",
|
||||
hot_runtime_wired: false,
|
||||
discovery_attempted: true,
|
||||
turn_input: { adapter_status: "ready" },
|
||||
bridge: {
|
||||
bridge_status: "answer_draft_ready",
|
||||
user_facing_response_allowed: true,
|
||||
business_fact_answer_allowed: true,
|
||||
requires_user_clarification: false,
|
||||
answer_draft: {
|
||||
answer_mode: "confirmed_with_bounded_inference"
|
||||
}
|
||||
},
|
||||
reason_codes: ["runtime_entry_point_bridge_executed"],
|
||||
...overrides
|
||||
};
|
||||
}
|
||||
|
||||
describe("assistant MCP discovery debug attachment", () => {
|
||||
it("attaches a validated entry point contract and exposes summary flags", () => {
|
||||
const debug = attachAssistantMcpDiscoveryDebug(
|
||||
{ trace_id: "trace-1" },
|
||||
{ addressRuntimeMeta: { mcpDiscoveryRuntimeEntryPoint: entryPointContract() } }
|
||||
);
|
||||
|
||||
expect(debug.assistant_mcp_discovery_entry_point_v1?.schema_version).toBe(
|
||||
"assistant_mcp_discovery_runtime_entry_point_v1"
|
||||
);
|
||||
expect(debug.mcp_discovery_entry_status).toBe("bridge_executed");
|
||||
expect(debug.mcp_discovery_attempted).toBe(true);
|
||||
expect(debug.mcp_discovery_hot_runtime_wired).toBe(false);
|
||||
expect(debug.mcp_discovery_bridge_status).toBe("answer_draft_ready");
|
||||
expect(debug.mcp_discovery_answer_mode).toBe("confirmed_with_bounded_inference");
|
||||
expect(debug.mcp_discovery_business_fact_answer_allowed).toBe(true);
|
||||
expect(debug.mcp_discovery_user_facing_response_allowed).toBe(true);
|
||||
expect(debug.mcp_discovery_requires_clarification).toBe(false);
|
||||
});
|
||||
|
||||
it("keeps safe null flags when no validated entry point exists", () => {
|
||||
const debug = attachAssistantMcpDiscoveryDebug(
|
||||
{ trace_id: "trace-1" },
|
||||
{ addressRuntimeMeta: { mcpDiscoveryRuntimeEntryPoint: { schema_version: "wrong" } } }
|
||||
);
|
||||
|
||||
expect(debug.assistant_mcp_discovery_entry_point_v1).toBeNull();
|
||||
expect(debug.mcp_discovery_entry_status).toBeNull();
|
||||
expect(debug.mcp_discovery_attempted).toBe(false);
|
||||
expect(debug.mcp_discovery_hot_runtime_wired).toBe(false);
|
||||
expect(debug.mcp_discovery_bridge_status).toBeNull();
|
||||
expect(debug.mcp_discovery_answer_mode).toBeNull();
|
||||
expect(debug.mcp_discovery_business_fact_answer_allowed).toBe(false);
|
||||
expect(debug.mcp_discovery_user_facing_response_allowed).toBe(false);
|
||||
expect(debug.mcp_discovery_requires_clarification).toBe(false);
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue