ARCH: удержать year-switch после contracts pivot
This commit is contained in:
parent
0c4b53ccc6
commit
84beaf5540
|
|
@ -0,0 +1,53 @@
|
||||||
|
{
|
||||||
|
"schema_version": "domain_truth_harness_spec_v1",
|
||||||
|
"scenario_id": "address_truth_harness_phase72_document_to_contracts_year_switch",
|
||||||
|
"domain": "address_phase72_document_to_contracts_year_switch",
|
||||||
|
"title": "Phase 72 document to contracts year-switch continuity",
|
||||||
|
"description": "Replay for a human chain where the user opens documents by counterparty, pivots to contracts with a pronoun follow-up, and then switches the year without renaming the counterparty.",
|
||||||
|
"bindings": {},
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"step_id": "step_01_documents_by_counterparty",
|
||||||
|
"title": "Open documents for the counterparty",
|
||||||
|
"question": "Покажи документы по Жуковке 51.",
|
||||||
|
"allowed_reply_types": ["factual", "factual_with_explanation", "partial_coverage"],
|
||||||
|
"required_answer_patterns_all": [
|
||||||
|
"(?i)жуковк",
|
||||||
|
"(?i)документ|сч[её]т|акт|накладн|строк"
|
||||||
|
],
|
||||||
|
"criticality": "critical",
|
||||||
|
"semantic_tags": ["documents_by_counterparty", "pronoun_pivot_seed", "integrity_guard"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"step_id": "step_02_contracts_by_pronoun_followup",
|
||||||
|
"title": "Pivot to contracts via pronoun follow-up",
|
||||||
|
"question": "А по нему договоры?",
|
||||||
|
"allowed_reply_types": ["factual", "factual_with_explanation", "partial_coverage"],
|
||||||
|
"required_answer_patterns_all": [
|
||||||
|
"(?i)жуковк|контрагент",
|
||||||
|
"(?i)договор|контракт|соглаш"
|
||||||
|
],
|
||||||
|
"criticality": "critical",
|
||||||
|
"semantic_tags": ["contracts_followup", "counterparty_pronoun_resolution", "integrity_guard"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"step_id": "step_03_year_switch_after_contracts_pivot",
|
||||||
|
"title": "Switch the year without renaming the counterparty",
|
||||||
|
"question": "А за 2021?",
|
||||||
|
"allowed_reply_types": ["factual", "factual_with_explanation", "partial_coverage"],
|
||||||
|
"required_answer_patterns_all": [
|
||||||
|
"(?i)2021",
|
||||||
|
"(?i)жуковк|контрагент",
|
||||||
|
"(?i)договор|контракт|соглаш"
|
||||||
|
],
|
||||||
|
"forbidden_answer_patterns": [
|
||||||
|
"(?i)уточните .* контрагент",
|
||||||
|
"(?i)метадан",
|
||||||
|
"(?i)схем",
|
||||||
|
"(?i)объект[а-я]* 1с"
|
||||||
|
],
|
||||||
|
"criticality": "critical",
|
||||||
|
"semantic_tags": ["year_switch_after_pivot", "contracts_followup", "integrity_guard"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
{
|
||||||
|
"schema_version": "domain_truth_harness_spec_v1",
|
||||||
|
"scenario_id": "address_truth_harness_phase73_document_to_contracts_all_time",
|
||||||
|
"domain": "address_phase73_document_to_contracts_all_time",
|
||||||
|
"title": "Phase 73 document to contracts all-time continuity",
|
||||||
|
"description": "Replay for a human chain where the user opens documents by counterparty, pivots to contracts with a pronoun follow-up, and then asks for all-time scope without renaming the counterparty.",
|
||||||
|
"bindings": {},
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"step_id": "step_01_documents_by_counterparty",
|
||||||
|
"title": "Open documents for the counterparty",
|
||||||
|
"question": "Покажи документы по Жуковке 51.",
|
||||||
|
"allowed_reply_types": ["factual", "factual_with_explanation", "partial_coverage"],
|
||||||
|
"required_answer_patterns_all": [
|
||||||
|
"(?i)жуковк",
|
||||||
|
"(?i)документ|сч[её]т|акт|накладн|строк"
|
||||||
|
],
|
||||||
|
"criticality": "critical",
|
||||||
|
"semantic_tags": ["documents_by_counterparty", "pronoun_pivot_seed", "integrity_guard"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"step_id": "step_02_contracts_by_pronoun_followup",
|
||||||
|
"title": "Pivot to contracts via pronoun follow-up",
|
||||||
|
"question": "А по нему договоры?",
|
||||||
|
"allowed_reply_types": ["factual", "factual_with_explanation", "partial_coverage"],
|
||||||
|
"required_answer_patterns_all": [
|
||||||
|
"(?i)жуковк|контрагент",
|
||||||
|
"(?i)договор|контракт|соглаш"
|
||||||
|
],
|
||||||
|
"criticality": "critical",
|
||||||
|
"semantic_tags": ["contracts_followup", "counterparty_pronoun_resolution", "integrity_guard"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"step_id": "step_03_all_time_after_contracts_pivot",
|
||||||
|
"title": "Switch to all-time scope without renaming the counterparty",
|
||||||
|
"question": "А за все время?",
|
||||||
|
"allowed_reply_types": ["factual", "factual_with_explanation", "partial_coverage"],
|
||||||
|
"required_answer_patterns_all": [
|
||||||
|
"(?i)жуковк|контрагент",
|
||||||
|
"(?i)договор|контракт|соглаш"
|
||||||
|
],
|
||||||
|
"forbidden_answer_patterns": [
|
||||||
|
"(?i)уточните .* контрагент",
|
||||||
|
"(?i)уточните .* период",
|
||||||
|
"(?i)метадан",
|
||||||
|
"(?i)схем",
|
||||||
|
"(?i)объект[а-я]* 1с"
|
||||||
|
],
|
||||||
|
"criticality": "critical",
|
||||||
|
"semantic_tags": ["all_time_after_pivot", "contracts_followup", "integrity_guard"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -1839,6 +1839,49 @@ function applyFutureDatedRowsGuard(rows, intent, referenceDate) {
|
||||||
droppedCount
|
droppedCount
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
function applyExplicitPeriodWindowFilter(rows, filters) {
|
||||||
|
const periodFrom = typeof filters.period_from === "string" ? filters.period_from.trim() : "";
|
||||||
|
const periodTo = typeof filters.period_to === "string" ? filters.period_to.trim() : "";
|
||||||
|
if (!periodFrom && !periodTo) {
|
||||||
|
return {
|
||||||
|
rows,
|
||||||
|
droppedCount: 0,
|
||||||
|
applied: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const periodFromTs = periodFrom ? parseIsoDateUtcTimestamp(periodFrom) : null;
|
||||||
|
const periodToTs = periodTo ? parseIsoDateUtcTimestamp(periodTo) : null;
|
||||||
|
if ((periodFrom && periodFromTs === null) || (periodTo && periodToTs === null)) {
|
||||||
|
return {
|
||||||
|
rows,
|
||||||
|
droppedCount: 0,
|
||||||
|
applied: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const keptRows = [];
|
||||||
|
let droppedCount = 0;
|
||||||
|
for (const row of rows) {
|
||||||
|
const rowTs = parseIsoDateUtcTimestamp(row.period);
|
||||||
|
if (rowTs === null) {
|
||||||
|
droppedCount += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (periodFromTs !== null && rowTs < periodFromTs) {
|
||||||
|
droppedCount += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (periodToTs !== null && rowTs > periodToTs) {
|
||||||
|
droppedCount += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
keptRows.push(row);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
rows: keptRows,
|
||||||
|
droppedCount,
|
||||||
|
applied: true
|
||||||
|
};
|
||||||
|
}
|
||||||
function hasExplicitPeriodWindow(filters) {
|
function hasExplicitPeriodWindow(filters) {
|
||||||
return ((typeof filters.period_from === "string" && filters.period_from.trim().length > 0) ||
|
return ((typeof filters.period_from === "string" && filters.period_from.trim().length > 0) ||
|
||||||
(typeof filters.period_to === "string" && filters.period_to.trim().length > 0));
|
(typeof filters.period_to === "string" && filters.period_to.trim().length > 0));
|
||||||
|
|
@ -1855,6 +1898,7 @@ function canAutoBroadenPeriodWindow(intent, filters) {
|
||||||
}
|
}
|
||||||
return (intent === "list_documents_by_counterparty" ||
|
return (intent === "list_documents_by_counterparty" ||
|
||||||
intent === "bank_operations_by_counterparty" ||
|
intent === "bank_operations_by_counterparty" ||
|
||||||
|
intent === "list_contracts_by_counterparty" ||
|
||||||
intent === "list_documents_by_contract" ||
|
intent === "list_documents_by_contract" ||
|
||||||
intent === "bank_operations_by_contract" ||
|
intent === "bank_operations_by_contract" ||
|
||||||
intent === "inventory_purchase_provenance_for_item" ||
|
intent === "inventory_purchase_provenance_for_item" ||
|
||||||
|
|
@ -3327,7 +3371,8 @@ class AddressQueryService {
|
||||||
});
|
});
|
||||||
let anchorFilter = applyAddressFilters(normalizedRows, filtersForMatching);
|
let anchorFilter = applyAddressFilters(normalizedRows, filtersForMatching);
|
||||||
let filterByAnchors = anchorFilter.rows;
|
let filterByAnchors = anchorFilter.rows;
|
||||||
let filteredRowsBeforeFutureGuard = applyIntentSpecificFilter(intent.intent, filterByAnchors);
|
let explicitPeriodWindowFilter = applyExplicitPeriodWindowFilter(filterByAnchors, executionFilters);
|
||||||
|
let filteredRowsBeforeFutureGuard = applyIntentSpecificFilter(intent.intent, explicitPeriodWindowFilter.rows);
|
||||||
let filteredRowsFutureGuard = applyFutureDatedRowsGuard(filteredRowsBeforeFutureGuard, intent.intent, futureGuardReferenceDate);
|
let filteredRowsFutureGuard = applyFutureDatedRowsGuard(filteredRowsBeforeFutureGuard, intent.intent, futureGuardReferenceDate);
|
||||||
let filteredRows = filteredRowsFutureGuard.rows;
|
let filteredRows = filteredRowsFutureGuard.rows;
|
||||||
let organizationWarehouseRecoveryApplied = false;
|
let organizationWarehouseRecoveryApplied = false;
|
||||||
|
|
@ -3369,7 +3414,8 @@ class AddressQueryService {
|
||||||
}
|
}
|
||||||
anchorFilter = applyAddressFilters(normalizedRows, filtersForMatching);
|
anchorFilter = applyAddressFilters(normalizedRows, filtersForMatching);
|
||||||
filterByAnchors = anchorFilter.rows;
|
filterByAnchors = anchorFilter.rows;
|
||||||
filteredRowsBeforeFutureGuard = applyIntentSpecificFilter(intent.intent, filterByAnchors);
|
explicitPeriodWindowFilter = applyExplicitPeriodWindowFilter(filterByAnchors, executionFilters);
|
||||||
|
filteredRowsBeforeFutureGuard = applyIntentSpecificFilter(intent.intent, explicitPeriodWindowFilter.rows);
|
||||||
filteredRowsFutureGuard = applyFutureDatedRowsGuard(filteredRowsBeforeFutureGuard, intent.intent, futureGuardReferenceDate);
|
filteredRowsFutureGuard = applyFutureDatedRowsGuard(filteredRowsBeforeFutureGuard, intent.intent, futureGuardReferenceDate);
|
||||||
filteredRows = filteredRowsFutureGuard.rows;
|
filteredRows = filteredRowsFutureGuard.rows;
|
||||||
organizationWarehouseRecoveryApplied = filteredRows.length > 0;
|
organizationWarehouseRecoveryApplied = filteredRows.length > 0;
|
||||||
|
|
@ -3382,6 +3428,19 @@ class AddressQueryService {
|
||||||
baseReasons.push("future_rows_excluded_from_response");
|
baseReasons.push("future_rows_excluded_from_response");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (explicitPeriodWindowFilter.applied) {
|
||||||
|
if (!baseReasons.includes("explicit_period_window_post_filter_applied")) {
|
||||||
|
baseReasons.push("explicit_period_window_post_filter_applied");
|
||||||
|
}
|
||||||
|
if (explicitPeriodWindowFilter.droppedCount > 0) {
|
||||||
|
if (!filters.warnings.includes("rows_outside_explicit_period_window_excluded")) {
|
||||||
|
filters.warnings.push("rows_outside_explicit_period_window_excluded");
|
||||||
|
}
|
||||||
|
if (!baseReasons.includes("rows_outside_explicit_period_window_excluded")) {
|
||||||
|
baseReasons.push("rows_outside_explicit_period_window_excluded");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
const rowDiagnostics = deriveRowStageDiagnostics(mcp.raw_rows, normalizedRows.length, normalizedRows.length);
|
const rowDiagnostics = deriveRowStageDiagnostics(mcp.raw_rows, normalizedRows.length, normalizedRows.length);
|
||||||
const stageStatus = deriveMcpStageStatus({
|
const stageStatus = deriveMcpStageStatus({
|
||||||
rawRowsReceived: mcp.raw_rows.length,
|
rawRowsReceived: mcp.raw_rows.length,
|
||||||
|
|
@ -3758,7 +3817,8 @@ class AddressQueryService {
|
||||||
});
|
});
|
||||||
const expandedAnchorFilter = applyAddressFilters(expandedNormalizedRows, expandedFiltersForMatching);
|
const expandedAnchorFilter = applyAddressFilters(expandedNormalizedRows, expandedFiltersForMatching);
|
||||||
const expandedRowsByAnchor = expandedAnchorFilter.rows;
|
const expandedRowsByAnchor = expandedAnchorFilter.rows;
|
||||||
const expandedFilteredRowsBeforeFutureGuard = applyIntentSpecificFilter(intent.intent, expandedRowsByAnchor);
|
const expandedExplicitPeriodWindowFilter = applyExplicitPeriodWindowFilter(expandedRowsByAnchor, expandedLimitFilters);
|
||||||
|
const expandedFilteredRowsBeforeFutureGuard = applyIntentSpecificFilter(intent.intent, expandedExplicitPeriodWindowFilter.rows);
|
||||||
const expandedFutureGuard = applyFutureDatedRowsGuard(expandedFilteredRowsBeforeFutureGuard, intent.intent, resolveFutureGuardReferenceDate(analysisDate, expandedLimitFilters));
|
const expandedFutureGuard = applyFutureDatedRowsGuard(expandedFilteredRowsBeforeFutureGuard, intent.intent, resolveFutureGuardReferenceDate(analysisDate, expandedLimitFilters));
|
||||||
const expandedFilteredRows = expandedFutureGuard.rows;
|
const expandedFilteredRows = expandedFutureGuard.rows;
|
||||||
if (expandedFutureGuard.droppedCount > 0) {
|
if (expandedFutureGuard.droppedCount > 0) {
|
||||||
|
|
@ -3981,7 +4041,8 @@ class AddressQueryService {
|
||||||
});
|
});
|
||||||
const historicalAnchorFilter = applyAddressFilters(historicalNormalizedRows, historicalFiltersForMatching);
|
const historicalAnchorFilter = applyAddressFilters(historicalNormalizedRows, historicalFiltersForMatching);
|
||||||
const historicalRowsByAnchor = historicalAnchorFilter.rows;
|
const historicalRowsByAnchor = historicalAnchorFilter.rows;
|
||||||
const historicalFilteredRowsBeforeFutureGuard = applyIntentSpecificFilter(intent.intent, historicalRowsByAnchor);
|
const historicalExplicitPeriodWindowFilter = applyExplicitPeriodWindowFilter(historicalRowsByAnchor, historicalFilters);
|
||||||
|
const historicalFilteredRowsBeforeFutureGuard = applyIntentSpecificFilter(intent.intent, historicalExplicitPeriodWindowFilter.rows);
|
||||||
const historicalFutureGuard = applyFutureDatedRowsGuard(historicalFilteredRowsBeforeFutureGuard, intent.intent, resolveFutureGuardReferenceDate(analysisDate, historicalFilters));
|
const historicalFutureGuard = applyFutureDatedRowsGuard(historicalFilteredRowsBeforeFutureGuard, intent.intent, resolveFutureGuardReferenceDate(analysisDate, historicalFilters));
|
||||||
const historicalFilteredRows = historicalFutureGuard.rows;
|
const historicalFilteredRows = historicalFutureGuard.rows;
|
||||||
if (historicalFutureGuard.droppedCount > 0) {
|
if (historicalFutureGuard.droppedCount > 0) {
|
||||||
|
|
|
||||||
|
|
@ -871,7 +871,7 @@ const BASE_RECIPES = [
|
||||||
intent: "list_contracts_by_counterparty",
|
intent: "list_contracts_by_counterparty",
|
||||||
purpose: "List contracts by counterparty from contract catalog",
|
purpose: "List contracts by counterparty from contract catalog",
|
||||||
required_filters: ["counterparty"],
|
required_filters: ["counterparty"],
|
||||||
optional_filters: ["limit", "sort"],
|
optional_filters: ["period_from", "period_to", "as_of_date", "organization", "limit", "sort"],
|
||||||
default_limit: 300,
|
default_limit: 300,
|
||||||
account_scope_mode: "preferred",
|
account_scope_mode: "preferred",
|
||||||
query_template: "contracts_by_counterparty_profile"
|
query_template: "contracts_by_counterparty_profile"
|
||||||
|
|
|
||||||
|
|
@ -2274,6 +2274,56 @@ function applyFutureDatedRowsGuard(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function applyExplicitPeriodWindowFilter(
|
||||||
|
rows: NormalizedAddressRow[],
|
||||||
|
filters: AddressFilterSet
|
||||||
|
): { rows: NormalizedAddressRow[]; droppedCount: number; applied: boolean } {
|
||||||
|
const periodFrom = typeof filters.period_from === "string" ? filters.period_from.trim() : "";
|
||||||
|
const periodTo = typeof filters.period_to === "string" ? filters.period_to.trim() : "";
|
||||||
|
if (!periodFrom && !periodTo) {
|
||||||
|
return {
|
||||||
|
rows,
|
||||||
|
droppedCount: 0,
|
||||||
|
applied: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const periodFromTs = periodFrom ? parseIsoDateUtcTimestamp(periodFrom) : null;
|
||||||
|
const periodToTs = periodTo ? parseIsoDateUtcTimestamp(periodTo) : null;
|
||||||
|
if ((periodFrom && periodFromTs === null) || (periodTo && periodToTs === null)) {
|
||||||
|
return {
|
||||||
|
rows,
|
||||||
|
droppedCount: 0,
|
||||||
|
applied: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const keptRows: NormalizedAddressRow[] = [];
|
||||||
|
let droppedCount = 0;
|
||||||
|
for (const row of rows) {
|
||||||
|
const rowTs = parseIsoDateUtcTimestamp(row.period);
|
||||||
|
if (rowTs === null) {
|
||||||
|
droppedCount += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (periodFromTs !== null && rowTs < periodFromTs) {
|
||||||
|
droppedCount += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (periodToTs !== null && rowTs > periodToTs) {
|
||||||
|
droppedCount += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
keptRows.push(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
rows: keptRows,
|
||||||
|
droppedCount,
|
||||||
|
applied: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function hasExplicitPeriodWindow(filters: AddressFilterSet): boolean {
|
function hasExplicitPeriodWindow(filters: AddressFilterSet): boolean {
|
||||||
return (
|
return (
|
||||||
(typeof filters.period_from === "string" && filters.period_from.trim().length > 0) ||
|
(typeof filters.period_from === "string" && filters.period_from.trim().length > 0) ||
|
||||||
|
|
@ -2295,6 +2345,7 @@ function canAutoBroadenPeriodWindow(intent: AddressIntent, filters: AddressFilte
|
||||||
return (
|
return (
|
||||||
intent === "list_documents_by_counterparty" ||
|
intent === "list_documents_by_counterparty" ||
|
||||||
intent === "bank_operations_by_counterparty" ||
|
intent === "bank_operations_by_counterparty" ||
|
||||||
|
intent === "list_contracts_by_counterparty" ||
|
||||||
intent === "list_documents_by_contract" ||
|
intent === "list_documents_by_contract" ||
|
||||||
intent === "bank_operations_by_contract" ||
|
intent === "bank_operations_by_contract" ||
|
||||||
intent === "inventory_purchase_provenance_for_item" ||
|
intent === "inventory_purchase_provenance_for_item" ||
|
||||||
|
|
@ -4082,7 +4133,8 @@ export class AddressQueryService {
|
||||||
});
|
});
|
||||||
let anchorFilter = applyAddressFilters(normalizedRows, filtersForMatching);
|
let anchorFilter = applyAddressFilters(normalizedRows, filtersForMatching);
|
||||||
let filterByAnchors = anchorFilter.rows;
|
let filterByAnchors = anchorFilter.rows;
|
||||||
let filteredRowsBeforeFutureGuard = applyIntentSpecificFilter(intent.intent, filterByAnchors);
|
let explicitPeriodWindowFilter = applyExplicitPeriodWindowFilter(filterByAnchors, executionFilters);
|
||||||
|
let filteredRowsBeforeFutureGuard = applyIntentSpecificFilter(intent.intent, explicitPeriodWindowFilter.rows);
|
||||||
let filteredRowsFutureGuard = applyFutureDatedRowsGuard(
|
let filteredRowsFutureGuard = applyFutureDatedRowsGuard(
|
||||||
filteredRowsBeforeFutureGuard,
|
filteredRowsBeforeFutureGuard,
|
||||||
intent.intent,
|
intent.intent,
|
||||||
|
|
@ -4130,7 +4182,8 @@ export class AddressQueryService {
|
||||||
}
|
}
|
||||||
anchorFilter = applyAddressFilters(normalizedRows, filtersForMatching);
|
anchorFilter = applyAddressFilters(normalizedRows, filtersForMatching);
|
||||||
filterByAnchors = anchorFilter.rows;
|
filterByAnchors = anchorFilter.rows;
|
||||||
filteredRowsBeforeFutureGuard = applyIntentSpecificFilter(intent.intent, filterByAnchors);
|
explicitPeriodWindowFilter = applyExplicitPeriodWindowFilter(filterByAnchors, executionFilters);
|
||||||
|
filteredRowsBeforeFutureGuard = applyIntentSpecificFilter(intent.intent, explicitPeriodWindowFilter.rows);
|
||||||
filteredRowsFutureGuard = applyFutureDatedRowsGuard(
|
filteredRowsFutureGuard = applyFutureDatedRowsGuard(
|
||||||
filteredRowsBeforeFutureGuard,
|
filteredRowsBeforeFutureGuard,
|
||||||
intent.intent,
|
intent.intent,
|
||||||
|
|
@ -4147,6 +4200,19 @@ export class AddressQueryService {
|
||||||
baseReasons.push("future_rows_excluded_from_response");
|
baseReasons.push("future_rows_excluded_from_response");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (explicitPeriodWindowFilter.applied) {
|
||||||
|
if (!baseReasons.includes("explicit_period_window_post_filter_applied")) {
|
||||||
|
baseReasons.push("explicit_period_window_post_filter_applied");
|
||||||
|
}
|
||||||
|
if (explicitPeriodWindowFilter.droppedCount > 0) {
|
||||||
|
if (!filters.warnings.includes("rows_outside_explicit_period_window_excluded")) {
|
||||||
|
filters.warnings.push("rows_outside_explicit_period_window_excluded");
|
||||||
|
}
|
||||||
|
if (!baseReasons.includes("rows_outside_explicit_period_window_excluded")) {
|
||||||
|
baseReasons.push("rows_outside_explicit_period_window_excluded");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
const rowDiagnostics = deriveRowStageDiagnostics(mcp.raw_rows, normalizedRows.length, normalizedRows.length);
|
const rowDiagnostics = deriveRowStageDiagnostics(mcp.raw_rows, normalizedRows.length, normalizedRows.length);
|
||||||
const stageStatus = deriveMcpStageStatus({
|
const stageStatus = deriveMcpStageStatus({
|
||||||
rawRowsReceived: mcp.raw_rows.length,
|
rawRowsReceived: mcp.raw_rows.length,
|
||||||
|
|
@ -4599,7 +4665,14 @@ export class AddressQueryService {
|
||||||
});
|
});
|
||||||
const expandedAnchorFilter = applyAddressFilters(expandedNormalizedRows, expandedFiltersForMatching);
|
const expandedAnchorFilter = applyAddressFilters(expandedNormalizedRows, expandedFiltersForMatching);
|
||||||
const expandedRowsByAnchor = expandedAnchorFilter.rows;
|
const expandedRowsByAnchor = expandedAnchorFilter.rows;
|
||||||
const expandedFilteredRowsBeforeFutureGuard = applyIntentSpecificFilter(intent.intent, expandedRowsByAnchor);
|
const expandedExplicitPeriodWindowFilter = applyExplicitPeriodWindowFilter(
|
||||||
|
expandedRowsByAnchor,
|
||||||
|
expandedLimitFilters
|
||||||
|
);
|
||||||
|
const expandedFilteredRowsBeforeFutureGuard = applyIntentSpecificFilter(
|
||||||
|
intent.intent,
|
||||||
|
expandedExplicitPeriodWindowFilter.rows
|
||||||
|
);
|
||||||
const expandedFutureGuard = applyFutureDatedRowsGuard(
|
const expandedFutureGuard = applyFutureDatedRowsGuard(
|
||||||
expandedFilteredRowsBeforeFutureGuard,
|
expandedFilteredRowsBeforeFutureGuard,
|
||||||
intent.intent,
|
intent.intent,
|
||||||
|
|
@ -4859,7 +4932,14 @@ export class AddressQueryService {
|
||||||
});
|
});
|
||||||
const historicalAnchorFilter = applyAddressFilters(historicalNormalizedRows, historicalFiltersForMatching);
|
const historicalAnchorFilter = applyAddressFilters(historicalNormalizedRows, historicalFiltersForMatching);
|
||||||
const historicalRowsByAnchor = historicalAnchorFilter.rows;
|
const historicalRowsByAnchor = historicalAnchorFilter.rows;
|
||||||
const historicalFilteredRowsBeforeFutureGuard = applyIntentSpecificFilter(intent.intent, historicalRowsByAnchor);
|
const historicalExplicitPeriodWindowFilter = applyExplicitPeriodWindowFilter(
|
||||||
|
historicalRowsByAnchor,
|
||||||
|
historicalFilters
|
||||||
|
);
|
||||||
|
const historicalFilteredRowsBeforeFutureGuard = applyIntentSpecificFilter(
|
||||||
|
intent.intent,
|
||||||
|
historicalExplicitPeriodWindowFilter.rows
|
||||||
|
);
|
||||||
const historicalFutureGuard = applyFutureDatedRowsGuard(
|
const historicalFutureGuard = applyFutureDatedRowsGuard(
|
||||||
historicalFilteredRowsBeforeFutureGuard,
|
historicalFilteredRowsBeforeFutureGuard,
|
||||||
intent.intent,
|
intent.intent,
|
||||||
|
|
|
||||||
|
|
@ -895,7 +895,7 @@ const BASE_RECIPES: AddressRecipeDefinition[] = [
|
||||||
intent: "list_contracts_by_counterparty",
|
intent: "list_contracts_by_counterparty",
|
||||||
purpose: "List contracts by counterparty from contract catalog",
|
purpose: "List contracts by counterparty from contract catalog",
|
||||||
required_filters: ["counterparty"],
|
required_filters: ["counterparty"],
|
||||||
optional_filters: ["limit", "sort"],
|
optional_filters: ["period_from", "period_to", "as_of_date", "organization", "limit", "sort"],
|
||||||
default_limit: 300,
|
default_limit: 300,
|
||||||
account_scope_mode: "preferred",
|
account_scope_mode: "preferred",
|
||||||
query_template: "contracts_by_counterparty_profile"
|
query_template: "contracts_by_counterparty_profile"
|
||||||
|
|
|
||||||
|
|
@ -4080,6 +4080,28 @@ describe("address query limited taxonomy and stage diagnostics", { timeout: 1500
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("auto-broadens out-of-window period after contracts pivot and keeps requested year in the reply", async () => {
|
||||||
|
const service = new AddressQueryService();
|
||||||
|
const seed = await service.tryHandle("покажи договора все по жуковке 51");
|
||||||
|
expect(seed?.handled).toBe(true);
|
||||||
|
expect(seed?.debug.detected_intent).toBe("list_contracts_by_counterparty");
|
||||||
|
|
||||||
|
const result = await service.tryHandle("Р° Р·Р° 2021?", {
|
||||||
|
followupContext: {
|
||||||
|
previous_intent: (seed?.debug.detected_intent as any) ?? "list_contracts_by_counterparty",
|
||||||
|
previous_filters: seed?.debug.extracted_filters,
|
||||||
|
previous_anchor_type: (seed?.debug.anchor_type as any) ?? "counterparty",
|
||||||
|
previous_anchor_value: seed?.debug.anchor_value_resolved ?? seed?.debug.anchor_value_raw ?? null
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result?.handled).toBe(true);
|
||||||
|
expect(result?.debug.detected_intent).toBe("list_contracts_by_counterparty");
|
||||||
|
expect(result?.debug.selected_recipe).toBe("address_contracts_by_counterparty_v1");
|
||||||
|
expect(result?.debug.limitations).toContain("period_window_auto_broadened_to_available_data");
|
||||||
|
expect(String(result?.reply_text ?? "")).toContain("2021");
|
||||||
|
});
|
||||||
|
|
||||||
describe("address decompose stage follow-up carryover", () => {
|
describe("address decompose stage follow-up carryover", () => {
|
||||||
it("promotes selected-object supplier slang follow-up into inventory provenance with inherited date context", () => {
|
it("promotes selected-object supplier slang follow-up into inventory provenance with inherited date context", () => {
|
||||||
const result = runAddressDecomposeStage('По выбранному объекту "Столешница 600*3050*26 дуб ниагара": кто это поставил нам', {
|
const result = runAddressDecomposeStage('По выбранному объекту "Столешница 600*3050*26 дуб ниагара": кто это поставил нам', {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue