NODEDC_1C/llm_normalizer/backend/tests/assistantDebugPayloadAssemb...

226 lines
9.0 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { describe, expect, it } from "vitest";
import { buildDeepAnalysisDebugPayload } from "../src/services/assistantDebugPayloadAssembler";
function baseInput() {
return {
traceId: "trace-1",
promptVersion: "normalizer_v2_0_2",
schemaVersion: "normalized_query_v2_0_2",
fallbackType: "none",
routeSummary: { mode: "deterministic_v2" },
fragments: [{ fragment_id: "F1" }],
requirementsExtracted: [{ requirement_id: "R1", status: "covered" }],
coverageReport: { requirements_total: 1, requirements_covered: 1 },
routes: [{ fragment_id: "F1", route: "hybrid_store_plus_live" }],
retrievalStatus: [
{
fragment_id: "F1",
requirement_ids: ["R1"],
route: "hybrid_store_plus_live",
status: "ok",
result_type: "summary"
}
],
retrievalResults: [{ fragment_id: "F1", status: "ok" }],
groundingCheck: { status: "grounded" },
droppedIntentSegments: [],
questionTypeClass: "factual_lookup",
companyAnchors: { companies: ["demo"] },
runtimeAnalysisContext: {
active: true,
as_of_date: "2020-07-31",
period_from: null,
period_to: null,
source: "eval_analysis_date",
snapshot_mode: "auto" as const
},
businessScopeResolution: {
business_scope_raw: ["company_specific_accounting"],
business_scope_resolved: ["company_specific_accounting"],
company_grounding_applied: true,
scope_resolution_reason: ["resolved"]
},
temporalGuard: {
raw_time_anchor: "2020-07",
raw_time_scope: "month",
resolved_time_anchor: "2020-07",
resolved_primary_period: { from: "2020-07-01", to: "2020-07-31", granularity: "day" },
effective_primary_period: { from: "2020-07-01", to: "2020-07-31", granularity: "day" },
temporal_guard_input: "2020-07",
temporal_alignment_status: "aligned",
temporal_resolution_source: "analysis_context",
temporal_guard_basis: "analysis_context",
temporal_guard_applied: true,
temporal_guard_outcome: "pass"
},
polarityAudit: {
raw_numeric_tokens: ["60.01"],
classified_numeric_tokens: [{ token: "60.01" }],
rejected_as_non_accounts: [],
resolved_account_anchors: ["60.01"]
},
claimAnchorAudit: {
settlement_role: "supplier",
settlement_role_resolution_reason: ["account_60_detected"],
polarity_resolution_status: "resolved"
},
targetedEvidenceAudit: { targeted_evidence_hit_rate: 1 },
evidenceAdmissibilityGateAudit: { admissible_evidence_count: 1 },
rbpLiveRouteAudit: null,
faLiveRouteAudit: null,
groundedAnswerEligibilityGuard: { eligibility_time_basis: "analysis_context", eligible: true },
followupStateUsage: null,
compositionDebug: {
problem_centric_answer_applied: true,
problem_units_used_count: 2,
problem_answer_mode: "stage3_lifecycle_aware_v1",
problem_unit_ids_used: ["pu-1", "pu-2"]
},
addressRuntimeMetaForDeep: {
attempted: true,
applied: true,
reason: "ok",
provider: "openai",
fallbackRuleHit: null,
toolGateDecision: "run_address_lane",
toolGateReason: "detected",
predecomposeContract: { schema_version: "x" },
orchestrationContract: { schema_version: "y" }
},
outcomeClassV1: "FULLY_ANSWERED",
assistantOrchestrationContractsV1: { query_frame: {}, execution_plan: {}, evidence_bundle: {}, coverage: {} },
answerStructureV11: { schema_version: "answer_structure_v1_1" },
assistantReply: [
"Коротко: Признак проблемы подтвержден частично.",
"Что именно проверено:\n- Проверен учетный контур.",
"Что найдено:\n- Есть признак разрыва цепочки.",
"Что пока не доказано:\n- Не хватает части подтверждений.",
"Что проверить первым:\n- Уточнить период."
].join("\n\n"),
investigationStateSnapshot: { status: "active" },
normalizedPayload: { schema_version: "normalized_query_v2_0_2" }
};
}
describe("assistant debug payload assembler", () => {
it("builds deep debug payload with analysis context and optional sections", () => {
const payload = buildDeepAnalysisDebugPayload(baseInput());
expect(payload.trace_id).toBe("trace-1");
expect(payload.analysis_context_applied).toBe(true);
expect(payload.analysis_context).toMatchObject({
as_of_date: "2020-07-31",
source: "eval_analysis_date"
});
expect(payload.problem_unit_ids_used).toEqual(["pu-1", "pu-2"]);
expect(payload.address_llm_predecompose_applied).toBe(true);
expect(payload.assistant_outcome_class_v1).toBe("FULLY_ANSWERED");
expect(payload.answer_contract_stage4_v1?.is_stage4_shape).toBe(true);
expect(payload.assistant_truth_answer_policy_v1).toEqual(
expect.objectContaining({
schema_version: "assistant_truth_answer_policy_runtime_v1",
policy_owner: "assistantTruthAnswerPolicyRuntimeAdapter"
})
);
expect(payload.coverage_gate_contract).toEqual(
expect.objectContaining({
coverage_status: "full",
truth_mode: "confirmed"
})
);
expect(payload.answer_shape_contract).toEqual(
expect.objectContaining({
answer_shape: "confirmed_factual",
reply_type: "deep_analysis"
})
);
expect(payload.assistant_state_transition_v1).toEqual(
expect.objectContaining({
schema_version: "assistant_state_transition_runtime_v1",
state_owner: "assistantStateTransitionRuntimeAdapter",
application_status: "unresolved"
})
);
expect(payload.state_transition_contract).toEqual(
expect.objectContaining({
effective_carryover_depth: "none"
})
);
expect(payload.assistant_capability_binding_v1).toEqual(
expect.objectContaining({
schema_version: "assistant_capability_runtime_binding_v1",
binding_owner: "assistantCapabilityRuntimeBindingAdapter",
binding_status: "not_applicable",
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", () => {
const input = baseInput();
input.runtimeAnalysisContext.active = false;
input.followupStateUsage = null;
input.compositionDebug.problem_unit_ids_used = [];
input.rbpLiveRouteAudit = null;
input.faLiveRouteAudit = null;
input.addressRuntimeMetaForDeep = null;
const payload = buildDeepAnalysisDebugPayload(input);
expect(payload.analysis_context).toBeNull();
expect(Object.prototype.hasOwnProperty.call(payload, "followup_state_usage")).toBe(false);
expect(Object.prototype.hasOwnProperty.call(payload, "problem_unit_ids_used")).toBe(false);
expect(payload.address_llm_predecompose_applied).toBe(false);
expect(payload.address_llm_predecompose_contract).toBeNull();
});
it("marks non-stage4 answer shapes in contract audit", () => {
const input = baseInput();
input.assistantReply = [
"Коротко: Есть проблема.",
"Что сломано:\n- Разрыв перехода.",
"Ограничения:\n- Частичная опора."
].join("\n\n");
const payload = buildDeepAnalysisDebugPayload(input);
expect(payload.answer_contract_stage4_v1?.is_stage4_shape).toBe(false);
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);
});
});