fix(rectification): reject pre-birth scoring evidence
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
||||
} from "../../../lib/conversational-rectification/errors.ts";
|
||||
import {
|
||||
createConversationalRectificationService,
|
||||
evidencePredatesBirthDate,
|
||||
type ConversationalRectificationPacketBuildInput,
|
||||
type ConversationalRectificationService,
|
||||
} from "../../../lib/conversational-rectification/orchestrator.ts";
|
||||
@@ -281,10 +282,14 @@ function currentRange(input: ConversationalRectificationPacketBuildInput) {
|
||||
return start && end ? { startTime: start, endTime: end } : declaredRange(input.declaredBirthInput);
|
||||
}
|
||||
|
||||
function scoreableLifeEvents(evidence: readonly LifeEventEvidence[]): LifeEvent[] {
|
||||
function scoreableLifeEvents(
|
||||
evidence: readonly LifeEventEvidence[],
|
||||
birthDate: string,
|
||||
): LifeEvent[] {
|
||||
return evidence.flatMap((item) => {
|
||||
if (item.scoreable !== true || !item.dateValue
|
||||
|| !(["day", "month", "year"] as const).includes(item.datePrecision as "day" | "month" | "year")) {
|
||||
|| !(["day", "month", "year"] as const).includes(item.datePrecision as "day" | "month" | "year")
|
||||
|| evidencePredatesBirthDate(item, birthDate)) {
|
||||
return [];
|
||||
}
|
||||
if (item.domain === "family" || item.domain === "other") return [];
|
||||
@@ -408,7 +413,10 @@ export async function buildProductionConversationalRectificationPacket(
|
||||
throw new ConversationalRectificationError("profile_incomplete");
|
||||
}
|
||||
const baseRange = currentRange(input);
|
||||
const events = scoreableLifeEvents(input.evidence as readonly LifeEventEvidence[]);
|
||||
const events = scoreableLifeEvents(
|
||||
input.evidence as readonly LifeEventEvidence[],
|
||||
input.declaredBirthInput.birthDate,
|
||||
);
|
||||
const eventScore: CandidateResult | null = events.length >= 3
|
||||
? await engine.scoreEvents({
|
||||
birthDate: input.declaredBirthInput.birthDate,
|
||||
|
||||
@@ -85,6 +85,31 @@ const transitionValidatorVersion = "conversational-rectification-orchestrator-v1
|
||||
const explicitDirectionChangePattern = /(?:都不符合|都不是|不符合|换(?:个|一)?(?:方向|领域)|其他方向|别的方向|不想(?:谈|说|回答)|拒绝回答)/;
|
||||
const genericUncertaintyPattern = /(?:不知道|不确定)/;
|
||||
|
||||
export function evidencePredatesBirthDate(
|
||||
evidence: Pick<LifeEventEvidence, "dateValue" | "datePrecision">,
|
||||
birthDate: string,
|
||||
): boolean {
|
||||
if (!evidence.dateValue) return false;
|
||||
const boundary = evidence.datePrecision === "year"
|
||||
? birthDate.slice(0, 4)
|
||||
: evidence.datePrecision === "month"
|
||||
? birthDate.slice(0, 7)
|
||||
: evidence.datePrecision === "day"
|
||||
? birthDate
|
||||
: null;
|
||||
return boundary !== null && evidence.dateValue < boundary;
|
||||
}
|
||||
|
||||
function evidenceForDeclaredBirthDate(
|
||||
evidence: readonly LifeEventEvidence[],
|
||||
birthDate: string,
|
||||
): readonly LifeEventEvidence[] {
|
||||
return evidence.map((item) => item.scoreable === true
|
||||
&& evidencePredatesBirthDate(item, birthDate)
|
||||
? { ...item, extractionStatus: "needs_clarification" as const, scoreable: false }
|
||||
: item);
|
||||
}
|
||||
|
||||
function safeFailure(error: unknown): ConversationalRectificationError {
|
||||
return error instanceof ConversationalRectificationError
|
||||
? error
|
||||
@@ -552,7 +577,10 @@ export function createConversationalRectificationService(
|
||||
if (receipt) return receipt;
|
||||
const current = await load(userId, command.caseId);
|
||||
requireMutable(current);
|
||||
const evidence = extractedEvidence(command);
|
||||
const evidence = evidenceForDeclaredBirthDate(
|
||||
extractedEvidence(command),
|
||||
current.declaredBirthInput.birthDate,
|
||||
);
|
||||
|
||||
if (current.turnVersion === command.turnVersion + 1) {
|
||||
try {
|
||||
@@ -606,7 +634,9 @@ export function createConversationalRectificationService(
|
||||
|
||||
try {
|
||||
const allScoreable = [...current.eventEvidence, ...evidence]
|
||||
.filter((item) => item.scoreable === true && item.extractionStatus !== "needs_clarification");
|
||||
.filter((item) => item.scoreable === true
|
||||
&& item.extractionStatus !== "needs_clarification"
|
||||
&& !evidencePredatesBirthDate(item, current.declaredBirthInput.birthDate));
|
||||
const computed = await ports.buildTechnicalPacket({
|
||||
userId,
|
||||
caseId: command.caseId,
|
||||
|
||||
Reference in New Issue
Block a user