Этап 4 / Волна 18 закрытие блокеров по времени, доменной полярности и допуску доказательной базы
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -10,6 +10,7 @@ import * as investigationState_1 from "./investigationState";
|
||||
import * as retrievalResultNormalizer_1 from "./retrievalResultNormalizer";
|
||||
import * as questionTypeResolver_1 from "./questionTypeResolver";
|
||||
import * as companyAnchorResolver_1 from "./companyAnchorResolver";
|
||||
import * as assistantRuntimeGuards_1 from "./assistantRuntimeGuards";
|
||||
function retrievalSummaryForRoute(route) {
|
||||
if (route === "store_canonical")
|
||||
return "Canonical accounting data path selected.";
|
||||
@@ -859,6 +860,43 @@ function extractFollowupAccountAnchorsLoose(text) {
|
||||
}
|
||||
return Array.from(new Set(anchors));
|
||||
}
|
||||
function accountPrefixToken(value) {
|
||||
const token = String(value ?? "").trim();
|
||||
const match = token.match(/^(\d{2})/);
|
||||
return match ? match[1] : null;
|
||||
}
|
||||
function hasCrossScopeConflictWithState(userMessage, state) {
|
||||
const explicitPeriod = extractNormalizedPeriodLiteral(userMessage);
|
||||
const statePeriod = compactWhitespace(state.focus.period ?? "");
|
||||
if (explicitPeriod && statePeriod && explicitPeriod !== statePeriod) {
|
||||
return true;
|
||||
}
|
||||
const inferredDomain = inferP0DomainFromMessage(userMessage);
|
||||
const stateDomain = compactWhitespace(state.followup_context?.active_domain ?? state.focus.domain ?? "");
|
||||
if (inferredDomain && stateDomain && inferredDomain !== stateDomain) {
|
||||
return true;
|
||||
}
|
||||
const explicitAccounts = extractAccountTokens(userMessage);
|
||||
const fallbackAccounts = explicitAccounts.length > 0 ? explicitAccounts : extractFollowupAccountAnchorsLoose(userMessage);
|
||||
const knownAccounts = Array.isArray(state.focus.primary_accounts) ? state.focus.primary_accounts : [];
|
||||
if (fallbackAccounts.length > 0 && knownAccounts.length > 0) {
|
||||
const knownPrefixes = new Set(knownAccounts.map((item) => accountPrefixToken(item)).filter(Boolean));
|
||||
const newPrefixes = new Set(fallbackAccounts.map((item) => accountPrefixToken(item)).filter(Boolean));
|
||||
if (newPrefixes.size > 0 && knownPrefixes.size > 0) {
|
||||
let intersects = false;
|
||||
for (const prefix of newPrefixes) {
|
||||
if (knownPrefixes.has(prefix)) {
|
||||
intersects = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!intersects) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function inferP0DomainFromMessage(text) {
|
||||
const lower = String(text ?? "").toLowerCase();
|
||||
const accountTokens = extractAccountTokens(lower);
|
||||
@@ -971,9 +1009,11 @@ function buildFollowupStateBinding(input) {
|
||||
Boolean(problemState) &&
|
||||
((problemState?.active_problem_units.length ?? 0) > 0 || (problemState?.focus_problem_types.length ?? 0) > 0);
|
||||
const strongNewAnchorDetected = hasStrongFollowupAnchors(userMessage, input.investigationState);
|
||||
const scopeConflictDetected = hasCrossScopeConflictWithState(userMessage, input.investigationState);
|
||||
const periodRefinementFollowup = hasPeriodLiteral(userMessage) && problemContinuityAvailable;
|
||||
const shouldBind = !smallTalkSignal &&
|
||||
!strongNewAnchorDetected &&
|
||||
!scopeConflictDetected &&
|
||||
(followupMarker || referentialPointer || periodRefinementFollowup || (!strongSignal && shortPrompt));
|
||||
if (!shouldBind) {
|
||||
return {
|
||||
@@ -1078,7 +1118,10 @@ function buildFollowupStateBinding(input) {
|
||||
problem_continuity_available: problemContinuityAvailable,
|
||||
problem_continuity_applied: problemContinuityApplied,
|
||||
problem_continuity_skipped_reason: problemContinuityApplied ? null : problemContinuitySkippedReason,
|
||||
strong_new_anchor_detected: strongNewAnchorDetected
|
||||
strong_new_anchor_detected: strongNewAnchorDetected,
|
||||
scope_isolation_applied: true,
|
||||
scope_carryover_allowed: !scopeConflictDetected,
|
||||
scope_reset_reason: scopeConflictDetected ? "cross_scope_conflict" : null
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1147,11 +1190,30 @@ export class AssistantService {
|
||||
useMock: Boolean(payload.useMock)
|
||||
};
|
||||
const normalized = await this.normalizerService.normalize(normalizePayload);
|
||||
const companyAnchors = (0, companyAnchorResolver_1.resolveCompanyAnchors)(userMessage);
|
||||
const inferredDomainByMessage = inferP0DomainFromMessage(userMessage);
|
||||
const focusDomainForGuards = inferredDomainByMessage === "settlements_60_62" ||
|
||||
inferredDomainByMessage === "vat_document_register_book" ||
|
||||
inferredDomainByMessage === "month_close_costs_20_44"
|
||||
? inferredDomainByMessage
|
||||
: null;
|
||||
const temporalGuard = (0, assistantRuntimeGuards_1.resolveTemporalGuard)({
|
||||
userMessage,
|
||||
normalized: normalized.normalized,
|
||||
companyAnchors
|
||||
});
|
||||
const domainPolarityGuardInitial = (0, assistantRuntimeGuards_1.resolveDomainPolarityGuard)({
|
||||
userMessage,
|
||||
companyAnchors,
|
||||
focusDomainHint: focusDomainForGuards
|
||||
});
|
||||
const requirementExtraction = extractRequirements(normalized.route_hint_summary, normalized.normalized, userMessage);
|
||||
const executionPlan = toExecutionPlan(normalized.route_hint_summary, normalized.normalized, userMessage, requirementExtraction.byFragment);
|
||||
let executionPlan = toExecutionPlan(normalized.route_hint_summary, normalized.normalized, userMessage, requirementExtraction.byFragment);
|
||||
executionPlan = (0, assistantRuntimeGuards_1.applyTemporalHintToExecutionPlan)(executionPlan, temporalGuard);
|
||||
executionPlan = (0, assistantRuntimeGuards_1.applyPolarityHintToExecutionPlan)(executionPlan, domainPolarityGuardInitial);
|
||||
const retrievalCalls = [];
|
||||
const retrievalResultsRaw = [];
|
||||
const retrievalResults = [];
|
||||
let retrievalResults = [];
|
||||
for (const planItem of executionPlan) {
|
||||
if (!planItem.should_execute) {
|
||||
retrievalCalls.push({
|
||||
@@ -1210,13 +1272,32 @@ export class AssistantService {
|
||||
retrievalResults.push((0, retrievalResultNormalizer_1.normalizeRetrievalResult)(planItem.fragment_id, planItem.requirement_ids, planItem.route, rawError));
|
||||
}
|
||||
}
|
||||
const polarityGuardResult = (0, assistantRuntimeGuards_1.applyDomainPolarityGuardToRetrievalResults)({
|
||||
retrievalResults,
|
||||
guard: domainPolarityGuardInitial
|
||||
});
|
||||
retrievalResults = polarityGuardResult.retrievalResults;
|
||||
const evidenceGateResult = (0, assistantRuntimeGuards_1.applyEvidenceAdmissibilityGate)({
|
||||
retrievalResults,
|
||||
temporal: temporalGuard,
|
||||
focusDomainHint: focusDomainForGuards,
|
||||
polarity: polarityGuardResult.audit.polarity,
|
||||
companyAnchors,
|
||||
userMessage
|
||||
});
|
||||
retrievalResults = evidenceGateResult.retrievalResults;
|
||||
const coverageEvaluation = evaluateCoverage(requirementExtraction.requirements, retrievalResults);
|
||||
const groundingCheck = checkGrounding(userMessage, coverageEvaluation.requirements, coverageEvaluation.coverage, retrievalResults);
|
||||
const groundingCheckBase = checkGrounding(userMessage, coverageEvaluation.requirements, coverageEvaluation.coverage, retrievalResults);
|
||||
const groundedAnswerEligibilityGuard = (0, assistantRuntimeGuards_1.evaluateGroundedAnswerEligibility)({
|
||||
temporal: temporalGuard,
|
||||
polarity: polarityGuardResult.audit,
|
||||
evidence: evidenceGateResult.audit
|
||||
});
|
||||
const groundingCheck = (0, assistantRuntimeGuards_1.applyEligibilityToGroundingCheck)(groundingCheckBase, groundedAnswerEligibilityGuard);
|
||||
const focusDomainHint = followupBinding.usage?.applied
|
||||
? session.investigation_state?.followup_context?.active_domain ?? session.investigation_state?.focus.domain ?? null
|
||||
: null;
|
||||
const questionTypeClass = (0, questionTypeResolver_1.resolveQuestionType)(userMessage);
|
||||
const companyAnchors = (0, companyAnchorResolver_1.resolveCompanyAnchors)(userMessage);
|
||||
const hasPeriodInCompanyAnchors = (Array.isArray(companyAnchors?.dates) && companyAnchors.dates.some((item) => String(item ?? "").trim().length > 0)) ||
|
||||
(Array.isArray(companyAnchors?.periods) && companyAnchors.periods.some((item) => String(item ?? "").trim().length > 0));
|
||||
const normalizationPeriodExplicit = hasExplicitPeriodAnchorFromNormalized(normalized.normalized) || hasPeriodInCompanyAnchors;
|
||||
@@ -1260,7 +1341,8 @@ export class AssistantService {
|
||||
requirements: coverageEvaluation.requirements,
|
||||
coverageReport: coverageEvaluation.coverage,
|
||||
retrievalResults,
|
||||
replyType: composition.reply_type
|
||||
replyType: composition.reply_type,
|
||||
followupApplied: Boolean(followupBinding.usage?.applied)
|
||||
})
|
||||
: null;
|
||||
if (config_1.FEATURE_ASSISTANT_INVESTIGATION_STATE_V1 && investigationStateSnapshot) {
|
||||
@@ -1288,6 +1370,15 @@ export class AssistantService {
|
||||
dropped_intent_segments: extractDiscardedIntentSegments(normalized.normalized),
|
||||
question_type_class: questionTypeClass,
|
||||
company_anchors: companyAnchors,
|
||||
raw_time_anchor: temporalGuard.raw_time_anchor,
|
||||
resolved_time_anchor: temporalGuard.resolved_time_anchor,
|
||||
temporal_resolution_source: temporalGuard.temporal_resolution_source,
|
||||
temporal_guard_applied: temporalGuard.temporal_guard_applied,
|
||||
temporal_guard_outcome: temporalGuard.temporal_guard_outcome,
|
||||
temporal_guard: temporalGuard,
|
||||
domain_polarity_guard: polarityGuardResult.audit,
|
||||
evidence_admissibility_gate: evidenceGateResult.audit,
|
||||
grounded_answer_eligibility_guard: groundedAnswerEligibilityGuard,
|
||||
...(followupBinding.usage ? { followup_state_usage: followupBinding.usage } : {}),
|
||||
problem_centric_answer_applied: composition.problem_centric_answer_applied ?? false,
|
||||
problem_units_used_count: composition.problem_units_used_count ?? 0,
|
||||
@@ -1353,6 +1444,15 @@ export class AssistantService {
|
||||
dropped_intent_segments: extractDiscardedIntentSegments(normalized.normalized),
|
||||
question_type_class: questionTypeClass,
|
||||
company_anchors: companyAnchors,
|
||||
raw_time_anchor: temporalGuard.raw_time_anchor,
|
||||
resolved_time_anchor: temporalGuard.resolved_time_anchor,
|
||||
temporal_resolution_source: temporalGuard.temporal_resolution_source,
|
||||
temporal_guard_applied: temporalGuard.temporal_guard_applied,
|
||||
temporal_guard_outcome: temporalGuard.temporal_guard_outcome,
|
||||
temporal_guard: temporalGuard,
|
||||
domain_polarity_guard: polarityGuardResult.audit,
|
||||
evidence_admissibility_gate: evidenceGateResult.audit,
|
||||
grounded_answer_eligibility_guard: groundedAnswerEligibilityGuard,
|
||||
...(followupBinding.usage ? { followup_state_usage: followupBinding.usage } : {}),
|
||||
problem_centric_answer_applied: composition.problem_centric_answer_applied ?? false,
|
||||
problem_units_used_count: composition.problem_units_used_count ?? 0,
|
||||
|
||||
@@ -7,6 +7,7 @@ import type { RouteHintSummary } from "../types/normalizer";
|
||||
import type {
|
||||
InvestigationLastAnswerMode,
|
||||
InvestigationNarrowingStatus,
|
||||
InvestigationScopeOrigin,
|
||||
InvestigationState
|
||||
} from "../types/stage1Contracts";
|
||||
import {
|
||||
@@ -39,6 +40,7 @@ interface UpdateInvestigationStateInput {
|
||||
coverageReport: RequirementCoverageReport;
|
||||
retrievalResults: UnifiedRetrievalResult[];
|
||||
replyType: InvestigationLastAnswerMode;
|
||||
followupApplied?: boolean;
|
||||
}
|
||||
|
||||
function uniqueStrings(values: string[]): string[] {
|
||||
@@ -61,6 +63,83 @@ function detectPeriod(text: string): string | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
function detectExplicitDomainHint(text: string): string | null {
|
||||
const messageCorpus = String(text ?? "").toLowerCase();
|
||||
const accounts = detectAccounts(text);
|
||||
const hasSettlementSignal =
|
||||
accounts.some((item) => isSettlementAccount(item)) ||
|
||||
/(?:60(?:\.\d{2})?|62(?:\.\d{2})?|оплат|расч[её]т|зач[её]т|аванс|долг|поставщ|покупат|settlement|payment|supplier|customer)/i.test(
|
||||
messageCorpus
|
||||
);
|
||||
if (hasSettlementSignal) {
|
||||
return "settlements_60_62";
|
||||
}
|
||||
const hasVatSignal =
|
||||
accounts.some((item) => isVatAccount(item)) ||
|
||||
/(?:ндс|сч[её]т[\s-]?фактур|книг[аи]|vat|invoice|book|register)/i.test(messageCorpus);
|
||||
if (hasVatSignal) {
|
||||
return "vat_document_register_book";
|
||||
}
|
||||
const hasCloseSignal =
|
||||
accounts.some((item) => isCloseCostsAccount(item)) ||
|
||||
/(?:закрыти|месяц|затрат|распредел|списан|period\s*close|month\s*close|allocation|residual|cost|рбп)/i.test(messageCorpus);
|
||||
if (hasCloseSignal) {
|
||||
return "month_close_costs_20_44";
|
||||
}
|
||||
const hasFixedAssetSignal =
|
||||
accounts.some((item) => isFixedAssetAccount(item)) ||
|
||||
/(?:амортиз|основн(ые|ых|ым)?\s+средств|(?:^|[^a-zа-яё])ос(?:$|[^a-zа-яё])|объект[а-яё]*\s+ос|fixed\s*asset|depreciat)/i.test(
|
||||
messageCorpus
|
||||
);
|
||||
if (hasFixedAssetSignal) {
|
||||
return "fixed_asset_amortization";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function buildQuestionScopeId(input: {
|
||||
domain: string | null;
|
||||
period: string | null;
|
||||
accounts: string[];
|
||||
subject: string;
|
||||
}): string | null {
|
||||
const domainPart = String(input.domain ?? "").trim();
|
||||
const periodPart = String(input.period ?? "").trim();
|
||||
const accountPart = capStrings(input.accounts.map((item) => String(item ?? "").trim()).filter(Boolean), 4).join(",");
|
||||
const subjectPart = String(input.subject ?? "").trim().slice(0, 96).toLowerCase();
|
||||
const parts = [
|
||||
domainPart ? `d:${domainPart}` : "",
|
||||
periodPart ? `p:${periodPart}` : "",
|
||||
accountPart ? `a:${accountPart}` : "",
|
||||
subjectPart ? `s:${subjectPart}` : ""
|
||||
].filter(Boolean);
|
||||
if (parts.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return parts.join("|");
|
||||
}
|
||||
|
||||
function deriveScopeOrigin(input: {
|
||||
followupApplied: boolean;
|
||||
userMessage: string;
|
||||
routeSummary: RouteHintSummary | null;
|
||||
}): InvestigationScopeOrigin {
|
||||
if (input.followupApplied) {
|
||||
return "followup_state_carryover";
|
||||
}
|
||||
const hasExplicitPeriod = Boolean(detectPeriod(input.userMessage));
|
||||
const hasExplicitAccounts = detectAccounts(input.userMessage).length > 0;
|
||||
const explicitDomain = detectExplicitDomainHint(input.userMessage);
|
||||
if (hasExplicitPeriod || hasExplicitAccounts || explicitDomain) {
|
||||
return "explicit_from_message";
|
||||
}
|
||||
const routeDomain = deriveDomain(input.routeSummary);
|
||||
if (routeDomain && routeDomain !== "no_route") {
|
||||
return "route_derived";
|
||||
}
|
||||
return "underspecified";
|
||||
}
|
||||
|
||||
function deriveDomain(routeSummary: RouteHintSummary | null): string | null {
|
||||
if (!routeSummary) return null;
|
||||
if (routeSummary.mode === "legacy_v1") {
|
||||
@@ -165,9 +244,12 @@ function inferFollowupActiveDomain(input: {
|
||||
focusAccounts: string[];
|
||||
routeSummary: RouteHintSummary | null;
|
||||
previous: InvestigationStateWithProblemUnits;
|
||||
allowStateCarryover: boolean;
|
||||
}): string | null {
|
||||
const messageCorpus = String(input.userMessage ?? "").toLowerCase();
|
||||
const contextualCorpus = `${messageCorpus} ${input.previous.focus.active_query_subject ?? ""}`.toLowerCase();
|
||||
const contextualCorpus = input.allowStateCarryover
|
||||
? `${messageCorpus} ${input.previous.focus.active_query_subject ?? ""}`.toLowerCase()
|
||||
: messageCorpus;
|
||||
|
||||
const hasFixedAssetLexicalSignal =
|
||||
/(?:амортиз|основн(ые|ых|ым)?\s+средств|(?:^|[^a-zа-яё])ос(?:$|[^a-zа-яё])|объект[а-яё]*\s+ос|fixed\s*asset|depreciat)/i.test(
|
||||
@@ -206,6 +288,7 @@ function inferFollowupActiveDomain(input: {
|
||||
}
|
||||
|
||||
if (
|
||||
input.allowStateCarryover &&
|
||||
/(?:60(?:\.\d{2})?|62(?:\.\d{2})?|оплат|расч[её]т|аванс|долг|settlement|payment)/i.test(contextualCorpus) &&
|
||||
(input.previous.followup_context?.active_domain === "settlements_60_62" ||
|
||||
input.previous.focus.domain === "settlements_60_62")
|
||||
@@ -218,7 +301,11 @@ function inferFollowupActiveDomain(input: {
|
||||
return routeDomain;
|
||||
}
|
||||
|
||||
return input.previous.followup_context?.active_domain ?? input.previous.focus.domain ?? null;
|
||||
if (input.allowStateCarryover) {
|
||||
return input.previous.followup_context?.active_domain ?? input.previous.focus.domain ?? null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function collectUncoveredRequirementIds(coverageReport: RequirementCoverageReport): string[] {
|
||||
@@ -447,6 +534,8 @@ export function createEmptyInvestigationState(
|
||||
turn_index: 0,
|
||||
updated_at: timestamp,
|
||||
question_id: null,
|
||||
question_scope_id: null,
|
||||
scope_origin: null,
|
||||
focus: {
|
||||
domain: null,
|
||||
period: null,
|
||||
@@ -464,11 +553,11 @@ export function createEmptyInvestigationState(
|
||||
|
||||
export function updateInvestigationState(input: UpdateInvestigationStateInput): InvestigationStateWithProblemUnits {
|
||||
const previous = input.previous;
|
||||
const followupApplied = input.followupApplied === true;
|
||||
const focusFromMessage = capStrings(detectAccounts(input.userMessage), INVESTIGATION_MAX_PRIMARY_ACCOUNTS);
|
||||
const mergedFocusAccounts = capStrings(
|
||||
[...focusFromMessage, ...previous.focus.primary_accounts],
|
||||
INVESTIGATION_MAX_PRIMARY_ACCOUNTS
|
||||
);
|
||||
const mergedFocusAccounts = followupApplied
|
||||
? capStrings([...focusFromMessage, ...previous.focus.primary_accounts], INVESTIGATION_MAX_PRIMARY_ACCOUNTS)
|
||||
: capStrings(focusFromMessage, INVESTIGATION_MAX_PRIMARY_ACCOUNTS);
|
||||
const requirementIds = capStrings(
|
||||
input.requirements.map((item) => item.requirement_id),
|
||||
INVESTIGATION_MAX_REQUIREMENT_LINKS
|
||||
@@ -476,16 +565,31 @@ export function updateInvestigationState(input: UpdateInvestigationStateInput):
|
||||
const mainRequirement = input.requirements[0]?.requirement_text ?? input.userMessage;
|
||||
const problemUnitState = updateProblemUnitState(previous, input.retrievalResults);
|
||||
const uncoveredRequirementIds = collectUncoveredRequirementIds(input.coverageReport);
|
||||
const routeDomain = deriveDomain(input.routeSummary);
|
||||
const activeDomain = inferFollowupActiveDomain({
|
||||
userMessage: input.userMessage,
|
||||
focusAccounts: focusFromMessage,
|
||||
routeSummary: input.routeSummary,
|
||||
previous
|
||||
previous,
|
||||
allowStateCarryover: followupApplied
|
||||
});
|
||||
const focusDomain = activeDomain ?? deriveDomain(input.routeSummary) ?? previous.focus.domain;
|
||||
const focusDomain = activeDomain ?? routeDomain ?? (followupApplied ? previous.focus.domain : null);
|
||||
const detectedPeriod = detectPeriod(input.userMessage);
|
||||
const focusPeriod = detectedPeriod ?? (followupApplied ? previous.focus.period : null);
|
||||
const settlementNextActions = settlementFocusActions(activeDomain);
|
||||
const lastProblemUnitId = problemUnitState?.active_problem_units[0] ?? null;
|
||||
const evidenceSummary = collectEvidenceSummary(input.retrievalResults);
|
||||
const scopeOrigin = deriveScopeOrigin({
|
||||
followupApplied,
|
||||
userMessage: input.userMessage,
|
||||
routeSummary: input.routeSummary
|
||||
});
|
||||
const questionScopeId = buildQuestionScopeId({
|
||||
domain: focusDomain,
|
||||
period: focusPeriod,
|
||||
accounts: mergedFocusAccounts,
|
||||
subject: mainRequirement
|
||||
});
|
||||
|
||||
return {
|
||||
schema_version: INVESTIGATION_STATE_SCHEMA_VERSION,
|
||||
@@ -494,9 +598,11 @@ export function updateInvestigationState(input: UpdateInvestigationStateInput):
|
||||
turn_index: previous.turn_index + 1,
|
||||
updated_at: input.timestamp,
|
||||
question_id: input.questionId,
|
||||
question_scope_id: questionScopeId,
|
||||
scope_origin: scopeOrigin,
|
||||
focus: {
|
||||
domain: focusDomain,
|
||||
period: detectPeriod(input.userMessage) ?? previous.focus.period,
|
||||
period: focusPeriod,
|
||||
primary_accounts: mergedFocusAccounts,
|
||||
active_query_subject: mainRequirement.slice(0, 180)
|
||||
},
|
||||
@@ -516,7 +622,9 @@ export function updateInvestigationState(input: UpdateInvestigationStateInput):
|
||||
uncovered_requirement_ids: uncoveredRequirementIds,
|
||||
last_problem_unit_id: lastProblemUnitId,
|
||||
settlement_next_actions: settlementNextActions,
|
||||
evidence_summary: evidenceSummary
|
||||
evidence_summary: evidenceSummary,
|
||||
question_scope_id: questionScopeId,
|
||||
scope_origin: scopeOrigin
|
||||
},
|
||||
query_mode_hint: deriveQueryModeHint(input.routeSummary),
|
||||
...(problemUnitState
|
||||
|
||||
@@ -67,9 +67,66 @@ export interface FollowupStateUsageDebug {
|
||||
problem_continuity_applied?: boolean;
|
||||
problem_continuity_skipped_reason?: string | null;
|
||||
strong_new_anchor_detected?: boolean;
|
||||
scope_isolation_applied?: boolean;
|
||||
scope_carryover_allowed?: boolean;
|
||||
scope_reset_reason?: string | null;
|
||||
};
|
||||
}
|
||||
|
||||
export interface TemporalGuardDebug {
|
||||
raw_time_anchor: string | null;
|
||||
resolved_time_anchor: string | null;
|
||||
temporal_resolution_source: string;
|
||||
temporal_guard_applied: boolean;
|
||||
temporal_guard_outcome: "passed" | "failed_out_of_snapshot_window" | "ambiguous_limited";
|
||||
primary_period_window: {
|
||||
from: string;
|
||||
to: string;
|
||||
granularity: "day" | "month";
|
||||
} | null;
|
||||
reason_codes: string[];
|
||||
}
|
||||
|
||||
export interface DomainPolarityGuardDebug {
|
||||
applied: boolean;
|
||||
polarity: "supplier_payable" | "customer_receivable" | "mixed_or_unresolved" | "not_applicable";
|
||||
outcome: "passed" | "limited_unresolved_polarity" | "blocked_conflict" | "not_applicable";
|
||||
supplier_score: number;
|
||||
customer_score: number;
|
||||
account_scope: string[];
|
||||
rejected_problem_units: number;
|
||||
rejected_evidence: number;
|
||||
critical_contradiction: boolean;
|
||||
reason_codes: string[];
|
||||
}
|
||||
|
||||
export interface EvidenceAdmissibilityGateDebug {
|
||||
candidate_evidence_total: number;
|
||||
admissible_evidence_count: number;
|
||||
rejected_evidence_count: number;
|
||||
rejected_item_count: number;
|
||||
reject_breakdown: Record<
|
||||
"wrong_period" | "wrong_domain" | "wrong_account_scope" | "weak_source_mapping" | "zero_live_match" | "future_dated_or_out_of_window",
|
||||
number
|
||||
>;
|
||||
category_breakdown: {
|
||||
hard_evidence: number;
|
||||
supporting_signal: number;
|
||||
inadmissible_noise: number;
|
||||
};
|
||||
reason_codes: string[];
|
||||
}
|
||||
|
||||
export interface GroundedAnswerEligibilityGuardDebug {
|
||||
eligible: boolean;
|
||||
temporal_passed: boolean;
|
||||
polarity_passed: boolean;
|
||||
admissible_evidence_count: number;
|
||||
critical_contradiction: boolean;
|
||||
outcome: "grounded_allowed" | "limited_or_insufficient_evidence";
|
||||
reason_codes: string[];
|
||||
}
|
||||
|
||||
export interface AssistantMessageRequestPayload {
|
||||
session_id?: string;
|
||||
user_message?: string;
|
||||
@@ -132,6 +189,15 @@ export interface AssistantDebugPayload {
|
||||
retrieval_results: UnifiedRetrievalResult[];
|
||||
answer_grounding_check: AnswerGroundingCheck;
|
||||
dropped_intent_segments: string[];
|
||||
raw_time_anchor?: string | null;
|
||||
resolved_time_anchor?: string | null;
|
||||
temporal_resolution_source?: string;
|
||||
temporal_guard_applied?: boolean;
|
||||
temporal_guard_outcome?: TemporalGuardDebug["temporal_guard_outcome"];
|
||||
temporal_guard?: TemporalGuardDebug;
|
||||
domain_polarity_guard?: DomainPolarityGuardDebug;
|
||||
evidence_admissibility_gate?: EvidenceAdmissibilityGateDebug;
|
||||
grounded_answer_eligibility_guard?: GroundedAnswerEligibilityGuardDebug;
|
||||
followup_state_usage?: FollowupStateUsageDebug;
|
||||
problem_centric_answer_applied?: boolean;
|
||||
problem_units_used_count?: number;
|
||||
|
||||
@@ -10,6 +10,11 @@ export const INVESTIGATION_MAX_REQUIREMENT_LINKS = 8;
|
||||
|
||||
export type InvestigationNarrowingStatus = "unknown" | "not_needed" | "applied" | "needs_clarification" | "broad_guarded";
|
||||
export type InvestigationQueryModeHint = "direct_answer" | "investigation_candidate";
|
||||
export type InvestigationScopeOrigin =
|
||||
| "explicit_from_message"
|
||||
| "followup_state_carryover"
|
||||
| "route_derived"
|
||||
| "underspecified";
|
||||
export type InvestigationLastAnswerMode =
|
||||
| "factual"
|
||||
| "factual_with_explanation"
|
||||
@@ -39,6 +44,8 @@ export interface InvestigationFollowupContext {
|
||||
last_problem_unit_id?: string | null;
|
||||
settlement_next_actions?: string[];
|
||||
evidence_summary?: string[];
|
||||
question_scope_id?: string | null;
|
||||
scope_origin?: InvestigationScopeOrigin | null;
|
||||
}
|
||||
|
||||
export interface InvestigationState {
|
||||
@@ -48,6 +55,8 @@ export interface InvestigationState {
|
||||
turn_index: number;
|
||||
updated_at: string;
|
||||
question_id: string | null;
|
||||
question_scope_id?: string | null;
|
||||
scope_origin?: InvestigationScopeOrigin | null;
|
||||
focus: InvestigationStateFocus;
|
||||
narrowing_status: InvestigationNarrowingStatus;
|
||||
evidence_refs: string[];
|
||||
|
||||
Reference in New Issue
Block a user