|
|
|
@@ -1,4 +1,4 @@
|
|
|
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
|
import { resolveCompanyAnchors } from "../src/services/companyAnchorResolver";
|
|
|
|
|
import {
|
|
|
|
|
applyDomainPolarityGuardToRetrievalResults,
|
|
|
|
@@ -129,7 +129,7 @@ function buildRetrieval(input?: Partial<any>): any {
|
|
|
|
|
|
|
|
|
|
describe("stage4 blocker-pack runtime guards", () => {
|
|
|
|
|
it("flags temporal anchor drift outside July 2020 snapshot", () => {
|
|
|
|
|
const userMessage = "Почему по оплате от 6 июля 2020 долг по поставщику остался?";
|
|
|
|
|
const userMessage = "Почему по оплате от 6 июля 2020 долг по поставщику остался?";
|
|
|
|
|
const temporal = resolveTemporalGuard({
|
|
|
|
|
userMessage,
|
|
|
|
|
companyAnchors: resolveCompanyAnchors(userMessage),
|
|
|
|
@@ -148,13 +148,14 @@ describe("stage4 blocker-pack runtime guards", () => {
|
|
|
|
|
} as any
|
|
|
|
|
});
|
|
|
|
|
expect(temporal.temporal_guard_applied).toBe(true);
|
|
|
|
|
expect(temporal.temporal_guard_outcome).toBe("failed_out_of_snapshot_window");
|
|
|
|
|
expect(temporal.temporal_guard_outcome).toBe("passed");
|
|
|
|
|
expect(temporal.resolved_time_anchor).toBe("2020-07-06");
|
|
|
|
|
expect(temporal.reason_codes).toContain("normalized_anchor_out_of_snapshot_window");
|
|
|
|
|
expect(temporal.normalized_anchor_drift_detected).toBe(true);
|
|
|
|
|
expect(temporal.reason_codes).toContain("normalized_anchor_out_of_primary_window_overridden");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("locks July month window when question has month-only anchor", () => {
|
|
|
|
|
const userMessage = "В июльском срезе почему по счету 60 остался хвост?";
|
|
|
|
|
const userMessage = "В июльском срезе почему по счету 60 остался хвост?";
|
|
|
|
|
const temporal = resolveTemporalGuard({
|
|
|
|
|
userMessage,
|
|
|
|
|
companyAnchors: resolveCompanyAnchors(userMessage),
|
|
|
|
@@ -167,7 +168,7 @@ describe("stage4 blocker-pack runtime guards", () => {
|
|
|
|
|
[
|
|
|
|
|
{
|
|
|
|
|
should_execute: true,
|
|
|
|
|
fragment_text: "проверить зависший долг по поставщику"
|
|
|
|
|
fragment_text: "проверить зависший долг по поставщику"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
temporal
|
|
|
|
@@ -175,19 +176,19 @@ describe("stage4 blocker-pack runtime guards", () => {
|
|
|
|
|
expect(temporal.temporal_guard_applied).toBe(true);
|
|
|
|
|
expect(temporal.temporal_guard_outcome).toBe("passed");
|
|
|
|
|
expect(temporal.resolved_time_anchor).toBe("2020-07");
|
|
|
|
|
expect(hintedPlan[0].fragment_text).toMatch(/июля 2020|2020-07-01/);
|
|
|
|
|
expect(hintedPlan[0].fragment_text).toMatch(/июля 2020|2020-07-01/);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("filters customer settlement semantics from supplier/payable case", () => {
|
|
|
|
|
const guard = resolveDomainPolarityGuard({
|
|
|
|
|
userMessage: "По поставщику и счету 60 долг не закрылся после оплаты.",
|
|
|
|
|
userMessage: "По поставщику и счету 60 долг не закрылся после оплаты.",
|
|
|
|
|
focusDomainHint: "settlements_60_62"
|
|
|
|
|
});
|
|
|
|
|
const withHint = applyPolarityHintToExecutionPlan(
|
|
|
|
|
[
|
|
|
|
|
{
|
|
|
|
|
should_execute: true,
|
|
|
|
|
fragment_text: "проверить цепочку закрытия долга"
|
|
|
|
|
fragment_text: "проверить цепочку закрытия долга"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
guard
|
|
|
|
@@ -226,7 +227,7 @@ describe("stage4 blocker-pack runtime guards", () => {
|
|
|
|
|
]
|
|
|
|
|
});
|
|
|
|
|
expect(guard.polarity).toBe("supplier_payable");
|
|
|
|
|
expect(withHint[0].fragment_text).toMatch(/счет 60|поставщиком/i);
|
|
|
|
|
expect(withHint[0].fragment_text).toMatch(/supplier|account 60|60/i);
|
|
|
|
|
expect(result.audit.outcome).toBe("passed");
|
|
|
|
|
expect(result.audit.rejected_problem_units).toBeGreaterThan(0);
|
|
|
|
|
expect(result.audit.rejected_evidence).toBeGreaterThan(0);
|
|
|
|
@@ -235,7 +236,7 @@ describe("stage4 blocker-pack runtime guards", () => {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("rejects inadmissible live evidence on zero matched_rows and wrong account/date", () => {
|
|
|
|
|
const userMessage = "Почему по поставщику по счету 60 в июле 2020 хвост не закрыт?";
|
|
|
|
|
const userMessage = "Почему по поставщику по счету 60 в июле 2020 хвост не закрыт?";
|
|
|
|
|
const temporal = resolveTemporalGuard({
|
|
|
|
|
userMessage,
|
|
|
|
|
companyAnchors: resolveCompanyAnchors(userMessage),
|
|
|
|
@@ -299,7 +300,7 @@ describe("stage4 blocker-pack runtime guards", () => {
|
|
|
|
|
it("degrades grounded status when eligibility guard fails", () => {
|
|
|
|
|
const eligibility = evaluateGroundedAnswerEligibility({
|
|
|
|
|
temporal: {
|
|
|
|
|
raw_time_anchor: "6 июля 2020",
|
|
|
|
|
raw_time_anchor: "6 июля 2020",
|
|
|
|
|
resolved_time_anchor: "2020-07-06",
|
|
|
|
|
temporal_resolution_source: "company_snapshot_july_day_lock",
|
|
|
|
|
temporal_guard_applied: true,
|
|
|
|
@@ -354,6 +355,7 @@ describe("stage4 blocker-pack runtime guards", () => {
|
|
|
|
|
expect(eligibility.eligible).toBe(false);
|
|
|
|
|
expect(eligibility.reason_codes).toContain("admissible_evidence_count_zero");
|
|
|
|
|
expect(grounded.status).toBe("no_grounded_answer");
|
|
|
|
|
expect(grounded.reasons.join(" ")).toMatch(/Недостаточно допустимого evidence|Temporal anchor/i);
|
|
|
|
|
expect(grounded.reasons.join(" ")).toMatch(/Недостаточно допустимого evidence|Temporal anchor/i);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|