Этап 4 / Волна 16: смысловая изоляция РБП и ОС, фиксы лайв-ответов и добивка экспорта
This commit is contained in:
@@ -147,7 +147,7 @@ describe("assistant mode API", () => {
|
||||
});
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(["partial_coverage", "route_mismatch_blocked", "factual_with_explanation"]).toContain(
|
||||
expect(["partial_coverage", "clarification_required", "route_mismatch_blocked", "factual_with_explanation"]).toContain(
|
||||
String(response.body.reply_type)
|
||||
);
|
||||
expect(["partial", "grounded", "route_mismatch_blocked"]).toContain(
|
||||
|
||||
@@ -194,6 +194,43 @@ describe.sequential("assistant follow-up state binding", () => {
|
||||
expect(second.body.debug?.investigation_state_snapshot?.turn_index).toBe(2);
|
||||
});
|
||||
|
||||
it("rebinds follow-up domain away from settlements on fixed-asset amortization query", async () => {
|
||||
const app = await createAppWithFlags({
|
||||
state: "1",
|
||||
binding: "1",
|
||||
problemUnits: "1",
|
||||
continuity: "1",
|
||||
answerPolicy: "1",
|
||||
problemCentric: "1"
|
||||
});
|
||||
const sessionId = `asst-wave16-fa-domain-${Date.now()}`;
|
||||
|
||||
const first = await request(app).post("/api/assistant/message").send({
|
||||
session_id: sessionId,
|
||||
useMock: true,
|
||||
promptVersion: "normalizer_v2_0_2",
|
||||
user_message: "Почему деньги ушли, а долг по 60.01/62.02 остался?"
|
||||
});
|
||||
expect(first.status).toBe(200);
|
||||
expect(first.body.debug?.investigation_state_snapshot?.followup_context?.active_domain).toBe("settlements_60_62");
|
||||
|
||||
const second = await request(app).post("/api/assistant/message").send({
|
||||
session_id: sessionId,
|
||||
useMock: true,
|
||||
promptVersion: "normalizer_v2_0_2",
|
||||
user_message:
|
||||
"Полно ли начислена амортизация по объектам ОС за июль? Проверь по 01/02, нет ли пропущенных объектов."
|
||||
});
|
||||
|
||||
expect(second.status).toBe(200);
|
||||
const activeDomain = String(second.body.debug?.investigation_state_snapshot?.followup_context?.active_domain ?? "");
|
||||
expect(activeDomain).not.toBe("settlements_60_62");
|
||||
expect(activeDomain).toMatch(/fixed_asset_amortization|month_close_costs_20_44|no_route|hybrid_store_plus_live|fixed_asset/i);
|
||||
|
||||
const settlementActions = second.body.debug?.investigation_state_snapshot?.followup_context?.settlement_next_actions;
|
||||
expect(Array.isArray(settlementActions) ? settlementActions.length : 0).toBe(0);
|
||||
});
|
||||
|
||||
it("keeps UTF-8 follow-up period refinement in-scope with soft continuity hints", async () => {
|
||||
const app = await createAppWithFlags({
|
||||
state: "1",
|
||||
|
||||
@@ -0,0 +1,546 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { composeAssistantAnswer } from "../src/services/answerComposer";
|
||||
import { resolveCompanyAnchors } from "../src/services/companyAnchorResolver";
|
||||
import type { AnswerGroundingCheck, RequirementCoverageReport, UnifiedRetrievalResult } from "../src/types/assistant";
|
||||
import type { ProblemUnit } from "../src/types/stage2ProblemUnits";
|
||||
|
||||
function buildRouteSummary() {
|
||||
return {
|
||||
mode: "deterministic_v2" as const,
|
||||
message_in_scope: true,
|
||||
scope_confidence: "high" as const,
|
||||
planner: {
|
||||
total_fragments: 1,
|
||||
in_scope_fragments: 1,
|
||||
out_of_scope_fragments: 0,
|
||||
discarded_fragments: 0,
|
||||
contains_multiple_tasks: false
|
||||
},
|
||||
decisions: [],
|
||||
fallback: {
|
||||
type: "none" as const,
|
||||
message: null
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function buildCoverage(input?: Partial<RequirementCoverageReport>): RequirementCoverageReport {
|
||||
return {
|
||||
requirements_total: 1,
|
||||
requirements_covered: 1,
|
||||
requirements_uncovered: [],
|
||||
requirements_partially_covered: [],
|
||||
clarification_needed_for: [],
|
||||
out_of_scope_requirements: [],
|
||||
...input
|
||||
};
|
||||
}
|
||||
|
||||
function buildGrounding(input?: Partial<AnswerGroundingCheck>): AnswerGroundingCheck {
|
||||
return {
|
||||
status: "partial",
|
||||
route_subject_match: true,
|
||||
missing_requirements: [],
|
||||
reasons: [],
|
||||
why_included_summary: ["wave16-live"],
|
||||
selection_reason_summary: ["wave16-live"],
|
||||
...input
|
||||
};
|
||||
}
|
||||
|
||||
function buildProblemUnit(input?: Partial<ProblemUnit>): ProblemUnit {
|
||||
return {
|
||||
schema_version: "problem_unit_v0_1",
|
||||
problem_unit_id: input?.problem_unit_id ?? "pu-live-1",
|
||||
problem_unit_type: input?.problem_unit_type ?? "cross_branch_inconsistency_cluster",
|
||||
title: input?.title ?? "Live corrective test unit",
|
||||
mechanism_summary: input?.mechanism_summary ?? "Mechanism candidate: invoice_to_vat.",
|
||||
business_defect_class: input?.business_defect_class ?? "invoice_to_vat",
|
||||
severity: input?.severity ?? {
|
||||
score: 0.61,
|
||||
grade: "medium"
|
||||
},
|
||||
confidence: input?.confidence ?? {
|
||||
score: 0.58,
|
||||
grade: "medium"
|
||||
},
|
||||
lifecycle_domain: input?.lifecycle_domain ?? "vat_flow",
|
||||
affected_entities: input?.affected_entities ?? ["Document:DOC-1"],
|
||||
affected_documents: input?.affected_documents ?? ["Document:DOC-1"],
|
||||
affected_postings: input?.affected_postings ?? ["Posting:POST-1"],
|
||||
affected_accounts: input?.affected_accounts ?? ["19"],
|
||||
affected_counterparties: input?.affected_counterparties ?? ["Counterparty:CP-1"],
|
||||
affected_contracts: input?.affected_contracts ?? ["Contract:CTR-1"],
|
||||
failed_expected_edge: input?.failed_expected_edge ?? "invoice_to_vat",
|
||||
period_impact: input?.period_impact ?? {
|
||||
is_period_sensitive: true,
|
||||
impact_class: "close_risk"
|
||||
},
|
||||
evidence_pack: input?.evidence_pack ?? ["ev-1"],
|
||||
entity_backlinks: input?.entity_backlinks ?? [{ entity: "Document", id: "DOC-1" }],
|
||||
snapshot_limitations: input?.snapshot_limitations ?? []
|
||||
};
|
||||
}
|
||||
|
||||
function buildRetrieval(input?: Partial<UnifiedRetrievalResult>): UnifiedRetrievalResult {
|
||||
return {
|
||||
fragment_id: "F1",
|
||||
requirement_ids: ["R1"],
|
||||
route: "hybrid_store_plus_live",
|
||||
status: "ok",
|
||||
result_type: "chain",
|
||||
items: [
|
||||
{
|
||||
source_entity: "Document",
|
||||
source_id: "DOC-1",
|
||||
display_name: "Документ",
|
||||
account_context: ["19"],
|
||||
document_context: ["invoice", "vat_document"],
|
||||
relation_pattern_hits: ["invoice_to_vat", "document_to_posting"],
|
||||
graph_domain_scope: ["vat_flow"],
|
||||
period: "2020-07"
|
||||
}
|
||||
],
|
||||
summary: {
|
||||
semantic_profile: {
|
||||
account_scope: ["19"],
|
||||
domain_scope: ["vat", "taxes"],
|
||||
relation_patterns: ["invoice_to_vat", "document_to_posting"],
|
||||
period_scope: {
|
||||
from: "2020-07-01",
|
||||
to: "2020-07-31",
|
||||
granularity: "month"
|
||||
}
|
||||
},
|
||||
domain_purity_guard: {
|
||||
domain_card_id: "vat_document_register_book"
|
||||
},
|
||||
broad_query_detected: false,
|
||||
broad_result_flag: false,
|
||||
minimum_evidence_failed: false,
|
||||
narrowing_strength: "strong"
|
||||
},
|
||||
evidence: [
|
||||
{
|
||||
evidence_id: "ev-1",
|
||||
claim_ref: "requirement:R1",
|
||||
source_type: "retrieval_item",
|
||||
source_ref: {
|
||||
schema_version: "evidence_source_ref_v1",
|
||||
namespace: "snapshot_2020_07",
|
||||
entity: "document",
|
||||
id: "DOC-1",
|
||||
period: "2020-07",
|
||||
canonical_ref: "evidence_source_ref_v1|snapshot_2020_07|document|doc-1|2020-07"
|
||||
},
|
||||
pointer: {
|
||||
fragment_id: "F1",
|
||||
route: "hybrid_store_plus_live",
|
||||
source: {
|
||||
namespace: "snapshot_2020_07",
|
||||
entity: "document",
|
||||
id: "DOC-1",
|
||||
period: "2020-07"
|
||||
},
|
||||
locator: {
|
||||
field_path: "risk_score",
|
||||
item_index: 0
|
||||
}
|
||||
},
|
||||
evidence_kind: "mechanism_link",
|
||||
mechanism_note: "invoice_to_vat",
|
||||
confidence: "medium",
|
||||
limitation: null,
|
||||
payload: {
|
||||
value: 1
|
||||
}
|
||||
}
|
||||
],
|
||||
candidate_evidence: [],
|
||||
problem_units: [buildProblemUnit()],
|
||||
problem_unit_summary: {
|
||||
schema_version: "problem_unit_summary_v0_1",
|
||||
units_total: 1,
|
||||
duplicate_collapses: 0,
|
||||
unit_types: ["cross_branch_inconsistency_cluster"],
|
||||
type_distribution: {
|
||||
cross_branch_inconsistency_cluster: 1
|
||||
},
|
||||
severity_distribution: {
|
||||
low: 0,
|
||||
medium: 1,
|
||||
high: 0
|
||||
},
|
||||
confidence_distribution: {
|
||||
low: 0,
|
||||
medium: 1,
|
||||
high: 0
|
||||
},
|
||||
primary_unit_type: "cross_branch_inconsistency_cluster"
|
||||
},
|
||||
why_included: ["wave16-live"],
|
||||
selection_reason: ["wave16-live"],
|
||||
risk_factors: ["cross_branch_inconsistency"],
|
||||
business_interpretation: ["wave16-live"],
|
||||
confidence: "medium",
|
||||
limitations: [],
|
||||
errors: [],
|
||||
...input
|
||||
};
|
||||
}
|
||||
|
||||
describe("wave16 live corrective pass regressions", () => {
|
||||
it("removes leaked debug payload scaffolding from user-facing reply", () => {
|
||||
const output = composeAssistantAnswer({
|
||||
userMessage: "Проверь НДС цепочку в июле.",
|
||||
routeSummary: buildRouteSummary(),
|
||||
retrievalResults: [
|
||||
buildRetrieval({
|
||||
selection_reason: [
|
||||
"### debug_payload_json\n```json\n{\"trace_id\":\"abc\",\"route_summary\":{\"mode\":\"x\"}}\n```"
|
||||
]
|
||||
})
|
||||
],
|
||||
requirements: [
|
||||
{
|
||||
requirement_id: "R1",
|
||||
source_fragment_id: "F1",
|
||||
requirement_text: "Проверка НДС",
|
||||
subject_tokens: [],
|
||||
status: "covered",
|
||||
route: "hybrid_store_plus_live"
|
||||
}
|
||||
],
|
||||
coverageReport: buildCoverage(),
|
||||
groundingCheck: buildGrounding({ status: "grounded" }),
|
||||
focusDomainHint: "vat_document_register_book",
|
||||
questionTypeHint: "why_breaks",
|
||||
enableAnswerPolicyV11: true,
|
||||
enableProblemCentricAnswerV1: true,
|
||||
enableLifecycleAnswerV1: true
|
||||
});
|
||||
|
||||
expect(output.assistant_reply).not.toMatch(/debug_payload_json|technical_breakdown_json|trace_id|route_summary/i);
|
||||
});
|
||||
|
||||
it("does not claim missing period when normalization already extracted explicit period", () => {
|
||||
const output = composeAssistantAnswer({
|
||||
userMessage: "Рошибка кодировки", // emulates noisy text from live channel
|
||||
routeSummary: buildRouteSummary(),
|
||||
retrievalResults: [
|
||||
buildRetrieval({
|
||||
summary: {
|
||||
semantic_profile: {
|
||||
account_scope: ["19"],
|
||||
domain_scope: ["vat", "taxes"],
|
||||
relation_patterns: ["invoice_to_vat"]
|
||||
},
|
||||
domain_purity_guard: {
|
||||
domain_card_id: "vat_document_register_book"
|
||||
},
|
||||
broad_query_detected: true,
|
||||
broad_result_flag: false,
|
||||
minimum_evidence_failed: false,
|
||||
narrowing_strength: "weak"
|
||||
}
|
||||
})
|
||||
],
|
||||
requirements: [
|
||||
{
|
||||
requirement_id: "R1",
|
||||
source_fragment_id: "F1",
|
||||
requirement_text: "Проверка периода",
|
||||
subject_tokens: [],
|
||||
status: "covered",
|
||||
route: "hybrid_store_plus_live"
|
||||
}
|
||||
],
|
||||
coverageReport: buildCoverage({
|
||||
requirements_covered: 0,
|
||||
requirements_partially_covered: ["R1"],
|
||||
clarification_needed_for: ["R1"]
|
||||
}),
|
||||
groundingCheck: buildGrounding({
|
||||
status: "partial",
|
||||
reasons: ["Mechanism is unresolved for part of the evidence."]
|
||||
}),
|
||||
focusDomainHint: "vat_document_register_book",
|
||||
questionTypeHint: "which_chains_are_complete_vs_incomplete",
|
||||
normalizationPeriodExplicit: true,
|
||||
enableAnswerPolicyV11: true,
|
||||
enableProblemCentricAnswerV1: true,
|
||||
enableLifecycleAnswerV1: true
|
||||
});
|
||||
|
||||
expect(output.assistant_reply).not.toMatch(/период в запросе не указан/i);
|
||||
expect(output.assistant_reply).not.toMatch(/уточните период проверки/i);
|
||||
});
|
||||
|
||||
it("blocks VAT primary synthesis when top evidence is cross-domain polluted", () => {
|
||||
const polluted = buildRetrieval({
|
||||
items: [
|
||||
{
|
||||
source_entity: "Document",
|
||||
source_id: "DOC-1",
|
||||
display_name: "Документ",
|
||||
account_context: ["25", "20", "19"],
|
||||
document_context: ["invoice", "vat_document", "deferred_expense_document"],
|
||||
relation_pattern_hits: ["invoice_to_vat", "deferred_expense_to_writeoff"],
|
||||
graph_domain_scope: ["vat_flow", "deferred_expense", "period_close", "bank_settlement", "fixed_asset"],
|
||||
period: "2020-07"
|
||||
}
|
||||
],
|
||||
summary: {
|
||||
semantic_profile: {
|
||||
account_scope: ["19"],
|
||||
domain_scope: ["vat", "taxes"],
|
||||
relation_patterns: ["invoice_to_vat", "deferred_expense_to_writeoff"],
|
||||
period_scope: {
|
||||
from: "2020-07-01",
|
||||
to: "2020-07-31",
|
||||
granularity: "month"
|
||||
}
|
||||
},
|
||||
domain_purity_guard: {
|
||||
domain_card_id: "vat_document_register_book"
|
||||
},
|
||||
broad_query_detected: false,
|
||||
broad_result_flag: false,
|
||||
minimum_evidence_failed: false,
|
||||
narrowing_strength: "strong"
|
||||
}
|
||||
});
|
||||
|
||||
const output = composeAssistantAnswer({
|
||||
userMessage: "Проверь НДС-цепочку: документ -> счет-фактура -> регистр -> книга.",
|
||||
routeSummary: buildRouteSummary(),
|
||||
retrievalResults: [polluted],
|
||||
requirements: [
|
||||
{
|
||||
requirement_id: "R1",
|
||||
source_fragment_id: "F1",
|
||||
requirement_text: "Проверка НДС",
|
||||
subject_tokens: [],
|
||||
status: "covered",
|
||||
route: "hybrid_store_plus_live"
|
||||
}
|
||||
],
|
||||
coverageReport: buildCoverage(),
|
||||
groundingCheck: buildGrounding({ status: "grounded" }),
|
||||
focusDomainHint: "vat_document_register_book",
|
||||
questionTypeHint: "why_breaks",
|
||||
enableAnswerPolicyV11: true,
|
||||
enableProblemCentricAnswerV1: true,
|
||||
enableLifecycleAnswerV1: true
|
||||
});
|
||||
|
||||
expect(output.reply_type).toBe("clarification_required");
|
||||
expect(output.answer_structure_v11?.uncertainty_block.open_uncertainties).toContain("primary_domain_evidence_not_confirmed");
|
||||
});
|
||||
|
||||
it("uses VAT-specific partial-coverage wording instead of generic chain template", () => {
|
||||
const output = composeAssistantAnswer({
|
||||
userMessage:
|
||||
"13 июля поступление, 15 июля реализация. НДС-цепочка по этим движениям полная или есть выпадение?",
|
||||
routeSummary: buildRouteSummary(),
|
||||
retrievalResults: [
|
||||
buildRetrieval({
|
||||
summary: {
|
||||
semantic_profile: {
|
||||
account_scope: ["19", "68"],
|
||||
domain_scope: ["vat", "taxes"],
|
||||
relation_patterns: ["invoice_to_vat", "document_to_posting"],
|
||||
period_scope: {
|
||||
from: "2020-07-01",
|
||||
to: "2020-07-31",
|
||||
granularity: "month"
|
||||
}
|
||||
},
|
||||
domain_purity_guard: {
|
||||
domain_card_id: "vat_document_register_book"
|
||||
},
|
||||
broad_query_detected: false,
|
||||
broad_result_flag: false,
|
||||
minimum_evidence_failed: false,
|
||||
narrowing_strength: "strong"
|
||||
}
|
||||
})
|
||||
],
|
||||
requirements: [
|
||||
{
|
||||
requirement_id: "R1",
|
||||
source_fragment_id: "F1",
|
||||
requirement_text: "Проверка полноты НДС-цепочки",
|
||||
subject_tokens: [],
|
||||
status: "covered",
|
||||
route: "hybrid_store_plus_live"
|
||||
}
|
||||
],
|
||||
coverageReport: buildCoverage({ requirements_covered: 0, requirements_partially_covered: ["R1"] }),
|
||||
groundingCheck: buildGrounding({ status: "partial" }),
|
||||
focusDomainHint: "vat_document_register_book",
|
||||
questionTypeHint: "which_chains_are_complete_vs_incomplete",
|
||||
normalizationPeriodExplicit: true,
|
||||
enableAnswerPolicyV11: true,
|
||||
enableProblemCentricAnswerV1: true,
|
||||
enableLifecycleAnswerV1: true
|
||||
});
|
||||
|
||||
expect(output.assistant_reply).toMatch(/НДС-цепочк|НДС-звеньям|документ -> счет-фактура -> регистр -> книга/i);
|
||||
expect(output.assistant_reply).not.toMatch(/ключевой переход закрытия/i);
|
||||
});
|
||||
|
||||
it("renders RBP answer in RBP language with RBP-first checks", () => {
|
||||
const output = composeAssistantAnswer({
|
||||
userMessage:
|
||||
"31 июля прошло Списание РБП за июль. Есть ли признаки, что часть РБП к концу июля живет дольше ожидаемого?",
|
||||
routeSummary: buildRouteSummary(),
|
||||
retrievalResults: [
|
||||
buildRetrieval({
|
||||
items: [
|
||||
{
|
||||
source_entity: "Document",
|
||||
source_id: "DOC-RBP-1",
|
||||
display_name: "Списание РБП",
|
||||
account_context: ["97"],
|
||||
document_context: ["deferred_expense_document"],
|
||||
relation_pattern_hits: ["deferred_expense_to_writeoff", "document_to_posting", "asset_card_to_depreciation"],
|
||||
graph_domain_scope: ["deferred_expense", "period_close", "fixed_asset"],
|
||||
period: "2020-07"
|
||||
}
|
||||
],
|
||||
summary: {
|
||||
semantic_profile: {
|
||||
account_scope: ["97", "01"],
|
||||
domain_scope: ["deferred_expense", "period_close"],
|
||||
relation_patterns: ["deferred_expense_to_writeoff", "document_to_posting", "asset_card_to_depreciation"],
|
||||
period_scope: {
|
||||
from: "2020-07-01",
|
||||
to: "2020-07-31",
|
||||
granularity: "month"
|
||||
}
|
||||
},
|
||||
domain_purity_guard: {
|
||||
domain_card_id: "month_close_costs_20_44"
|
||||
},
|
||||
broad_query_detected: false,
|
||||
broad_result_flag: false,
|
||||
minimum_evidence_failed: false,
|
||||
narrowing_strength: "strong"
|
||||
}
|
||||
})
|
||||
],
|
||||
requirements: [
|
||||
{
|
||||
requirement_id: "R1",
|
||||
source_fragment_id: "F1",
|
||||
requirement_text: "Проверка списания РБП",
|
||||
subject_tokens: [],
|
||||
status: "covered",
|
||||
route: "hybrid_store_plus_live"
|
||||
}
|
||||
],
|
||||
coverageReport: buildCoverage({ requirements_covered: 0, requirements_partially_covered: ["R1"] }),
|
||||
groundingCheck: buildGrounding({ status: "partial" }),
|
||||
questionTypeHint: "what_is_it_grounded_on",
|
||||
companyAnchors: resolveCompanyAnchors(
|
||||
"31 июля прошло Списание РБП за июль. Есть ли признаки, что часть РБП к концу июля живет дольше ожидаемого?"
|
||||
),
|
||||
normalizationPeriodExplicit: true,
|
||||
enableAnswerPolicyV11: true,
|
||||
enableProblemCentricAnswerV1: true,
|
||||
enableLifecycleAnswerV1: true
|
||||
});
|
||||
|
||||
expect(output.assistant_reply).toMatch(/РБП|списани[ея]\s+РБП|счет\s*97/i);
|
||||
expect(output.assistant_reply).toMatch(/документ списания|остаток/i);
|
||||
expect(output.assistant_reply).not.toMatch(/амортиз|объект\w*\s+ОС|01\/02|сч[её]т\s*0[12]/i);
|
||||
expect(output.assistant_reply).not.toMatch(/отдельн\w*\s+проверк\w*\s+расчетн\w*\s+связк/i);
|
||||
});
|
||||
|
||||
it("does not collapse fixed-asset amortization question into month-close primary narrative", () => {
|
||||
const unit = buildProblemUnit({
|
||||
problem_unit_id: "pu-fa-1",
|
||||
problem_unit_type: "lifecycle_anomaly_node",
|
||||
lifecycle_domain: "fixed_asset",
|
||||
affected_accounts: ["01", "02"],
|
||||
mechanism_summary: "Mechanism candidate: asset_card_to_depreciation.",
|
||||
business_defect_class: "asset_card_to_depreciation",
|
||||
failed_expected_edge: "asset_card_to_depreciation"
|
||||
});
|
||||
|
||||
const output = composeAssistantAnswer({
|
||||
userMessage: "Полно ли начислена амортизация по всем объектам ОС за июль?",
|
||||
routeSummary: buildRouteSummary(),
|
||||
retrievalResults: [
|
||||
buildRetrieval({
|
||||
problem_units: [unit],
|
||||
problem_unit_summary: {
|
||||
schema_version: "problem_unit_summary_v0_1",
|
||||
units_total: 1,
|
||||
duplicate_collapses: 0,
|
||||
unit_types: ["lifecycle_anomaly_node"],
|
||||
type_distribution: {
|
||||
lifecycle_anomaly_node: 1
|
||||
},
|
||||
severity_distribution: {
|
||||
low: 0,
|
||||
medium: 1,
|
||||
high: 0
|
||||
},
|
||||
confidence_distribution: {
|
||||
low: 0,
|
||||
medium: 1,
|
||||
high: 0
|
||||
},
|
||||
primary_unit_type: "lifecycle_anomaly_node"
|
||||
},
|
||||
summary: {
|
||||
semantic_profile: {
|
||||
account_scope: ["01", "02"],
|
||||
domain_scope: ["fixed_assets"],
|
||||
relation_patterns: ["asset_card_to_depreciation", "deferred_expense_to_writeoff"],
|
||||
period_scope: {
|
||||
from: "2020-07-01",
|
||||
to: "2020-07-31",
|
||||
granularity: "month"
|
||||
}
|
||||
},
|
||||
domain_purity_guard: {
|
||||
domain_card_id: "month_close_costs_20_44"
|
||||
},
|
||||
broad_query_detected: false,
|
||||
broad_result_flag: false,
|
||||
minimum_evidence_failed: false,
|
||||
narrowing_strength: "strong"
|
||||
}
|
||||
})
|
||||
],
|
||||
requirements: [
|
||||
{
|
||||
requirement_id: "R1",
|
||||
source_fragment_id: "F1",
|
||||
requirement_text: "Проверка амортизации",
|
||||
subject_tokens: [],
|
||||
status: "covered",
|
||||
route: "hybrid_store_plus_live"
|
||||
}
|
||||
],
|
||||
coverageReport: buildCoverage({ requirements_covered: 0, requirements_partially_covered: ["R1"] }),
|
||||
groundingCheck: buildGrounding({ status: "partial" }),
|
||||
questionTypeHint: "why_breaks",
|
||||
companyAnchors: resolveCompanyAnchors("Полно ли начислена амортизация по всем объектам ОС за июль?"),
|
||||
normalizationPeriodExplicit: true,
|
||||
enableAnswerPolicyV11: true,
|
||||
enableProblemCentricAnswerV1: true,
|
||||
enableLifecycleAnswerV1: true
|
||||
});
|
||||
|
||||
expect(output.assistant_reply).not.toMatch(/цепочка распределения затрат и закрытия месяца/i);
|
||||
expect(output.assistant_reply).toMatch(/карточк[аеи] ОС|амортизац/i);
|
||||
expect(output.assistant_reply).not.toMatch(/contradictory_asset_state|invalid_document_or_posting_transition|\bdisposed\b/i);
|
||||
expect(output.assistant_reply).not.toMatch(/Проверьте связку документов и проводок по проблемному участку/i);
|
||||
expect(output.assistant_reply).toMatch(/объект\w*\s+ОС|параметр\w*\s+амортиз|01\/02|счет\w*\s*0[12]/i);
|
||||
expect(output.assistant_reply).not.toMatch(/РБП|сч[её]т\s*97|документ\s+списани[яе]|остат(ок|ки)\s+РБП|списани[ея]\s+РБП/i);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user