131 lines
5.4 KiB
TypeScript
131 lines
5.4 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
||
import { buildDeepAnalysisProcessedLogDetails } from "../src/services/assistantMessageLogAssembler";
|
||
|
||
function baseInput() {
|
||
return {
|
||
sessionId: "asst-1",
|
||
messageId: "msg-1",
|
||
userMessage: "проверь 60.01",
|
||
normalizerOutput: { schema_version: "normalized_query_v2_0_2" },
|
||
executionPlan: [{ fragment_id: "F1", route: "hybrid_store_plus_live", should_execute: true }],
|
||
resolvedExecutionState: { executable: 1 },
|
||
routes: [{ fragment_id: "F1", route: "hybrid_store_plus_live" }],
|
||
retrievalCalls: [{ route: "hybrid_store_plus_live" }],
|
||
retrievalResultsRaw: [{ status: "ok" }],
|
||
retrievalResultsNormalized: [{ status: "ok" }],
|
||
requirementsExtracted: [{ requirement_id: "R1" }],
|
||
coverageReport: {
|
||
requirements_total: 1,
|
||
requirements_covered: 1,
|
||
requirements_uncovered: [],
|
||
requirements_partially_covered: [],
|
||
clarification_needed_for: [],
|
||
out_of_scope_requirements: []
|
||
},
|
||
groundingCheck: {
|
||
status: "grounded",
|
||
route_subject_match: true,
|
||
missing_requirements: [],
|
||
reasons: [],
|
||
why_included_summary: ["signal"],
|
||
selection_reason_summary: ["ranked"]
|
||
},
|
||
replyType: "factual",
|
||
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: 1,
|
||
problem_answer_mode: "stage3_lifecycle_aware_v1",
|
||
problem_unit_ids_used: ["pu-1"],
|
||
fallback_type: "none"
|
||
},
|
||
outcomeClassV1: "FULLY_ANSWERED",
|
||
assistantOrchestrationContractsV1: { query_frame: {}, execution_plan: {}, evidence_bundle: {}, coverage: {} },
|
||
answerStructureV11: { schema_version: "answer_structure_v1_1" },
|
||
investigationStateSnapshot: { status: "active" },
|
||
assistantReply: [
|
||
"Коротко: Признак проблемы подтвержден частично.",
|
||
"Что именно проверено:\n- Проверен учетный контур.",
|
||
"Что найдено:\n- Есть признак разрыва цепочки.",
|
||
"Что пока не доказано:\n- Не хватает части подтверждений.",
|
||
"Что проверить первым:\n- Уточнить период."
|
||
].join("\n\n"),
|
||
traceId: "trace-1"
|
||
};
|
||
}
|
||
|
||
describe("assistant message log assembler", () => {
|
||
it("builds deep analysis log details and resolves full coverage status", () => {
|
||
const details = buildDeepAnalysisProcessedLogDetails(baseInput());
|
||
expect(details.session_id).toBe("asst-1");
|
||
expect(details.coverage_status).toBe("full");
|
||
expect(details.analysis_context).toMatchObject({
|
||
as_of_date: "2020-07-31"
|
||
});
|
||
expect(details.problem_unit_ids_used).toEqual(["pu-1"]);
|
||
expect(details.reply_type).toBe("factual");
|
||
expect((details.answer_contract_stage4_v1 as { is_stage4_shape?: boolean } | undefined)?.is_stage4_shape).toBe(true);
|
||
});
|
||
|
||
it("marks partial coverage and omits optional sections when empty", () => {
|
||
const input = baseInput();
|
||
input.coverageReport.requirements_covered = 0;
|
||
input.coverageReport.requirements_uncovered = ["R1"];
|
||
input.runtimeAnalysisContext.active = false;
|
||
input.followupStateUsage = null;
|
||
input.compositionDebug.problem_unit_ids_used = [];
|
||
|
||
const details = buildDeepAnalysisProcessedLogDetails(input);
|
||
expect(details.coverage_status).toBe("partial_or_limited");
|
||
expect(details.analysis_context).toBeNull();
|
||
expect(Object.prototype.hasOwnProperty.call(details, "followup_state_usage")).toBe(false);
|
||
expect(Object.prototype.hasOwnProperty.call(details, "problem_unit_ids_used")).toBe(false);
|
||
});
|
||
});
|