Этап 4 / Волна 10: корректировка settlement-кейса — доменная фиксация синтеза, честное покрытие, удержание фокуса / Этап 4 / Волна 11: бизнес-якоря, доменное заземление и устранение утечки дебага
This commit is contained in:
+114
-4
@@ -75,6 +75,78 @@ function collectOpenUncertainties(coverageReport, retrievalResults) {
|
||||
const limitationNotes = retrievalResults.flatMap((result) => result.limitations).slice(0, 6);
|
||||
return capStrings([...requirementNotes, ...limitationNotes], stage1Contracts_1.INVESTIGATION_MAX_UNCERTAINTIES);
|
||||
}
|
||||
function normalizeAccountPrefix(value) {
|
||||
const account = String(value ?? "").trim();
|
||||
if (!account) {
|
||||
return null;
|
||||
}
|
||||
const match = account.match(/^(\d{2})/);
|
||||
return match?.[1] ?? null;
|
||||
}
|
||||
function isSettlementAccount(value) {
|
||||
const prefix = normalizeAccountPrefix(value);
|
||||
return prefix === "60" || prefix === "62" || prefix === "51" || prefix === "76";
|
||||
}
|
||||
function isVatAccount(value) {
|
||||
const prefix = normalizeAccountPrefix(value);
|
||||
return prefix === "19" || prefix === "68";
|
||||
}
|
||||
function isCloseCostsAccount(value) {
|
||||
const prefix = normalizeAccountPrefix(value);
|
||||
if (!prefix) {
|
||||
return false;
|
||||
}
|
||||
const account = Number(prefix);
|
||||
return (account >= 20 && account <= 44) || prefix === "97";
|
||||
}
|
||||
function inferFollowupActiveDomain(input) {
|
||||
const corpus = `${input.userMessage} ${input.previous.focus.active_query_subject ?? ""}`.toLowerCase();
|
||||
const hasSettlementSignal = input.focusAccounts.some((item) => isSettlementAccount(item)) ||
|
||||
/(60(?:\.\d{2})?|62(?:\.\d{2})?|оплат|расчет|расч[её]т|зачет|зач[её]т|аванс|долг|поставщ|покупат|settlement|payment|supplier|customer)/i.test(corpus);
|
||||
if (hasSettlementSignal) {
|
||||
return "settlements_60_62";
|
||||
}
|
||||
const hasVatSignal = input.focusAccounts.some((item) => isVatAccount(item)) ||
|
||||
/(ндс|счет[\s-]?фактур|сч[её]т[\s-]?фактур|книг[аи]|vat|invoice|book|register)/i.test(corpus);
|
||||
if (hasVatSignal) {
|
||||
return "vat_document_register_book";
|
||||
}
|
||||
const hasCloseSignal = input.focusAccounts.some((item) => isCloseCostsAccount(item)) ||
|
||||
/(закрыти|закрытие|месяц|затрат|распредел|списан|period\s*close|month\s*close|allocation|residual|cost)/i.test(corpus);
|
||||
if (hasCloseSignal) {
|
||||
return "month_close_costs_20_44";
|
||||
}
|
||||
const routeDomain = deriveDomain(input.routeSummary);
|
||||
if (routeDomain && routeDomain !== "no_route") {
|
||||
return routeDomain;
|
||||
}
|
||||
return input.previous.followup_context?.active_domain ?? input.previous.focus.domain ?? null;
|
||||
}
|
||||
function collectUncoveredRequirementIds(coverageReport) {
|
||||
return capStrings([
|
||||
...coverageReport.requirements_uncovered,
|
||||
...coverageReport.requirements_partially_covered,
|
||||
...coverageReport.clarification_needed_for,
|
||||
...coverageReport.out_of_scope_requirements
|
||||
], stage1Contracts_1.INVESTIGATION_MAX_REQUIREMENT_LINKS);
|
||||
}
|
||||
function collectEvidenceSummary(retrievalResults) {
|
||||
const lines = retrievalResults.map((result) => {
|
||||
const requirementRef = result.requirement_ids[0] ?? result.fragment_id;
|
||||
return `${requirementRef}:${result.status}:${result.route}`;
|
||||
});
|
||||
return capStrings(lines, 6);
|
||||
}
|
||||
function settlementFocusActions(activeDomain) {
|
||||
if (activeDomain !== "settlements_60_62") {
|
||||
return [];
|
||||
}
|
||||
return [
|
||||
"Проверьте договор и объект расчетов по платежу.",
|
||||
"Сверьте регистр расчетов и привязку платежа к закрывающему документу.",
|
||||
"Проверьте зачет аванса или взаимозачет по связке 60/62."
|
||||
];
|
||||
}
|
||||
function normalizeEntityBacklinks(values) {
|
||||
const result = [];
|
||||
const seen = new Set();
|
||||
@@ -180,7 +252,27 @@ function cloneInvestigationState(state) {
|
||||
followup_context: state.followup_context
|
||||
? {
|
||||
...state.followup_context,
|
||||
referenced_requirement_ids: [...state.followup_context.referenced_requirement_ids]
|
||||
referenced_requirement_ids: [...state.followup_context.referenced_requirement_ids],
|
||||
...(state.followup_context.active_requirement_ids
|
||||
? {
|
||||
active_requirement_ids: [...state.followup_context.active_requirement_ids]
|
||||
}
|
||||
: {}),
|
||||
...(state.followup_context.uncovered_requirement_ids
|
||||
? {
|
||||
uncovered_requirement_ids: [...state.followup_context.uncovered_requirement_ids]
|
||||
}
|
||||
: {}),
|
||||
...(state.followup_context.settlement_next_actions
|
||||
? {
|
||||
settlement_next_actions: [...state.followup_context.settlement_next_actions]
|
||||
}
|
||||
: {}),
|
||||
...(state.followup_context.evidence_summary
|
||||
? {
|
||||
evidence_summary: [...state.followup_context.evidence_summary]
|
||||
}
|
||||
: {})
|
||||
}
|
||||
: null
|
||||
};
|
||||
@@ -222,9 +314,21 @@ function createEmptyInvestigationState(sessionId, timestamp = new Date().toISOSt
|
||||
function updateInvestigationState(input) {
|
||||
const previous = input.previous;
|
||||
const focusFromMessage = capStrings(detectAccounts(input.userMessage), stage1Contracts_1.INVESTIGATION_MAX_PRIMARY_ACCOUNTS);
|
||||
const mergedFocusAccounts = capStrings([...focusFromMessage, ...previous.focus.primary_accounts], stage1Contracts_1.INVESTIGATION_MAX_PRIMARY_ACCOUNTS);
|
||||
const requirementIds = capStrings(input.requirements.map((item) => item.requirement_id), stage1Contracts_1.INVESTIGATION_MAX_REQUIREMENT_LINKS);
|
||||
const mainRequirement = input.requirements[0]?.requirement_text ?? input.userMessage;
|
||||
const problemUnitState = updateProblemUnitState(previous, input.retrievalResults);
|
||||
const uncoveredRequirementIds = collectUncoveredRequirementIds(input.coverageReport);
|
||||
const activeDomain = inferFollowupActiveDomain({
|
||||
userMessage: input.userMessage,
|
||||
focusAccounts: mergedFocusAccounts,
|
||||
routeSummary: input.routeSummary,
|
||||
previous
|
||||
});
|
||||
const focusDomain = activeDomain ?? deriveDomain(input.routeSummary) ?? previous.focus.domain;
|
||||
const settlementNextActions = settlementFocusActions(activeDomain);
|
||||
const lastProblemUnitId = problemUnitState?.active_problem_units[0] ?? null;
|
||||
const evidenceSummary = collectEvidenceSummary(input.retrievalResults);
|
||||
return {
|
||||
schema_version: stage1Contracts_1.INVESTIGATION_STATE_SCHEMA_VERSION,
|
||||
session_id: previous.session_id,
|
||||
@@ -233,9 +337,9 @@ function updateInvestigationState(input) {
|
||||
updated_at: input.timestamp,
|
||||
question_id: input.questionId,
|
||||
focus: {
|
||||
domain: deriveDomain(input.routeSummary) ?? previous.focus.domain,
|
||||
domain: focusDomain,
|
||||
period: detectPeriod(input.userMessage) ?? previous.focus.period,
|
||||
primary_accounts: capStrings([...focusFromMessage, ...previous.focus.primary_accounts], stage1Contracts_1.INVESTIGATION_MAX_PRIMARY_ACCOUNTS),
|
||||
primary_accounts: mergedFocusAccounts,
|
||||
active_query_subject: mainRequirement.slice(0, 180)
|
||||
},
|
||||
narrowing_status: deriveNarrowingStatus(input.routeSummary, input.coverageReport),
|
||||
@@ -245,7 +349,13 @@ function updateInvestigationState(input) {
|
||||
followup_context: {
|
||||
previous_question_id: previous.question_id,
|
||||
last_user_message: input.userMessage.slice(0, 240),
|
||||
referenced_requirement_ids: requirementIds
|
||||
referenced_requirement_ids: requirementIds,
|
||||
active_domain: activeDomain,
|
||||
active_requirement_ids: requirementIds,
|
||||
uncovered_requirement_ids: uncoveredRequirementIds,
|
||||
last_problem_unit_id: lastProblemUnitId,
|
||||
settlement_next_actions: settlementNextActions,
|
||||
evidence_summary: evidenceSummary
|
||||
},
|
||||
query_mode_hint: deriveQueryModeHint(input.routeSummary),
|
||||
...(problemUnitState
|
||||
|
||||
Reference in New Issue
Block a user