fix(rectification): invite another dated event instead of saying the pool is closed (BUG-689)
Independent Staging Quality Gate / validate (push) Failing after 10m16s
Independent Staging Quality Gate / publish (push) Skipped

When the seven collect lines are closed, the range card still appears, but the copy asks for one more exact-day event of any kind instead of saying the questions are finished. A new dated event after delivery stales the snapshot so the session does not stay delivered.
This commit is contained in:
jesse-ux
2026-09-14 22:56:01 +08:00
parent 62803c5d01
commit a266b6b727
16 changed files with 547 additions and 23 deletions
+6
View File
@@ -3390,6 +3390,12 @@ input:not([type="radio"]):not([type="checkbox"]):not([class^="ant-"]):not([class
.rectification-range-delivery__tie-break:disabled {
cursor: default;
}
.rectification-range-delivery__invite {
margin: 0;
color: var(--color-ink);
font-size: var(--type-body-md);
line-height: 1.65;
}
.rectification-range-delivery__boundary {
margin: 0;
color: var(--color-ink-secondary);
@@ -4,7 +4,9 @@ import type { RectificationCandidateResult } from "@/lib/rectification-candidate
import {
RECTIFICATION_USER_COPY,
REPRESENTATIVE_MINUTE_DISCLAIMER,
rangeDeliveryCaptionWithoutClosedInvite,
rangeDeliveryEventCopy,
rangeDeliveryShowsOpenCollectInvite,
} from "@/lib/rectification-agentic/user-copy";
import type { RangeDeliveryProjection } from "@/lib/rectification-agentic/v9/divergence-panel";
import { RectificationVerificationReport } from "@/components/rectification-verification-report";
@@ -40,14 +42,28 @@ export function RectificationRangeDelivery({
const markdown = delivery?.verification_markdown
?? result.verificationReportMarkdown;
const sharedTraits = delivery?.shared_traits ?? [];
const showOpenCollectInvite = rangeDeliveryShowsOpenCollectInvite({
hint: delivery?.narrow_hint,
columns,
});
const caption = showOpenCollectInvite || delivery?.narrow_hint?.includes(
RECTIFICATION_USER_COPY.rangeDeliveryCollectClosed,
)
? rangeDeliveryCaptionWithoutClosedInvite(delivery?.narrow_hint)
: delivery?.narrow_hint ?? null;
return (
<section className="rectification-candidates rectification-range-delivery" aria-label="生时校正区间">
<div className="rectification-candidates-heading">
<strong>{title}</strong>
</div>
{delivery?.narrow_hint ? (
<p className="rectification-range-delivery__narrow">{delivery.narrow_hint}</p>
{caption ? (
<p className="rectification-range-delivery__narrow">{caption}</p>
) : null}
{showOpenCollectInvite ? (
<p className="rectification-range-delivery__invite">
{RECTIFICATION_USER_COPY.rangeDeliveryCollectClosed}
</p>
) : null}
{delivery?.tie_break_available && onTieBreak && !readonly ? (
<button
@@ -342,9 +342,11 @@ export function decideRectification(input: DecideRectificationInput): Rectificat
if (input.snapshotCurrent === false) {
if (probe && !userStopped && input.trainingGateOpen !== false) {
return discriminateOrExhaust(input, separation, holdout, range, probe, rangeDeliveryCapability, stopReason);
return discriminateOrExhaust(input, separation, holdout, range, probe, rangeDeliveryCapability);
}
return collect(separation, holdout, range, probe, capability, stopReason);
// New dated evidence makes the snapshot stale. Do not carry exhaustion
// stop reasons into collect: those would keep the UI in the delivered gap.
return collect(separation, holdout, range, probe, capability);
}
if (
stopClass?.kind === "exhausted"
@@ -112,6 +112,25 @@ export const USER_COLLECT_QUESTION_RETRY: Readonly<Record<string, string>> = {
health_pressure: "身体或压力这边再问一次:哪年生病、受伤,或特别难熬?",
};
/** Exact-day examples asked first after the seven targeted-collect lines close. */
export const RANGE_DELIVERY_OPEN_COLLECT_DAY_EXAMPLES = [
"登记结婚那天",
"入职第一天",
"手术那天",
"孩子出生那天",
"拿到录取通知那天",
] as const;
/** Year-month examples outside the seven targeted-collect lines. */
export const RANGE_DELIVERY_OPEN_COLLECT_EXAMPLES = [
"换专业",
"出国",
"打官司",
"创业",
"重病",
"亲人离世",
] as const;
export const RECTIFICATION_USER_COPY = {
genericCollectQuestion: GENERIC_COLLECT_QUESTION,
collectQuestionByDomain: USER_COLLECT_QUESTION,
@@ -149,10 +168,39 @@ export const RECTIFICATION_USER_COPY = {
rangeDeliveryTieBreakEntry: "再答两道参考题微调排序",
rangeDeliveryTieBreakAck: "只微调排序,不改目前范围。",
rangeDeliveryTieBreakUsed: "这两分钟按现有信息分不开,参考题已经用过。",
rangeDeliveryCollectClosed: "能问的都问完了",
rangeDeliveryCollectClosed: `这两分钟按现有信息分不开。你要是还记得确切哪一天的事,不限领域,说出来我接着算——${RANGE_DELIVERY_OPEN_COLLECT_DAY_EXAMPLES.join("、")}都成。记不得哪一天的,有年月也行,比如${RANGE_DELIVERY_OPEN_COLLECT_EXAMPLES.join("、")}`,
verificationReportSummary: "查看验证报告",
} as const;
/** Top-two relative-likelihood gap, in percentage points, that counts as a tie on the range card. */
export const RANGE_DELIVERY_TIE_PERCENT = 3;
export function rangeDeliveryTopTwoTied(
columns: readonly { probability_percent: number }[],
): boolean {
if (columns.length < 2) return false;
return Math.abs(columns[0].probability_percent - columns[1].probability_percent)
<= RANGE_DELIVERY_TIE_PERCENT;
}
export function rangeDeliveryCaptionWithoutClosedInvite(
hint: string | null | undefined,
): string | null {
if (!hint) return null;
const invite = RECTIFICATION_USER_COPY.rangeDeliveryCollectClosed;
if (!hint.includes(invite)) return hint;
const stripped = hint.replaceAll(invite, "").replace(/[]\s*$/u, "").trim();
return stripped.length > 0 ? stripped : null;
}
export function rangeDeliveryShowsOpenCollectInvite(input: {
hint: string | null | undefined;
columns: readonly { probability_percent: number }[];
}): boolean {
const invite = RECTIFICATION_USER_COPY.rangeDeliveryCollectClosed;
return Boolean(input.hint?.includes(invite) && rangeDeliveryTopTwoTied(input.columns));
}
export const RANGE_DELIVERY_DOMAIN_LABEL: Readonly<Record<string, string>> = {
education: "学业",
career: "事业",