Initial import NDC_1C
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { RouteHintSummary } from "../src/types/normalizer";
|
||||
import type { UnifiedRetrievalResult } from "../src/types/assistant";
|
||||
import {
|
||||
ACCOUNTANT_SCORING_RUBRIC_V01,
|
||||
INVESTIGATION_MAX_EVIDENCE_REFS,
|
||||
INVESTIGATION_MAX_UNCERTAINTIES
|
||||
} from "../src/types/stage1Contracts";
|
||||
import { createEmptyInvestigationState, updateInvestigationState } from "../src/services/investigationState";
|
||||
|
||||
function buildRouteSummary(): RouteHintSummary {
|
||||
return {
|
||||
mode: "deterministic_v2",
|
||||
message_in_scope: true,
|
||||
scope_confidence: "high",
|
||||
planner: {
|
||||
total_fragments: 1,
|
||||
in_scope_fragments: 1,
|
||||
out_of_scope_fragments: 0,
|
||||
discarded_fragments: 0,
|
||||
contains_multiple_tasks: false
|
||||
},
|
||||
decisions: [
|
||||
{
|
||||
fragment_id: "F1",
|
||||
domain_relevance: "in_scope",
|
||||
business_scope: "company_specific_accounting",
|
||||
candidate_labels: ["anomaly_probe"],
|
||||
decision_flags: {
|
||||
has_multi_entity_scope: false,
|
||||
asks_for_chain_explanation: false,
|
||||
asks_for_ranking_or_top: false,
|
||||
asks_for_period_summary: false,
|
||||
asks_for_rule_check: true,
|
||||
asks_for_anomaly_scan: true,
|
||||
asks_for_exact_object_trace: false,
|
||||
asks_for_evidence: true,
|
||||
mentions_period_close_context: false
|
||||
},
|
||||
route: "store_feature_risk",
|
||||
reason: "test-route"
|
||||
}
|
||||
],
|
||||
fallback: {
|
||||
type: "none",
|
||||
message: null
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function buildRetrievalResult(evidenceCount: number): UnifiedRetrievalResult {
|
||||
return {
|
||||
fragment_id: "F1",
|
||||
requirement_ids: ["R1"],
|
||||
route: "store_feature_risk",
|
||||
status: "ok",
|
||||
result_type: "list",
|
||||
items: [],
|
||||
summary: {},
|
||||
evidence: Array.from({ length: evidenceCount }, (_, index) => ({
|
||||
evidence_id: `ev-${index + 1}`,
|
||||
claim_ref: "requirement:R1",
|
||||
source_type: "retrieval_item",
|
||||
source_ref: {
|
||||
schema_version: "evidence_source_ref_v1",
|
||||
namespace: "snapshot_2020",
|
||||
entity: "document",
|
||||
id: `doc-${index + 1}`,
|
||||
period: "2020-06",
|
||||
canonical_ref: `evidence_source_ref_v1|snapshot_2020|document|doc-${index + 1}|2020-06`
|
||||
},
|
||||
pointer: {
|
||||
fragment_id: "F1",
|
||||
route: "store_feature_risk",
|
||||
source: {
|
||||
namespace: "snapshot_2020",
|
||||
entity: "document",
|
||||
id: `doc-${index + 1}`,
|
||||
period: "2020-06"
|
||||
},
|
||||
locator: {
|
||||
field_path: "risk_score",
|
||||
item_index: index
|
||||
}
|
||||
},
|
||||
evidence_kind: "anomaly_signal",
|
||||
mechanism_note: "Risk signal",
|
||||
confidence: "medium",
|
||||
limitation: null,
|
||||
payload: { risk_score: 2 }
|
||||
})),
|
||||
why_included: [],
|
||||
selection_reason: [],
|
||||
risk_factors: [],
|
||||
business_interpretation: [],
|
||||
confidence: "high",
|
||||
limitations: ["Need period clarification"],
|
||||
errors: []
|
||||
};
|
||||
}
|
||||
|
||||
describe("stage1 contract scaffolding", () => {
|
||||
it("provides rubric v0.1 for accountant-facing metrics", () => {
|
||||
const metricNames = Object.keys(ACCOUNTANT_SCORING_RUBRIC_V01);
|
||||
expect(metricNames).toEqual([
|
||||
"retrieval_differentiation_rate",
|
||||
"generic_explanation_rate",
|
||||
"accountant_actionability_score",
|
||||
"false_confidence_rate",
|
||||
"broad_answer_rate",
|
||||
"mechanism_specificity_score",
|
||||
"followup_context_retention_score"
|
||||
]);
|
||||
for (const metric of metricNames) {
|
||||
const bands = ACCOUNTANT_SCORING_RUBRIC_V01[metric as keyof typeof ACCOUNTANT_SCORING_RUBRIC_V01];
|
||||
expect(bands.some((item) => item.score === 0)).toBe(true);
|
||||
expect(bands.some((item) => item.score === 5)).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it("updates investigation_state with bounded fields", () => {
|
||||
const initial = createEmptyInvestigationState("asst-contract-test", "2026-03-25T10:00:00.000Z");
|
||||
const updated = updateInvestigationState({
|
||||
previous: initial,
|
||||
timestamp: "2026-03-25T10:01:00.000Z",
|
||||
questionId: "msg-1",
|
||||
userMessage: "Prover schet 97 za 2020-06 i podsveti risk.",
|
||||
routeSummary: buildRouteSummary(),
|
||||
requirements: [
|
||||
{
|
||||
requirement_id: "R1",
|
||||
source_fragment_id: "F1",
|
||||
requirement_text: "Проверить счет 97",
|
||||
subject_tokens: ["счет_97"],
|
||||
status: "covered",
|
||||
route: "store_feature_risk"
|
||||
}
|
||||
],
|
||||
coverageReport: {
|
||||
requirements_total: 1,
|
||||
requirements_covered: 1,
|
||||
requirements_uncovered: [],
|
||||
requirements_partially_covered: [],
|
||||
clarification_needed_for: [],
|
||||
out_of_scope_requirements: []
|
||||
},
|
||||
retrievalResults: [buildRetrievalResult(40)],
|
||||
replyType: "factual_with_explanation"
|
||||
});
|
||||
|
||||
expect(updated.turn_index).toBe(1);
|
||||
expect(updated.status).toBe("active");
|
||||
expect(updated.focus.period).toBe("2020-06");
|
||||
expect(updated.focus.primary_accounts).toContain("97");
|
||||
expect(updated.evidence_refs.length).toBeLessThanOrEqual(INVESTIGATION_MAX_EVIDENCE_REFS);
|
||||
expect(updated.open_uncertainties.length).toBeLessThanOrEqual(INVESTIGATION_MAX_UNCERTAINTIES);
|
||||
expect(updated.query_mode_hint).toBe("direct_answer");
|
||||
expect(updated.followup_context?.referenced_requirement_ids).toEqual(["R1"]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user