Compare commits

...

3 Commits

19 changed files with 731 additions and 24 deletions

View File

@ -89,7 +89,7 @@
"depends_on": ["s06_vat_by_ambiguous_purchase_date"],
"semantic_tags": ["vat", "purchase_date_carryover", "first_purchase"],
"required_answer_shape": "direct_answer_first",
"required_answer_patterns_all": ["НДС", "первую подтвержденную дату закупки", "05.02.2015", "01.02.2015", "28.02.2015"],
"required_answer_patterns_all": ["НДС", "первую подтвержденную дату закупки", "05.02.2015", "01.01.2015", "31.03.2015"],
"forbidden_answer_patterns": ["(?i)capability_id", "(?i)runtime_", "(?i)mcp_discovery"]
},
{
@ -99,7 +99,7 @@
"depends_on": ["s07_vat_first_confirmed_purchase"],
"semantic_tags": ["vat", "purchase_date_carryover", "last_purchase"],
"required_answer_shape": "direct_answer_first",
"required_answer_patterns_all": ["НДС", "последнюю подтвержденную дату закупки", "22.07.2015", "01.07.2015", "31.07.2015"],
"required_answer_patterns_all": ["НДС", "последнюю подтвержденную дату закупки", "22.07.2015", "01.07.2015", "30.09.2015"],
"forbidden_answer_patterns": ["(?i)capability_id", "(?i)runtime_", "(?i)mcp_discovery"]
}
]
@ -116,7 +116,7 @@
"question": "Есть ли у {{bindings.organization}} остатки товара, которые закупались очень давно",
"semantic_tags": ["inventory", "aging", "supplier_provenance", "field_truth"],
"required_answer_shape": "direct_answer_first",
"required_answer_patterns_all": ["самым старым закупкам", "05.11.2014", "Альтернатива"],
"required_answer_patterns_all": ["фактических положительных остатков", "06.02.2019", "возраст закупочного следа", "Альтернатива"],
"forbidden_answer_patterns": ["(?i)capability_id", "(?i)runtime_", "(?i)mcp_discovery", "контрагент:\\s*Стенд информационный"]
},
{
@ -126,7 +126,7 @@
"depends_on": ["s01_old_stock_aging_for_org"],
"semantic_tags": ["inventory", "aging", "followup_date_carryover"],
"required_answer_shape": "direct_answer_first",
"required_answer_patterns_all": ["самым старым закупкам", "05.11.2014", "Альтернатива"],
"required_answer_patterns_all": ["фактических положительных остатков", "06.02.2019", "25.05.2026", "возраст закупочного следа"],
"forbidden_answer_patterns": ["(?i)capability_id", "(?i)runtime_", "(?i)mcp_discovery"]
}
]

View File

@ -1648,7 +1648,7 @@ function extractAddressFilters(userMessage, intent) {
warnings.push("supplier_anchor_derived_for_inventory_documentary_chain");
}
}
const allowGenericCounterpartyAnchor = !isInventoryTraceIntent(intent);
const allowGenericCounterpartyAnchor = !isInventoryTraceIntent(intent) && intent !== "inventory_on_hand_as_of_date";
const knownFinancialCounterparty = allowGenericCounterpartyAnchor && shouldPreferKnownFinancialCounterpartyAnchor(intent)
? extractKnownFinancialCounterpartyAnchor(text)
: undefined;

View File

