ARCH: замкнуть all-time continuity после metadata retrieval
This commit is contained in:
parent
4a6ac6bd99
commit
14465c7fde
|
|
@ -0,0 +1,78 @@
|
|||
{
|
||||
"schema_version": "domain_truth_harness_spec_v1",
|
||||
"scenario_id": "address_truth_harness_phase57_metadata_movement_all_time_after_retrieval",
|
||||
"domain": "address_phase57_metadata_movement_all_time_after_retrieval",
|
||||
"title": "Phase 57 metadata movement all-time follow-up after bounded retrieval",
|
||||
"description": "Targeted AGENT replay for Big Block F where a metadata-born movement loop reaches bounded retrieval and then survives a short all-time follow-up without losing organization or resetting the movement lane.",
|
||||
"bindings": {},
|
||||
"steps": [
|
||||
{
|
||||
"step_id": "step_01_metadata_ambiguity_surface",
|
||||
"title": "Metadata ambiguity is surfaced honestly for VAT",
|
||||
"question": "какие объекты 1С есть по НДС?",
|
||||
"allowed_reply_types": ["partial_coverage", "factual_with_explanation"],
|
||||
"required_answer_patterns_all": [
|
||||
"(?i)metadata|метадан",
|
||||
"(?i)ндс",
|
||||
"(?i)документ|регистр"
|
||||
],
|
||||
"criticality": "critical",
|
||||
"semantic_tags": ["metadata_surface", "mixed_ambiguity"]
|
||||
},
|
||||
{
|
||||
"step_id": "step_02_neutral_followup_requires_lane_choice",
|
||||
"title": "Neutral follow-up still requires lane choice",
|
||||
"question": "давай дальше",
|
||||
"allowed_reply_types": ["clarification_required", "partial_coverage"],
|
||||
"required_answer_patterns_all": [
|
||||
"(?i)документ",
|
||||
"(?i)движени|регистр",
|
||||
"(?i)уточн|выб(ери|рать)|какой контур"
|
||||
],
|
||||
"criticality": "critical",
|
||||
"semantic_tags": ["metadata_lane_choice_clarification", "neutral_followup"]
|
||||
},
|
||||
{
|
||||
"step_id": "step_03_inline_lane_choice_with_org_keeps_only_period_gap",
|
||||
"title": "Movement lane plus organization in one follow-up leaves only the period gap",
|
||||
"question": "по движениям по ООО Альтернатива Плюс",
|
||||
"allowed_reply_types": ["clarification_required", "partial_coverage"],
|
||||
"required_answer_patterns_all": [
|
||||
"(?i)движени|регистр",
|
||||
"(?i)период"
|
||||
],
|
||||
"criticality": "critical",
|
||||
"semantic_tags": ["movement_lane_after_clarification", "inline_organization_clarification"]
|
||||
},
|
||||
{
|
||||
"step_id": "step_04_period_clarification_executes_same_movement_loop",
|
||||
"title": "Period clarification executes the same bounded movement loop",
|
||||
"question": "за 2020 год",
|
||||
"allowed_reply_types": ["factual", "factual_with_explanation", "partial_coverage"],
|
||||
"required_answer_patterns_all": [
|
||||
"(?i)ндс|движени|регистр|операц|платеж|поступлен|списан|строк"
|
||||
],
|
||||
"criticality": "critical",
|
||||
"semantic_tags": ["movement_lane_execution", "bounded_retrieval"]
|
||||
},
|
||||
{
|
||||
"step_id": "step_05_all_time_followup_keeps_same_movement_loop",
|
||||
"title": "All-time follow-up clears the previous period but keeps the same movement lane and organization",
|
||||
"question": "а теперь за все время?",
|
||||
"allowed_reply_types": ["factual", "factual_with_explanation", "partial_coverage"],
|
||||
"required_answer_patterns_all": [
|
||||
"(?i)все время|доступное время|весь период",
|
||||
"(?i)ндс|движени|регистр|операц|платеж|поступлен|списан|строк"
|
||||
],
|
||||
"forbidden_answer_patterns": [
|
||||
"(?i)уточните .*организац",
|
||||
"(?i)уточните .*контур",
|
||||
"(?i)за 2020",
|
||||
"(?i)документ",
|
||||
"(?i)не найден контрагент"
|
||||
],
|
||||
"criticality": "critical",
|
||||
"semantic_tags": ["all_time_followup", "movement_lane_continuity", "period_cleared"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
{
|
||||
"schema_version": "domain_truth_harness_spec_v1",
|
||||
"scenario_id": "address_truth_harness_phase58_metadata_document_to_movement_pivot",
|
||||
"domain": "address_phase58_metadata_document_to_movement_pivot",
|
||||
"title": "Phase 58 metadata document retrieval to movement pivot",
|
||||
"description": "Targeted AGENT replay for Big Block F where a metadata-born document loop reaches bounded retrieval and then pivots into movement evidence on a short follow-up without losing organization or resetting the scoped proof path.",
|
||||
"bindings": {},
|
||||
"steps": [
|
||||
{
|
||||
"step_id": "step_01_metadata_ambiguity_surface",
|
||||
"title": "Metadata ambiguity is surfaced honestly for VAT",
|
||||
"question": "какие объекты 1С есть по НДС?",
|
||||
"allowed_reply_types": ["partial_coverage", "factual_with_explanation"],
|
||||
"required_answer_patterns_all": [
|
||||
"(?i)metadata|метадан",
|
||||
"(?i)ндс",
|
||||
"(?i)документ|регистр"
|
||||
],
|
||||
"criticality": "critical",
|
||||
"semantic_tags": ["metadata_surface", "mixed_ambiguity"]
|
||||
},
|
||||
{
|
||||
"step_id": "step_02_neutral_followup_requires_lane_choice",
|
||||
"title": "Neutral follow-up still requires lane choice",
|
||||
"question": "давай дальше",
|
||||
"allowed_reply_types": ["clarification_required", "partial_coverage"],
|
||||
"required_answer_patterns_all": [
|
||||
"(?i)документ",
|
||||
"(?i)движени|регистр",
|
||||
"(?i)уточн|выб(ери|рать)|какой контур"
|
||||
],
|
||||
"criticality": "critical",
|
||||
"semantic_tags": ["metadata_lane_choice_clarification", "neutral_followup"]
|
||||
},
|
||||
{
|
||||
"step_id": "step_03_document_lane_with_org_keeps_only_period_gap",
|
||||
"title": "Document lane plus organization in one follow-up leaves only the period gap",
|
||||
"question": "по документам по ООО Альтернатива Плюс",
|
||||
"allowed_reply_types": ["clarification_required", "partial_coverage"],
|
||||
"required_answer_patterns_all": [
|
||||
"(?i)документ|счет|накладн|акт",
|
||||
"(?i)период"
|
||||
],
|
||||
"criticality": "critical",
|
||||
"semantic_tags": ["document_lane_after_clarification", "inline_organization_clarification"]
|
||||
},
|
||||
{
|
||||
"step_id": "step_04_period_clarification_executes_same_document_loop",
|
||||
"title": "Period clarification executes the same bounded document loop",
|
||||
"question": "за 2020 год",
|
||||
"allowed_reply_types": ["factual", "factual_with_explanation", "partial_coverage"],
|
||||
"required_answer_patterns_all": [
|
||||
"(?i)документ|счет|сч[её]т[- ]?фактур|накладн|акт|строк"
|
||||
],
|
||||
"criticality": "critical",
|
||||
"semantic_tags": ["document_lane_execution", "bounded_retrieval"]
|
||||
},
|
||||
{
|
||||
"step_id": "step_05_movement_pivot_keeps_same_scope",
|
||||
"title": "Short movement pivot reuses the same organization and period",
|
||||
"question": "а теперь по движениям?",
|
||||
"allowed_reply_types": ["factual", "factual_with_explanation", "partial_coverage"],
|
||||
"required_answer_patterns_all": [
|
||||
"(?i)ндс|движени|регистр|операц|платеж|поступлен|списан|строк"
|
||||
],
|
||||
"forbidden_answer_patterns": [
|
||||
"(?i)уточните .*организац",
|
||||
"(?i)уточните .*период",
|
||||
"(?i)уточните .*контур",
|
||||
"(?i)не найден контрагент"
|
||||
],
|
||||
"criticality": "critical",
|
||||
"semantic_tags": ["movement_pivot_after_document_retrieval", "scope_reuse", "same_proof_path_family_shift"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
{
|
||||
"schema_version": "domain_truth_harness_spec_v1",
|
||||
"scenario_id": "address_truth_harness_phase59_metadata_document_all_time_after_retrieval",
|
||||
"domain": "address_phase59_metadata_document_all_time_after_retrieval",
|
||||
"title": "Phase 59 metadata document all-time follow-up after bounded retrieval",
|
||||
"description": "Targeted AGENT replay for Big Block F where a metadata-born document loop reaches bounded retrieval and then survives a short all-time follow-up without losing organization or resetting the document lane.",
|
||||
"bindings": {},
|
||||
"steps": [
|
||||
{
|
||||
"step_id": "step_01_metadata_ambiguity_surface",
|
||||
"title": "Metadata ambiguity is surfaced honestly for VAT",
|
||||
"question": "какие объекты 1С есть по НДС?",
|
||||
"allowed_reply_types": ["partial_coverage", "factual_with_explanation"],
|
||||
"required_answer_patterns_all": [
|
||||
"(?i)metadata|метадан",
|
||||
"(?i)ндс",
|
||||
"(?i)документ|регистр"
|
||||
],
|
||||
"criticality": "critical",
|
||||
"semantic_tags": ["metadata_surface", "mixed_ambiguity"]
|
||||
},
|
||||
{
|
||||
"step_id": "step_02_neutral_followup_requires_lane_choice",
|
||||
"title": "Neutral follow-up still requires lane choice",
|
||||
"question": "давай дальше",
|
||||
"allowed_reply_types": ["clarification_required", "partial_coverage"],
|
||||
"required_answer_patterns_all": [
|
||||
"(?i)документ",
|
||||
"(?i)движени|регистр",
|
||||
"(?i)уточн|выб(ери|рать)|какой контур"
|
||||
],
|
||||
"criticality": "critical",
|
||||
"semantic_tags": ["metadata_lane_choice_clarification", "neutral_followup"]
|
||||
},
|
||||
{
|
||||
"step_id": "step_03_inline_document_choice_with_org_keeps_only_period_gap",
|
||||
"title": "Document lane plus organization in one follow-up leaves only the period gap",
|
||||
"question": "по документам по ООО Альтернатива Плюс",
|
||||
"allowed_reply_types": ["clarification_required", "partial_coverage"],
|
||||
"required_answer_patterns_all": [
|
||||
"(?i)документ|счет|сч[её]т[- ]?фактур|накладн|акт",
|
||||
"(?i)период"
|
||||
],
|
||||
"criticality": "critical",
|
||||
"semantic_tags": ["document_lane_after_clarification", "inline_organization_clarification"]
|
||||
},
|
||||
{
|
||||
"step_id": "step_04_period_clarification_executes_same_document_loop",
|
||||
"title": "Period clarification executes the same bounded document loop",
|
||||
"question": "за 2020 год",
|
||||
"allowed_reply_types": ["factual", "factual_with_explanation", "partial_coverage"],
|
||||
"required_answer_patterns_all": [
|
||||
"(?i)документ|счет|сч[её]т[- ]?фактур|накладн|акт|строк"
|
||||
],
|
||||
"criticality": "critical",
|
||||
"semantic_tags": ["document_lane_execution", "bounded_retrieval"]
|
||||
},
|
||||
{
|
||||
"step_id": "step_05_all_time_followup_keeps_same_document_loop",
|
||||
"title": "All-time follow-up clears the previous period but keeps the same document lane and organization",
|
||||
"question": "а теперь за все время?",
|
||||
"allowed_reply_types": ["factual", "factual_with_explanation", "partial_coverage"],
|
||||
"required_answer_patterns_all": [
|
||||
"(?i)все время|доступное время|весь период",
|
||||
"(?i)документ|счет|сч[её]т[- ]?фактур|накладн|акт|строк"
|
||||
],
|
||||
"forbidden_answer_patterns": [
|
||||
"(?i)уточните .*организац",
|
||||
"(?i)уточните .*контур",
|
||||
"(?i)за 2020",
|
||||
"(?i)движени|регистр",
|
||||
"(?i)не найден контрагент"
|
||||
],
|
||||
"criticality": "critical",
|
||||
"semantic_tags": ["all_time_followup", "document_lane_continuity", "period_cleared"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -148,11 +148,20 @@ function explicitOrganizationScope(pilot) {
|
|||
const normalized = value.trim();
|
||||
return normalized.length > 0 ? normalized : null;
|
||||
}
|
||||
function hasAllTimeScope(pilot) {
|
||||
return (dryRunHasAxis(pilot, "all_time_scope") ||
|
||||
pilot.reason_codes.includes("mcp_discovery_all_time_scope_signal_detected") ||
|
||||
pilot.dry_run.reason_codes.includes("mcp_discovery_all_time_scope_signal_detected"));
|
||||
}
|
||||
function documentOrMovementScopeRu(pilot) {
|
||||
const entity = firstEntityCandidate(pilot);
|
||||
const period = explicitDateScope(pilot);
|
||||
const entityPart = entity ? ` по контрагенту ${entity}` : "";
|
||||
const periodPart = period ? ` за ${period}` : " в проверенном окне";
|
||||
const periodPart = period
|
||||
? ` за ${period}`
|
||||
: hasAllTimeScope(pilot)
|
||||
? " за все доступное время"
|
||||
: " в проверенном окне";
|
||||
return `${entityPart}${periodPart}`;
|
||||
}
|
||||
function isMovementLaneClarification(pilot) {
|
||||
|
|
|
|||
|
|
@ -200,11 +200,23 @@ function explicitOrganizationScope(pilot: AssistantMcpDiscoveryPilotExecutionCon
|
|||
return normalized.length > 0 ? normalized : null;
|
||||
}
|
||||
|
||||
function hasAllTimeScope(pilot: AssistantMcpDiscoveryPilotExecutionContract): boolean {
|
||||
return (
|
||||
dryRunHasAxis(pilot, "all_time_scope") ||
|
||||
pilot.reason_codes.includes("mcp_discovery_all_time_scope_signal_detected") ||
|
||||
pilot.dry_run.reason_codes.includes("mcp_discovery_all_time_scope_signal_detected")
|
||||
);
|
||||
}
|
||||
|
||||
function documentOrMovementScopeRu(pilot: AssistantMcpDiscoveryPilotExecutionContract): string {
|
||||
const entity = firstEntityCandidate(pilot);
|
||||
const period = explicitDateScope(pilot);
|
||||
const entityPart = entity ? ` по контрагенту ${entity}` : "";
|
||||
const periodPart = period ? ` за ${period}` : " в проверенном окне";
|
||||
const periodPart = period
|
||||
? ` за ${period}`
|
||||
: hasAllTimeScope(pilot)
|
||||
? " за все доступное время"
|
||||
: " в проверенном окне";
|
||||
return `${entityPart}${periodPart}`;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -170,6 +170,51 @@ describe("assistant MCP discovery answer adapter", () => {
|
|||
expect(draft.must_not_claim).toContain("Do not present the confirmed movement rows as a complete movement universe.");
|
||||
});
|
||||
|
||||
it("renders metadata-scoped movement all-time follow-up as an all-time bounded answer", async () => {
|
||||
const planner = planAssistantMcpDiscovery({
|
||||
dataNeedGraph: {
|
||||
schema_version: "assistant_data_need_graph_v1",
|
||||
policy_owner: "assistantMcpDiscoveryDataNeedGraph",
|
||||
subject_candidates: [],
|
||||
business_fact_family: "movement_evidence",
|
||||
action_family: "list_movements",
|
||||
aggregation_need: null,
|
||||
time_scope_need: "all_time_scope",
|
||||
comparison_need: null,
|
||||
ranking_need: null,
|
||||
proof_expectation: "coverage_checked_fact",
|
||||
clarification_gaps: [],
|
||||
decomposition_candidates: ["collect_scoped_movements", "probe_coverage"],
|
||||
forbidden_overclaim_flags: ["no_raw_model_claims", "no_unchecked_fact_totals"],
|
||||
reason_codes: ["data_need_graph_built", "data_need_graph_all_time_scope_hint"]
|
||||
},
|
||||
turnMeaning: {
|
||||
asked_domain_family: "movements",
|
||||
asked_action_family: "list_movements",
|
||||
explicit_entity_candidates: [],
|
||||
explicit_organization_scope: "ООО Альтернатива Плюс",
|
||||
unsupported_but_understood_family: "movement_evidence"
|
||||
}
|
||||
});
|
||||
const pilot = await executeAssistantMcpDiscoveryPilot(
|
||||
planner,
|
||||
buildCustomQueryDeps({
|
||||
fetched_rows: 100,
|
||||
matched_rows: 0,
|
||||
rows: [],
|
||||
raw_rows: [{ Period: "2020-06-30T00:00:00", Organization: "ООО Альтернатива Плюс", Registrar: "Move1" }]
|
||||
})
|
||||
);
|
||||
|
||||
const draft = buildAssistantMcpDiscoveryAnswerDraft(pilot);
|
||||
|
||||
expect(draft.answer_mode).toBe("bounded_inference_only");
|
||||
expect(draft.headline).toContain("движени");
|
||||
expect(draft.headline).toContain("все доступное время");
|
||||
expect(draft.headline).not.toContain("за 2020");
|
||||
expect(draft.inference_lines.join("\n")).not.toContain("за 2020");
|
||||
});
|
||||
|
||||
it("keeps bounded-only movement answers tied to the resolved entity and checked period", async () => {
|
||||
const planner = planAssistantMcpDiscovery({
|
||||
turnMeaning: {
|
||||
|
|
|
|||
Loading…
Reference in New Issue