@ -376,7 +376,14 @@ function buildFocusObjectFromDebug(debug, resultSetId, createdAt) {
}
}
const objectType = toAddressFocusObjectType(debug.anchor_type);
const canonicalType = objectType === "unknown" ? inferDisplayEntityType(toAddressIntent(debug.detected_intent)) : objectType;
const detectedIntent = toAddressIntent(debug.detected_intent);
if (detectedIntent === "inventory_on_hand_as_of_date") {
const organization = (0, assistantContinuityPolicy_1.readAddressDebugOrganization)(debug, toNonEmptyString);
if (organization) {
return buildFocusObject("organization", organization, resultSetId, createdAt);
}
}
const canonicalType = objectType === "unknown" ? inferDisplayEntityType(detectedIntent) : objectType;
if (canonicalType === "item") {
const item = (0, assistantContinuityPolicy_1.readAddressDebugItem)(debug, toNonEmptyString);
return item ? buildFocusObject(canonicalType, item, resultSetId, createdAt) : null;

View File

@ -1629,6 +1629,17 @@ function applyPreExecutionOrganizationScopeGrounding(input) {
input.semanticFrame.anchor_value = activeOrganization;
}
}
if (activeOrganization &&
sameNormalizedOrganizationScope(input.filters.organization ?? null, activeOrganization) &&
referentialOrganizationScopeDetected &&
typeof input.filters.counterparty !== "string") {
if (!input.warnings.includes("counterparty_cleared_from_referential_organization_scope")) {
input.warnings.push("counterparty_cleared_from_referential_organization_scope");
}
if (!input.baseReasons.includes("counterparty_cleared_from_referential_organization_scope")) {
input.baseReasons.push("counterparty_cleared_from_referential_organization_scope");
}
}
if (activeOrganization &&
sameNormalizedOrganizationScope(input.filters.organization ?? null, activeOrganization) &&
typeof input.filters.counterparty === "string" &&

View File

@ -3198,9 +3198,9 @@ function composeFactualReplyBody(intent, rows, options = {}) {
const purchaseBasisLabel = vatPurchaseDateBasisLabel(options.purchaseDateBridge?.basis, hasMultiplePurchaseDates);
const directVatLine = selectedPurchaseDate
? hasMultiplePurchaseDates
? `Коротко: если брать ${purchaseBasisLabel} ${formatDateRu(selectedPurchaseDate)}, подтвержденный НДС к уплате за налоговый период${organizationScopeLabel}${formatConfirmedMoney(vatToPay)}.`
: `Коротко: по дате покупки ${formatDateRu(selectedPurchaseDate)} подтвержденный НДС к уплате за налоговый период${organizationScopeLabel}${formatConfirmedMoney(vatToPay)}.`
: `Коротко: подтвержденный НДС к уплате за налоговый период${organizationScopeLabel}${formatConfirmedMoney(vatToPay)}.`;
? `Если брать ${purchaseBasisLabel} ${formatDateRu(selectedPurchaseDate)}, подтвержденный НДС к уплате за налоговый период${organizationScopeLabel}${formatConfirmedMoney(vatToPay)}.`
: `По дате покупки ${formatDateRu(selectedPurchaseDate)} подтвержденный НДС к уплате за налоговый период${organizationScopeLabel}${formatConfirmedMoney(vatToPay)}.`
: `Подтвержденный НДС к уплате за налоговый период${organizationScopeLabel}${formatConfirmedMoney(vatToPay)}.`;
const lines = [
directVatLine,
"Расчет сделан по подтвержденным строкам книг продаж и покупок.",

View File

@ -496,6 +496,9 @@ function createAssistantRoutePolicy(deps) {
hasDataRetrievalRequestSignal(repairedRawUserMessage);
const llmContractMode = toNonEmptyString(llmPreDecomposeMeta?.predecomposeContract?.mode);
const llmFirstAddressCandidate = Boolean(llmContractMode === "address_query" && llmContractIntent && llmContractIntent !== "unknown");
const llmSupportedAddressQueryIntent = Boolean(llmContractMode === "address_query" &&
llmContractIntent &&
ADDRESS_INTENTS_KEEP_ADDRESS_LANE.has(llmContractIntent));
const llmFirstUnsupportedCandidate = Boolean(llmContractMode === "unsupported" &&
(!llmContractIntent || llmContractIntent === "unknown"));
const dangerOrCoercionSignal = hasDangerOrCoercionSignal(rawUserMessage) ||
@ -832,6 +835,7 @@ function createAssistantRoutePolicy(deps) {
!capabilityMetaQuery &&
!dangerOrCoercionSignal &&
!effectiveGroundedValueFlowFollowupContextDetected &&
!llmSupportedAddressQueryIntent &&
!organizationClarificationContinuationDetected);
if (unsupportedCurrentTurnMeaningBoundary) {
return {

View File

@ -1912,7 +1912,7 @@ export function extractAddressFilters(userMessage: string, intent: AddressIntent
}
}
const allowGenericCounterpartyAnchor = !isInventoryTraceIntent(intent);
const allowGenericCounterpartyAnchor = !isInventoryTraceIntent(intent) && intent !== "inventory_on_hand_as_of_date";
const knownFinancialCounterparty =
allowGenericCounterpartyAnchor && shouldPreferKnownFinancialCounterpartyAnchor(intent)
? extractKnownFinancialCounterpartyAnchor(text)

View File

@ -442,7 +442,14 @@ function buildFocusObjectFromDebug(debug: Record<string, unknown>, resultSetId:
}
}
const objectType = toAddressFocusObjectType(debug.anchor_type);
const canonicalType = objectType === "unknown" ? inferDisplayEntityType(toAddressIntent(debug.detected_intent)) : objectType;
const detectedIntent = toAddressIntent(debug.detected_intent);
if (detectedIntent === "inventory_on_hand_as_of_date") {
const organization = readAddressDebugOrganization(debug, toNonEmptyString);
if (organization) {
return buildFocusObject("organization", organization, resultSetId, createdAt);
}
}
const canonicalType = objectType === "unknown" ? inferDisplayEntityType(detectedIntent) : objectType;
if (canonicalType === "item") {
const item = readAddressDebugItem(debug, toNonEmptyString);
return item ? buildFocusObject(canonicalType, item, resultSetId, createdAt) : null;

View File

@ -2012,6 +2012,20 @@ function applyPreExecutionOrganizationScopeGrounding(input: {
}
}
if (
activeOrganization &&
sameNormalizedOrganizationScope(input.filters.organization ?? null, activeOrganization) &&
referentialOrganizationScopeDetected &&
typeof input.filters.counterparty !== "string"
) {
if (!input.warnings.includes("counterparty_cleared_from_referential_organization_scope")) {
input.warnings.push("counterparty_cleared_from_referential_organization_scope");
}
if (!input.baseReasons.includes("counterparty_cleared_from_referential_organization_scope")) {
input.baseReasons.push("counterparty_cleared_from_referential_organization_scope");
}
}
if (
activeOrganization &&
sameNormalizedOrganizationScope(input.filters.organization ?? null, activeOrganization) &&

View File

@ -4094,9 +4094,9 @@ function composeFactualReplyBody(
const purchaseBasisLabel = vatPurchaseDateBasisLabel(options.purchaseDateBridge?.basis, hasMultiplePurchaseDates);
const directVatLine = selectedPurchaseDate
? hasMultiplePurchaseDates
? `Коротко: если брать ${purchaseBasisLabel} ${formatDateRu(selectedPurchaseDate)}, подтвержденный НДС к уплате за налоговый период${organizationScopeLabel}${formatConfirmedMoney(vatToPay)}.`
: `Коротко: по дате покупки ${formatDateRu(selectedPurchaseDate)} подтвержденный НДС к уплате за налоговый период${organizationScopeLabel}${formatConfirmedMoney(vatToPay)}.`
: `Коротко: подтвержденный НДС к уплате за налоговый период${organizationScopeLabel}${formatConfirmedMoney(vatToPay)}.`;
? `Если брать ${purchaseBasisLabel} ${formatDateRu(selectedPurchaseDate)}, подтвержденный НДС к уплате за налоговый период${organizationScopeLabel}${formatConfirmedMoney(vatToPay)}.`
: `По дате покупки ${formatDateRu(selectedPurchaseDate)} подтвержденный НДС к уплате за налоговый период${organizationScopeLabel}${formatConfirmedMoney(vatToPay)}.`
: `Подтвержденный НДС к уплате за налоговый период${organizationScopeLabel}${formatConfirmedMoney(vatToPay)}.`;
const lines = [
directVatLine,

View File

@ -584,6 +584,11 @@ export function createAssistantRoutePolicy(deps) {
hasDataRetrievalRequestSignal(repairedRawUserMessage);
const llmContractMode = toNonEmptyString(llmPreDecomposeMeta?.predecomposeContract?.mode);
const llmFirstAddressCandidate = Boolean(llmContractMode === "address_query" && llmContractIntent && llmContractIntent !== "unknown");
const llmSupportedAddressQueryIntent = Boolean(
llmContractMode === "address_query" &&
llmContractIntent &&
ADDRESS_INTENTS_KEEP_ADDRESS_LANE.has(llmContractIntent)
);
const llmFirstUnsupportedCandidate = Boolean(llmContractMode === "unsupported" &&
(!llmContractIntent || llmContractIntent === "unknown"));
const dangerOrCoercionSignal = hasDangerOrCoercionSignal(rawUserMessage) ||
@ -924,6 +929,7 @@ export function createAssistantRoutePolicy(deps) {
!capabilityMetaQuery &&
!dangerOrCoercionSignal &&
!effectiveGroundedValueFlowFollowupContextDetected &&
!llmSupportedAddressQueryIntent &&
!organizationClarificationContinuationDetected);
if (unsupportedCurrentTurnMeaningBoundary) {
return {

View File

@ -101,7 +101,7 @@ describe("inventory aging follow-up", () => {
);
expect(reply.responseType).toBe("FACTUAL_SUMMARY");
expect(reply.text).toContain("К самым старым закупкам");
expect(reply.text).toContain("Среди фактических положительных остатков");
expect(reply.text).toContain("Дата среза: 30.09.2021");
expect(reply.text).toContain("Позиции от самых старых закупок:");
expect(reply.text).toContain("Ограничения:");

View File

@ -2138,7 +2138,7 @@ describe("address compose stage utf8 headers", () => {
);
expect(reply.responseType).toBe("FACTUAL_SUMMARY");
expect(reply.text).toContain("Коротко: подтвержденный НДС к уплате за налоговый период по организации ООО Альтернатива Плюс");
expect(reply.text).toContain("Подтвержденный НДС к уплате за налоговый период по организации ООО Альтернатива Плюс");
expect(reply.text).toContain("Расчет сделан по подтвержденным строкам книг продаж и покупок.");
expect(reply.text).toContain("- Организация: ООО Альтернатива Плюс.");
expect(reply.text).toContain("50.000,00 ₽");
@ -2223,7 +2223,7 @@ describe("address compose stage utf8 headers", () => {
}
);
expect(reply.text).toContain("если брать первую подтвержденную дату закупки 05.02.2015");
expect(reply.text).toContain("Если брать первую подтвержденную дату закупки 05.02.2015");
expect(reply.text).toContain("у позиции несколько подтвержденных дат закупки");
expect(reply.text).toContain("05.02.2015..22.07.2015");
});

View File

@ -1,4 +1,67 @@
[
{
"generation_id": "gen-ag06020614-947fd1",
"created_at": "2026-06-02T06:14:41+00:00",
"mode": "saved_user_sessions",
"title": "AGENT | GUI Y9 inventory selected-object regression proof",
"count": 10,
"domain": "inventory_selected_object_reliability",
"questions": [
"Какие остатки на складе у ООО \"Альтернатива Плюс\"?",
"остатки на март 2016",
"По выбранному объекту \"Рабочая станция универсального специалиста (индивидуальное изготовление)\": где взяли это?",
"а кому продали?",
"у тебя написано кто контрагент: рабочая станция - это ошибка?",
"ндс можешь прикинуть на дату покупки рабочей станции?",
"если у нее несколько закупок, посчитай по первой подтвержденной покупке",
"а теперь по последней подтвержденной покупке",
"Есть ли у ООО \"Альтернатива Плюс\" остатки товара, которые закупались очень давно",
"какие остатки по товарам на эту дату относятся к старым закупкам?"
],
"generated_by": "codex_agent",
"saved_case_set_file": "assistant_autogen_saved_user_sessions_20260602061441_gen-ag06020614-947fd1.json",
"context": {
"llm_provider": null,
"model": null,
"assistant_prompt_version": null,
"decomposition_prompt_version": null,
"prompt_fingerprint": null,
"autogen_personality_id": null,
"autogen_personality_prompt": null,
"source_session_id": null,
"saved_session_file": "assistant_saved_session_20260602061441_gen-ag06020614-947fd1.json",
"saved_case_set_kind": "agent_semantic_scenario",
"agent_run": true,
"agent_focus": "Focused replay for assistant-stage1-Y9qmtnz66r: inventory snapshot, selected item provenance, sale trace, field-truth meta question, VAT carryover from ambiguous purchase dates, and old-stock aging.",
"architecture_phase": "turnaround_11",
"source_spec_file": "X:\\1C\\NDC_1C\\docs\\orchestration\\assistant_stage1_y9_inventory_selected_object_regression_20260525.json",
"scenario_id": null,
"semantic_tags": [
"aging",
"answer_inspection",
"date_carryover",
"field_truth",
"first_purchase",
"followup_date_carryover",
"historical_snapshot",
"inventory",
"item_vs_counterparty",
"last_purchase",
"organization_scope",
"pronoun_followup",
"purchase_date_carryover",
"purchase_provenance",
"sale_trace",
"selected_object",
"supplier_provenance",
"temporal_honesty",
"vat"
],
"validation_status": "accepted_domain_pack_loop",
"validated_run_dir": "artifacts\\domain_runs\\assistant_stage1_y9_inventory_selected_object_20260602_p5",
"saved_after_validated_replay": true
}
},
{
"generation_id": "gen-ag06020454-07ff44",
"created_at": "2026-06-02T04:54:21+00:00",

View File

@ -0,0 +1,249 @@
{
"saved_at": "2026-06-02T06:14:41+00:00",
"generation_id": "gen-ag06020614-947fd1",
"mode": "saved_user_sessions",
"title": "AGENT | GUI Y9 inventory selected-object regression proof",
"agent_run": true,
"questions": [
"Какие остатки на складе у ООО \"Альтернатива Плюс\"?",
"остатки на март 2016",
"По выбранному объекту \"Рабочая станция универсального специалиста (индивидуальное изготовление)\": где взяли это?",
"а кому продали?",
"у тебя написано кто контрагент: рабочая станция - это ошибка?",
"ндс можешь прикинуть на дату покупки рабочей станции?",
"если у нее несколько закупок, посчитай по первой подтвержденной покупке",
"а теперь по последней подтвержденной покупке",
"Есть ли у ООО \"Альтернатива Плюс\" остатки товара, которые закупались очень давно",
"какие остатки по товарам на эту дату относятся к старым закупкам?"
],
"metadata": {
"assistant_prompt_version": null,
"decomposition_prompt_version": null,
"prompt_fingerprint": null,
"agent_focus": "Focused replay for assistant-stage1-Y9qmtnz66r: inventory snapshot, selected item provenance, sale trace, field-truth meta question, VAT carryover from ambiguous purchase dates, and old-stock aging.",
"architecture_phase": "turnaround_11",
"source_spec_file": "X:\\1C\\NDC_1C\\docs\\orchestration\\assistant_stage1_y9_inventory_selected_object_regression_20260525.json",
"scenario_id": null,
"semantic_tags": [
"aging",
"answer_inspection",
"date_carryover",
"field_truth",
"first_purchase",
"followup_date_carryover",
"historical_snapshot",
"inventory",
"item_vs_counterparty",
"last_purchase",
"organization_scope",
"pronoun_followup",
"purchase_date_carryover",
"purchase_provenance",
"sale_trace",
"selected_object",
"supplier_provenance",
"temporal_honesty",
"vat"
],
"validation_status": "accepted_domain_pack_loop",
"validated_run_dir": "artifacts\\domain_runs\\assistant_stage1_y9_inventory_selected_object_20260602_p5",
"saved_after_validated_replay": true,
"save_gate": {
"schema_version": "agent_semantic_save_gate_v1",
"validation_status": "accepted_domain_pack_loop",
"validated_run_dir": "artifacts\\domain_runs\\assistant_stage1_y9_inventory_selected_object_20260602_p5",
"final_status": "accepted",
"loop_id": "assistant_stage1_y9_inventory_selected_object_20260602_p5",
"target_score": 80,
"iterations_ran": 1,
"quality_score": 86,
"repair_target_count": 0,
"repair_target_severity_counts": {
"P0": 0,
"P1": 0,
"P2": 0
},
"accepted_gate": true,
"effective_runtime": {
"manifest_path": "artifacts\\domain_runs\\assistant_stage1_y9_inventory_selected_object_20260602_p5\\effective_runtime.json",
"runner": "domain_case_loop.run-pack-loop",
"git_sha": "5245a8aeea66ca2214b4bc3c18a70e27894df34c",
"backend_url": "http://127.0.0.1:8787",
"mcp_proxy_url": "http://127.0.0.1:6003",
"llm_provider": "local",
"llm_model": "unsloth/qwen3-30b-a3b-instruct-2507",
"temperature": 0.8,
"max_output_tokens": 900,
"prompt_version": "normalizer_v2_0_2",
"prompt_source": "file",
"prompt_hash": "f36e36a5e491cd24511b380e0c0059cb01aea5e2af738fb9f01671cd291735c1",
"prompt_registry_status": "pass"
},
"saved_after_validated_replay": true
}
},
"source_session_id": null,
"session": {
"session_id": null,
"mode": "agent_semantic_run",
"items": [
{
"message_id": "agent-user-001",
"role": "user",
"text": "Какие остатки на складе у ООО \"Альтернатива Плюс\"?",
"created_at": "2026-06-02T06:14:41+00:00",
"reply_type": null,
"trace_id": null,
"debug": null
},
{
"message_id": "agent-user-002",
"role": "user",
"text": "остатки на март 2016",
"created_at": "2026-06-02T06:14:41+00:00",
"reply_type": null,
"trace_id": null,
"debug": null
},
{
"message_id": "agent-user-003",
"role": "user",
"text": "По выбранному объекту \"Рабочая станция универсального специалиста (индивидуальное изготовление)\": где взяли это?",
"created_at": "2026-06-02T06:14:41+00:00",
"reply_type": null,
"trace_id": null,
"debug": null
},
{
"message_id": "agent-user-004",
"role": "user",
"text": "а кому продали?",
"created_at": "2026-06-02T06:14:41+00:00",
"reply_type": null,
"trace_id": null,
"debug": null
},
{
"message_id": "agent-user-005",
"role": "user",
"text": "у тебя написано кто контрагент: рабочая станция - это ошибка?",
"created_at": "2026-06-02T06:14:41+00:00",
"reply_type": null,
"trace_id": null,
"debug": null
},
{
"message_id": "agent-user-006",
"role": "user",
"text": "ндс можешь прикинуть на дату покупки рабочей станции?",
"created_at": "2026-06-02T06:14:41+00:00",
"reply_type": null,
"trace_id": null,
"debug": null
},
{
"message_id": "agent-user-007",
"role": "user",
"text": "если у нее несколько закупок, посчитай по первой подтвержденной покупке",
"created_at": "2026-06-02T06:14:41+00:00",
"reply_type": null,
"trace_id": null,
"debug": null
},
{
"message_id": "agent-user-008",
"role": "user",
"text": "а теперь по последней подтвержденной покупке",
"created_at": "2026-06-02T06:14:41+00:00",
"reply_type": null,
"trace_id": null,
"debug": null
},
{
"message_id": "agent-user-009",
"role": "user",
"text": "Есть ли у ООО \"Альтернатива Плюс\" остатки товара, которые закупались очень давно",
"created_at": "2026-06-02T06:14:41+00:00",
"reply_type": null,
"trace_id": null,
"debug": null
},
{
"message_id": "agent-user-010",
"role": "user",
"text": "какие остатки по товарам на эту дату относятся к старым закупкам?",
"created_at": "2026-06-02T06:14:41+00:00",
"reply_type": null,
"trace_id": null,
"debug": null
}
],
"agent_run": true,
"metadata": {
"assistant_prompt_version": null,
"decomposition_prompt_version": null,
"prompt_fingerprint": null,
"agent_focus": "Focused replay for assistant-stage1-Y9qmtnz66r: inventory snapshot, selected item provenance, sale trace, field-truth meta question, VAT carryover from ambiguous purchase dates, and old-stock aging.",
"architecture_phase": "turnaround_11",
"source_spec_file": "X:\\1C\\NDC_1C\\docs\\orchestration\\assistant_stage1_y9_inventory_selected_object_regression_20260525.json",
"scenario_id": null,
"semantic_tags": [
"aging",
"answer_inspection",
"date_carryover",
"field_truth",
"first_purchase",
"followup_date_carryover",
"historical_snapshot",
"inventory",
"item_vs_counterparty",
"last_purchase",
"organization_scope",
"pronoun_followup",
"purchase_date_carryover",
"purchase_provenance",
"sale_trace",
"selected_object",
"supplier_provenance",
"temporal_honesty",
"vat"
],
"validation_status": "accepted_domain_pack_loop",
"validated_run_dir": "artifacts\\domain_runs\\assistant_stage1_y9_inventory_selected_object_20260602_p5",
"saved_after_validated_replay": true,
"save_gate": {
"schema_version": "agent_semantic_save_gate_v1",
"validation_status": "accepted_domain_pack_loop",
"validated_run_dir": "artifacts\\domain_runs\\assistant_stage1_y9_inventory_selected_object_20260602_p5",
"final_status": "accepted",
"loop_id": "assistant_stage1_y9_inventory_selected_object_20260602_p5",
"target_score": 80,
"iterations_ran": 1,
"quality_score": 86,
"repair_target_count": 0,
"repair_target_severity_counts": {
"P0": 0,
"P1": 0,
"P2": 0
},
"accepted_gate": true,
"effective_runtime": {
"manifest_path": "artifacts\\domain_runs\\assistant_stage1_y9_inventory_selected_object_20260602_p5\\effective_runtime.json",
"runner": "domain_case_loop.run-pack-loop",
"git_sha": "5245a8aeea66ca2214b4bc3c18a70e27894df34c",
"backend_url": "http://127.0.0.1:8787",
"mcp_proxy_url": "http://127.0.0.1:6003",
"llm_provider": "local",
"llm_model": "unsloth/qwen3-30b-a3b-instruct-2507",
"temperature": 0.8,
"max_output_tokens": 900,
"prompt_version": "normalizer_v2_0_2",
"prompt_source": "file",
"prompt_hash": "f36e36a5e491cd24511b380e0c0059cb01aea5e2af738fb9f01671cd291735c1",
"prompt_registry_status": "pass"
},
"saved_after_validated_replay": true
}
}
}
}

View File

@ -0,0 +1,55 @@
{
"suite_id": "assistant_saved_session_gen-ag06020614-947fd1",
"suite_version": "0.1.0",
"schema_version": "assistant_saved_session_suite_v0_1",
"generated_at": "2026-06-02T06:14:41+00:00",
"generation_id": "gen-ag06020614-947fd1",
"mode": "saved_user_sessions",
"title": "AGENT | GUI Y9 inventory selected-object regression proof",
"domain": "inventory_selected_object_reliability",
"scenario_count": 1,
"case_ids": [
"SAVED-001"
],
"cases": [
{
"case_id": "SAVED-001",
"scenario_tag": "agent_saved_user_sessions",
"title": "AGENT | GUI Y9 inventory selected-object regression proof",
"question_type": "followup",
"broadness_level": "medium",
"turns": [
{
"user_message": "Какие остатки на складе у ООО \"Альтернатива Плюс\"?"
},
{
"user_message": "остатки на март 2016"
},
{
"user_message": "По выбранному объекту \"Рабочая станция универсального специалиста (индивидуальное изготовление)\": где взяли это?"
},
{
"user_message": "а кому продали?"
},
{
"user_message": "у тебя написано кто контрагент: рабочая станция - это ошибка?"
},
{
"user_message": "ндс можешь прикинуть на дату покупки рабочей станции?"
},
{
"user_message": "если у нее несколько закупок, посчитай по первой подтвержденной покупке"
},
{
"user_message": "а теперь по последней подтвержденной покупке"
},
{
"user_message": "Есть ли у ООО \"Альтернатива Плюс\" остатки товара, которые закупались очень давно"
},
{
"user_message": "какие остатки по товарам на эту дату относятся к старым закупкам?"
}
]
}
]
}

View File

@ -1,6 +1,6 @@
{
"schema_version": "shared_llm_connection_v1",
"updated_at": "2026-05-25T13:27:06.297Z",
"updated_at": "2026-06-02T05:23:43.938Z",
"connection": {
"llmProvider": "local",
"model": "unsloth/qwen3-30b-a3b-instruct-2507",

View File

@ -2937,15 +2937,27 @@ def build_scenario_step_state(
current_date_scope = derive_mcp_discovery_business_overview_date_scope(debug)
if current_date_scope is None:
current_date_scope = context.get("date_scope")
runtime_contract = (
debug.get("assistant_runtime_contract_v1")
if isinstance(debug.get("assistant_runtime_contract_v1"), dict)
else {}
)
assistant_truth_policy = (
debug.get("assistant_truth_answer_policy_v1")
if isinstance(debug.get("assistant_truth_answer_policy_v1"), dict)
else {}
)
truth_policy = debug.get("truth_answer_policy_v1") if isinstance(debug.get("truth_answer_policy_v1"), dict) else {}
if not truth_policy:
truth_policy = assistant_truth_policy
truth_gate = truth_policy.get("truth_gate") if isinstance(truth_policy.get("truth_gate"), dict) else {}
truth_answer_shape = truth_policy.get("answer_shape") if isinstance(truth_policy.get("answer_shape"), dict) else {}
coverage_gate_contract = (
debug.get("coverage_gate_contract") if isinstance(debug.get("coverage_gate_contract"), dict) else {}
)
answer_shape_contract = (
debug.get("answer_shape_contract") if isinstance(debug.get("answer_shape_contract"), dict) else {}
)
coverage_gate_contract = debug.get("coverage_gate_contract") if isinstance(debug.get("coverage_gate_contract"), dict) else {}
if not coverage_gate_contract:
coverage_gate_contract = truth_gate
answer_shape_contract = debug.get("answer_shape_contract") if isinstance(debug.get("answer_shape_contract"), dict) else {}
if not answer_shape_contract:
answer_shape_contract = truth_answer_shape
raw_answer_shape = debug.get("answer_shape")
debug_answer_shape = raw_answer_shape.get("answer_shape") if isinstance(raw_answer_shape, dict) else raw_answer_shape
@ -2982,7 +2994,22 @@ def build_scenario_step_state(
"detected_intent": debug.get("detected_intent"),
"selected_recipe": debug.get("selected_recipe"),
"capability_id": debug.get("capability_id"),
"capability_contract_id": first_non_empty_string(
debug.get("capability_contract_id"),
runtime_contract.get("capability_contract_id"),
answer_shape_contract.get("capability_contract_id"),
),
"capability_route_mode": debug.get("capability_route_mode"),
"truth_gate_contract_status": first_non_empty_string(
debug.get("truth_gate_contract_status"),
runtime_contract.get("truth_gate_contract_status"),
truth_gate.get("source_truth_gate_status"),
),
"carryover_eligibility": first_non_empty_string(
debug.get("carryover_eligibility"),
runtime_contract.get("carryover_eligibility"),
truth_gate.get("carryover_eligibility"),
),
"mcp_discovery_catalog_chain_alignment_status": debug.get("mcp_discovery_catalog_chain_alignment_status"),
"mcp_discovery_catalog_chain_top_match": debug.get("mcp_discovery_catalog_chain_top_match"),
"mcp_discovery_catalog_chain_selected_matches_top": debug.get("mcp_discovery_catalog_chain_selected_matches_top"),
@ -4081,6 +4108,9 @@ def compact_step_output_for_review(step_output: Any) -> dict[str, Any]:
"detected_intent": step_output.get("detected_intent"),
"selected_recipe": step_output.get("selected_recipe"),
"capability_id": step_output.get("capability_id"),
"capability_contract_id": step_output.get("capability_contract_id"),
"truth_gate_contract_status": step_output.get("truth_gate_contract_status"),
"carryover_eligibility": step_output.get("carryover_eligibility"),
"depends_on": step_output.get("depends_on"),
"semantic_tags": step_output.get("semantic_tags"),
"required_state_objects": step_output.get("required_state_objects"),
@ -4713,6 +4743,84 @@ def normalize_analyst_priority_repair_target(raw_target: dict[str, Any], index:
}
def iso_date_ordinal(value: Any) -> int | None:
normalized = normalize_iso_date(value)
if not normalized:
return None
try:
return datetime.strptime(normalized, "%Y-%m-%d").date().toordinal()
except ValueError:
return None
def extract_date_ordinals_from_text(value: Any) -> list[int]:
text = str(value or "")
dates: list[int] = []
for match in re.finditer(r"\b(\d{4})-(\d{2})-(\d{2})\b", text):
ordinal = iso_date_ordinal(match.group(0))
if ordinal is not None:
dates.append(ordinal)
for match in re.finditer(r"\b(\d{2})\.(\d{2})\.(\d{4})\b", text):
day, month, year = match.groups()
ordinal = iso_date_ordinal(f"{year}-{month}-{day}")
if ordinal is not None:
dates.append(ordinal)
return dates
def validated_temporal_cutoff_target_is_false_positive(
target: dict[str, Any],
step_snapshot: dict[str, Any],
target_text: str,
) -> bool:
temporal_markers = (
"temporal",
"date",
"cutoff",
"historical",
"later",
"post-",
"out-of-window",
"window",
"scope",
"дата",
"дат",
"позже",
"после",
"границ",
"временн",
"окн",
"срез",
)
if not any(marker in target_text for marker in temporal_markers):
return False
extracted_filters = step_snapshot.get("extracted_filters") if isinstance(step_snapshot.get("extracted_filters"), dict) else {}
date_scope = step_snapshot.get("date_scope") if isinstance(step_snapshot.get("date_scope"), dict) else {}
analysis_context = (
step_snapshot.get("analysis_context") if isinstance(step_snapshot.get("analysis_context"), dict) else {}
)
cutoff_ordinal = (
iso_date_ordinal(extracted_filters.get("as_of_date"))
or iso_date_ordinal(date_scope.get("as_of_date"))
or iso_date_ordinal(analysis_context.get("as_of_date"))
)
if cutoff_ordinal is None:
return False
assistant_dates = extract_date_ordinals_from_text(step_snapshot.get("assistant_text_excerpt"))
if not assistant_dates:
return False
if any(date_ordinal > cutoff_ordinal for date_ordinal in assistant_dates):
return False
target_dates = extract_date_ordinals_from_text(target_text)
if target_dates and any(date_ordinal > cutoff_ordinal for date_ordinal in target_dates):
return False
return True
def analyst_target_contradicts_validated_step(target: dict[str, Any], step_snapshot: dict[str, Any] | None) -> bool:
if not isinstance(step_snapshot, dict):
return False
@ -4742,6 +4850,13 @@ def analyst_target_contradicts_validated_step(target: dict[str, Any], step_snaps
"guarded_insufficiency_validated",
"runtime_factual_answer_validated",
"bounded_mcp_answer_validated",
"truth gate",
"runtime truth",
"truth confirmation",
"validated factual status",
"runtime truth confirmation",
"shape-only",
"candidate-only",
"heuristic_candidates",
"silent heuristic",
"unvalidated",
@ -4751,6 +4866,9 @@ def analyst_target_contradicts_validated_step(target: dict[str, Any], step_snaps
if any(marker in target_text for marker in stale_validation_markers):
return True
if validated_temporal_cutoff_target_is_false_positive(target, step_snapshot, target_text):
return True
assistant_text = str(step_snapshot.get("assistant_text_excerpt") or "").casefold()
problem_type = str(target.get("problem_type") or "").strip()
root_cause_layers = set(normalize_string_list(target.get("root_cause_layers")))

View File

@ -677,6 +677,179 @@ class DomainCaseLoopStepStateTests(unittest.TestCase):
self.assertEqual(step_state["business_first_review"]["issue_codes"], [])
self.assertEqual(step_state["acceptance_status"], "validated")
def test_assistant_truth_policy_runtime_contract_validates_exact_factual_step(self) -> None:
step_state = dcl.build_scenario_step_state(
scenario_id="truth_contract_demo",
domain="inventory_selected_object_reliability",
step={
"step_id": "step_01",
"title": "VAT by selected purchase date",
"depends_on": [],
"question_template": "calculate VAT by selected purchase date",
"required_answer_shape": "direct_answer_first",
"required_answer_patterns_all": ["VAT", "Q1 2015"],
},
step_index=1,
question_resolved="calculate VAT by selected purchase date",
analysis_context={},
turn_artifact={
"assistant_message": {
"reply_type": "factual",
"text": "VAT for Q1 2015 is confirmed: 1,556,449.06. Basis: sales and purchase ledgers.",
"message_id": "msg-1",
"trace_id": "trace-1",
},
"technical_debug_payload": {
"detected_mode": "address_query",
"detected_intent": "vat_liability_confirmed_for_tax_period",
"selected_recipe": "address_vat_liability_confirmed_tax_period_v1",
"capability_id": "confirmed_vat_liability_for_tax_period",
"capability_route_mode": "exact",
"fallback_type": "none",
"mcp_call_status": "matched_non_empty",
"response_type": "FACTUAL_SUMMARY",
"result_mode": "confirmed_balance",
"balance_confirmed": True,
"mcp_discovery_route_candidate_status": "ready_for_reviewed_execution",
"mcp_discovery_response_applied": False,
"assistant_runtime_contract_v1": {
"capability_contract_id": "confirmed_vat_liability_for_tax_period",
"truth_gate_contract_status": "full_confirmed",
"carryover_eligibility": "root_only",
},
"assistant_truth_answer_policy_v1": {
"truth_gate": {
"coverage_status": "full",
"evidence_grade": "strong",
"truth_mode": "confirmed",
"source_truth_gate_status": "full_confirmed",
},
"answer_shape": {
"answer_shape": "confirmed_factual",
"capability_contract_id": "confirmed_vat_liability_for_tax_period",
},
},
},
"session_summary": {},
},
entries=[],
)
self.assertEqual(step_state["capability_contract_id"], "confirmed_vat_liability_for_tax_period")
self.assertEqual(step_state["truth_gate_contract_status"], "full_confirmed")
self.assertEqual(step_state["truth_mode"], "confirmed")
self.assertEqual(step_state["coverage_status"], "full")
self.assertEqual(step_state["answer_shape"], "confirmed_factual")
self.assertTrue(step_state["runtime_factual_answer_validated"])
self.assertEqual(step_state["acceptance_status"], "validated")
def test_analyst_shape_only_target_is_suppressed_for_truth_confirmed_runtime_step(self) -> None:
repair_targets = {
"targets": [],
"step_validation_index": {
"scenario_a:step_01": {
"acceptance_status": "validated",
"violated_invariants": [],
"warnings": [],
"runtime_factual_answer_validated": True,
"truth_gate_contract_status": "full_confirmed",
"assistant_text_excerpt": "Confirmed business answer for the selected item.",
}
},
}
analyst_verdict = {
"priority_targets": [
{
"scenario_id": "scenario_a",
"step_id": "step_01",
"severity": "P1",
"problem_type": "capability_gap",
"root_cause_layers": ["runtime_capability_gap"],
"fix_goal": "Remove shape-only acceptance and add runtime truth confirmation.",
}
]
}
merged = dcl.merge_analyst_priority_repair_targets(repair_targets, analyst_verdict)
self.assertEqual(merged["target_count"], 0)
self.assertEqual(merged["suppressed_analyst_priority_target_count"], 1)
self.assertEqual(
merged["suppressed_analyst_priority_targets"][0]["reason"],
"analyst_target_contradicts_validated_step",
)
def test_analyst_temporal_cutoff_false_positive_is_suppressed_for_validated_step(self) -> None:
repair_targets = {
"targets": [],
"step_validation_index": {
"inventory_chain:s03": {
"acceptance_status": "validated",
"violated_invariants": [],
"warnings": [],
"runtime_factual_answer_validated": True,
"extracted_filters": {"as_of_date": "2016-03-31"},
"assistant_text_excerpt": (
"По позиции до 31.03.2016 поставщик не подтвержден. "
"Первая закупка: 05.02.2015. Последняя закупка: 22.07.2015. "
"Опорный документ от 22.07.2015."
),
}
},
}
analyst_verdict = {
"priority_targets": [
{
"scenario_id": "inventory_chain",
"step_id": "s03",
"severity": "P0",
"problem_type": "other",
"root_cause_layers": ["temporal_honesty_gap"],
"fix_goal": "The answer declares a historical cutoff but cites proof rows with later dates.",
}
]
}
merged = dcl.merge_analyst_priority_repair_targets(repair_targets, analyst_verdict)
self.assertEqual(merged["target_count"], 0)
self.assertEqual(merged["suppressed_analyst_priority_target_count"], 1)
def test_analyst_temporal_cutoff_real_out_of_window_target_is_kept(self) -> None:
repair_targets = {
"targets": [],
"step_validation_index": {
"inventory_chain:s03": {
"acceptance_status": "validated",
"violated_invariants": [],
"warnings": [],
"runtime_factual_answer_validated": True,
"extracted_filters": {"as_of_date": "2016-03-31"},
"assistant_text_excerpt": (
"По позиции до 31.03.2016 поставщик не подтвержден. "
"Опорный документ от 25.05.2026."
),
}
},
}
analyst_verdict = {
"priority_targets": [
{
"scenario_id": "inventory_chain",
"step_id": "s03",
"severity": "P0",
"problem_type": "other",
"root_cause_layers": ["temporal_honesty_gap"],
"fix_goal": "The answer declares a historical cutoff but cites proof rows with later dates.",
}
]
}
merged = dcl.merge_analyst_priority_repair_targets(repair_targets, analyst_verdict)
self.assertEqual(merged["target_count"], 1)
self.assertEqual(merged["suppressed_analyst_priority_target_count"], 0)
def test_literal_result_mode_contract_still_rejects_mismatch(self) -> None:
step_state = dcl.build_scenario_step_state(
scenario_id="literal_result_mode_demo",