Files
Jyotisha/frontend/tests/rectification-choice-card.test.ts
Jesse_Chen 078c1cdc0d
Independent Staging Quality Gate / validate (push) Successful in 23m37s
Independent Staging Quality Gate / publish (push) Has been cancelled
fix(rectification): keep collection denials from stalling the interview
A spoken no neither scored nor declined coverage, so relatives never closed and free-text turns left current_question null. Prefer a same-domain yearless scoring card before an unscoreable collect, resolve explicit collect denials as declined, and persist the next followup after an idle agent turn.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-29 22:37:32 +08:00

1521 lines
54 KiB
TypeScript

import assert from "node:assert/strict";
import test from "node:test";
import {
buildChoiceFrame,
choiceCardUserMessage,
HOLDOUT_MESSAGE_PREFIX,
isHoldoutVerificationQuote,
lifePeriodLabel,
preferConcreteChoicePrompt,
mergeChoiceCard,
parseAgentChoiceCopy,
parseRectificationChoiceCard,
serverOwnedChoiceCopy,
} from "../src/lib/rectification-agentic/v9/choice-card.ts";
import { buildMethodFollowupPlan, projectRectificationChoiceCard } from "../src/lib/rectification-agentic/v9/method-followup.ts";
import { choiceCardFromCaseDossier } from "../src/lib/rectification-agentic/v9/interview-state.ts";
import { QUALITY_STYLE_OPTIONS } from "../src/lib/rectification-agentic/v9/probe-question-contract.ts";
import type { DiscriminatingEventProbe } from "../src/lib/rectification-agentic/v9/refinement-packet.ts";
const DYNAMIC_STYLE_OPTIONS = [
{ label: "明确发生且时间吻合", answer_class: "yes" },
{ label: "发生过但程度较弱", answer_class: "weak_yes" },
{ label: "明确没有发生", answer_class: "no" },
{ label: "这段记不清楚", answer_class: "unsure" },
] as const;
const SAMPLE_COPY = {
prompt: "2016 年前后,有没有明显搬家、离乡或长期异地?",
option_a: DYNAMIC_STYLE_OPTIONS[0].label,
option_b: DYNAMIC_STYLE_OPTIONS[1].label,
option_c: DYNAMIC_STYLE_OPTIONS[2].label,
option_d: DYNAMIC_STYLE_OPTIONS[3].label,
options: DYNAMIC_STYLE_OPTIONS.map((option, index) => ({
key: (["A", "B", "C", "D"] as const)[index]!,
label: option.label,
answer_class: option.answer_class,
})),
} as const;
const FOCUS_ID = "abababab-abab-4bab-8bab-abababababab";
const MOVE_PROBE: DiscriminatingEventProbe = {
year: 2016,
year_label: "2016 年前后",
domain: "relocation",
event_family: "搬家、离乡或长期异地",
source: "dasha_activation",
tracks: ["vimshottari", "narayana"],
tracks_agree: true,
unique_minute_claim: false,
user_meaning: "年份锁定 2016 年前后。事件家族:搬家、离乡或长期异地。请写成一句自然语言是/否题。不得改年份。",
role: "distinguish",
information_gain: 0.4,
candidate_ids: ["05:00", "05:20"],
expected_outcomes: [
{ answer_class: "yes", supports: ["05:00"], conflicts: ["05:20"] },
{ answer_class: "no", supports: ["05:20"], conflicts: ["05:00"] },
],
style_options: DYNAMIC_STYLE_OPTIONS,
};
const IDENTITY_PROBE: DiscriminatingEventProbe = {
...MOVE_PROBE,
semantic_key: "relocation.2016",
candidate_split_hash: "relocation.2016:05:00|05:20",
};
function identityCard(schemaOverrides: Record<string, unknown> = {}) {
return projectRectificationChoiceCard({
evidence: [{
status: "confirmed",
domain: "education",
datePrecision: "year",
occurredFrom: "2016-01-01",
occurredTo: null,
}],
eventProbes: [IDENTITY_PROBE],
activeFocus: {
id: FOCUS_ID,
questionId: "persisted-question-id",
intent: "distinguish_candidates",
targetDomain: "relocation",
targetKind: "relocation_change",
expectedAnswerSchema: {
choice: SAMPLE_COPY,
semantic_key: IDENTITY_PROBE.semantic_key,
candidate_split_hash: IDENTITY_PROBE.candidate_split_hash,
...schemaOverrides,
},
},
});
}
test("choice frames ask one biographical event from a server probe, not competing charts", () => {
const frame = buildChoiceFrame(
{
method_id: "d4_home",
ask_theme: "home_change",
domain: "relocation",
user_prompt_hint: "unused",
},
{
observations: [
{ layer: "d9", candidates_differ: true, ask_theme: "relationship_style" },
{ layer: "d10", candidates_differ: true, ask_theme: "career_style" },
{ layer: "d4", candidates_differ: true, ask_theme: "home_change" },
],
evidence: [{
status: "confirmed",
domain: "education",
datePrecision: "year",
occurredFrom: "2016-01-01",
occurredTo: null,
}],
probes: [MOVE_PROBE],
},
);
assert.ok(frame);
assert.equal(frame.period, "2016 年前后");
assert.match(frame.why, /年份锁定/);
assert.match(frame.why, /请写成/);
assert.doesNotMatch(frame.why, /^2016 年前后,有没有明显/);
assert.equal(frame.option_a_hint, DYNAMIC_STYLE_OPTIONS[0].label);
assert.equal(frame.option_b_hint, DYNAMIC_STYLE_OPTIONS[1].label);
assert.doesNotMatch(frame.option_a_hint + frame.option_b_hint, /更像哪一件|可能性/);
assert.doesNotMatch(frame.why, /更像哪一件/);
assert.equal(/外貌|疤痕|胎记/.test(frame.option_a_hint + frame.option_b_hint), false);
assert.equal(frame.scoring, true);
assert.equal(mergeChoiceCard(frame, null), null);
});
test("choice frames keep the engine month lock instead of collapsing to a year", () => {
const frame = buildChoiceFrame(
{
method_id: "d10_career",
ask_theme: "dated_event",
domain: "career",
user_prompt_hint: "unused",
},
{
evidence: [{
status: "confirmed",
domain: "education",
datePrecision: "year",
occurredFrom: "2016-01-01",
occurredTo: null,
}],
probes: [{
...MOVE_PROBE,
year: 2018,
month: 3,
year_label: "2018 年 3 月前后",
domain: "career",
event_family: "入职、升职或职责明显加重",
source: "dasha_boundary",
user_meaning: "时间范围锁定 2018 年 3 月前后;领域锁定 career。",
semantic_key: "career.2018.03.dasha_boundary",
}],
},
);
assert.ok(frame);
assert.equal(frame.period, "2018 年 3 月前后");
assert.match(frame.prompt, /2018 年 3 月前后/);
assert.match(frame.why, /2018 年 3 月前后/);
assert.doesNotMatch(frame.period, /^2018 年前后$/);
});
test("server-owned card names the event family, not a generic 有没有这件事", () => {
const frame = buildChoiceFrame(
{
method_id: "d4_home",
ask_theme: "home_change",
domain: "relocation",
user_prompt_hint: "unused",
},
{ probes: [MOVE_PROBE] },
);
assert.ok(frame);
if (!frame) assert.fail("expected dynamic choice frame");
const copy = serverOwnedChoiceCopy(frame!);
assert.ok(copy);
assert.match(copy.prompt, /搬家、离乡或长期异地/);
assert.doesNotMatch(copy.prompt, /有没有这件事/);
assert.doesNotMatch(copy.prompt, /有没有明显/);
});
test("the visible card uses Agent copy for A/B/C/D, not the server hint", () => {
const frame = buildChoiceFrame({
method_id: "d4_home",
ask_theme: "home_change",
domain: "relocation",
user_prompt_hint: "unused",
}, {
evidence: [{
status: "confirmed",
domain: "education",
datePrecision: "year",
occurredFrom: "2016-01-01",
occurredTo: null,
}],
probes: [MOVE_PROBE],
});
assert.ok(frame);
const card = mergeChoiceCard(frame, SAMPLE_COPY);
assert.equal(card?.prompt, SAMPLE_COPY.prompt);
assert.equal(card?.options[0]?.label, SAMPLE_COPY.option_a);
assert.equal(card?.options[1]?.label, SAMPLE_COPY.option_b);
assert.equal(card?.options[2]?.label, SAMPLE_COPY.option_c);
assert.equal(card?.options[3]?.label, SAMPLE_COPY.option_d);
assert.equal(card?.stop_label, frame.stop_label);
});
test("holdout messages are prefixed and do not count as scoring quotes", () => {
const frame = buildChoiceFrame(
{
method_id: "oos_blind",
ask_theme: "oos_blind",
domain: "family",
user_prompt_hint: "unused",
},
{
scoring: false,
probes: [{
...MOVE_PROBE,
domain: "family",
event_family: "家人结婚、添丁或住院等重要变动",
user_meaning: "盘外核对:只核对家人事件,不计入候选评分。",
}],
},
);
assert.ok(frame);
const card = mergeChoiceCard(frame, {
...SAMPLE_COPY,
prompt: "家人这条线还没用过,有没有一件记得大概年份的变化?",
});
assert.ok(card);
const message = choiceCardUserMessage(card, "A");
assert.match(message, new RegExp(HOLDOUT_MESSAGE_PREFIX));
assert.equal(isHoldoutVerificationQuote(message), true);
assert.equal(isHoldoutVerificationQuote("A. 认真关系进入或结婚"), false);
assert.equal(card.scoring, false);
assert.match(frame.why, /盘外核对/);
});
test("reverse-verify after adopt scores the predicted event and invites 改选 on mismatch", () => {
const frame = buildChoiceFrame(
{
method_id: "reverse_verify",
ask_theme: "career_style",
domain: "career",
user_prompt_hint: "unused",
},
{
probes: [{
year: 2018,
year_label: "2018 年前后",
domain: "career",
event_family: "入职、升职或职责明显加重",
source: "dasha_activation",
tracks: ["vimshottari", "narayana"],
tracks_agree: true,
unique_minute_claim: false,
user_meaning: "按当前采用时间核对 2018 年前后的事业变化;若不吻合可以改选。",
role: "reverse_verify",
style_options: DYNAMIC_STYLE_OPTIONS,
}],
},
);
assert.ok(frame);
assert.equal(frame.period, "2018 年前后");
assert.equal(frame.scoring, true);
assert.match(frame.why, /按当前采用时间核对/);
assert.match(frame.why, /改选/);
assert.doesNotMatch(frame.why, /盘外核对/);
const card = mergeChoiceCard(frame, SAMPLE_COPY);
assert.ok(card);
assert.equal(card.scoring, true);
assert.doesNotMatch(choiceCardUserMessage(card, "A"), new RegExp(HOLDOUT_MESSAGE_PREFIX));
});
test("life period only reuses years from the same domain", () => {
assert.equal(lifePeriodLabel([
{ status: "confirmed", datePrecision: "unknown", occurredFrom: null, occurredTo: null },
]), "那段时间");
assert.equal(lifePeriodLabel([
{ status: "confirmed", domain: "education", datePrecision: "year", occurredFrom: "2016-01-01", occurredTo: null },
{ status: "confirmed", domain: "career", datePrecision: "year", occurredFrom: "2020-06-01", occurredTo: null },
], "education"), "2016 年前后");
assert.equal(lifePeriodLabel([
{ status: "confirmed", domain: "education", datePrecision: "year", occurredFrom: "2016-01-01", occurredTo: null },
], "relocation"), "那段时间");
assert.equal(lifePeriodLabel([
{ status: "confirmed", domain: "career", datePrecision: "month", occurredFrom: "2020-04-01", occurredTo: null },
], "career"), "2020 年 4 月前后");
assert.equal(lifePeriodLabel([
{ status: "confirmed", domain: "relationship", datePrecision: "day", occurredFrom: "2024-08-08", occurredTo: null },
], "relationship"), "2024 年 8 月前后");
});
test("choice frame requires a real non-empty event family", () => {
const missingFamily = { ...MOVE_PROBE, event_family: undefined } as unknown as DiscriminatingEventProbe;
assert.equal(buildChoiceFrame({
method_id: "d4_home",
ask_theme: "home_change",
domain: "relocation",
user_prompt_hint: "unused",
}, { probes: [missingFamily] }), null);
assert.equal(buildChoiceFrame({
method_id: "d4_home",
ask_theme: "home_change",
domain: "relocation",
user_prompt_hint: "unused",
}, { probes: [{ ...MOVE_PROBE, event_family: " " }] }), null);
});
test("yearless D24 quality cards do not borrow a recorded education year", () => {
const frame = buildChoiceFrame({
method_id: "d5_education",
ask_theme: "education_style",
domain: "education",
user_prompt_hint: "unused",
choice_kind: "event_quality",
semantic_key: "varga.d24.05:00/05:07",
style_options: QUALITY_STYLE_OPTIONS,
}, {
evidence: [{
status: "confirmed",
domain: "education",
datePrecision: "year",
occurredFrom: "2016-01-01",
occurredTo: null,
}],
probes: [{
...MOVE_PROBE,
year: 0,
year_label: "当前这几个候选",
domain: "education",
event_family: "学业或考试发挥失常、压力特别大",
choice_kind: "event_quality",
semantic_key: "varga.d24.05:00/05:07",
style_options: QUALITY_STYLE_OPTIONS,
}],
});
assert.ok(frame);
assert.doesNotMatch(frame.period, /2016/);
assert.doesNotMatch(frame.prompt, /2016/);
});
test("yearless family cards attach a scoring frame without borrowing another domain's year", () => {
const frame = buildChoiceFrame({
method_id: "relatives",
ask_theme: "family_event",
domain: "family",
user_prompt_hint: "unused",
choice_kind: "existence",
semantic_key: "varga.d12.05:00/05:07",
}, {
evidence: [{
status: "confirmed",
domain: "education",
datePrecision: "year",
occurredFrom: "2016-01-01",
occurredTo: null,
}],
probes: [{
...MOVE_PROBE,
year: 0,
year_label: "当前这几个候选",
domain: "family",
event_family: "家人结婚、添丁或住院",
choice_kind: "existence",
semantic_key: "varga.d12.05:00/05:07",
}],
});
assert.ok(frame);
assert.doesNotMatch(frame.period, /2016/);
assert.doesNotMatch(frame.prompt, /2016/);
assert.match(frame.neither_label + frame.option_a_hint + frame.option_b_hint, /明确没有发生|家人/);
});
test("yearless family cards do not borrow a recorded family year", () => {
const frame = buildChoiceFrame({
method_id: "relatives",
ask_theme: "family_event",
domain: "family",
user_prompt_hint: "unused",
choice_kind: "existence",
semantic_key: "varga.d12.05:00/05:07",
}, {
evidence: [{
status: "confirmed",
domain: "family",
datePrecision: "year",
occurredFrom: "2018-01-01",
occurredTo: null,
}],
probes: [{
...MOVE_PROBE,
year: 0,
year_label: "当前这几个候选",
domain: "family",
event_family: "家人结婚、添丁或住院",
choice_kind: "existence",
semantic_key: "varga.d12.05:00/05:07",
}],
});
assert.ok(frame);
assert.doesNotMatch(frame.period, /2018/);
assert.doesNotMatch(frame.prompt, /2018/);
});
test("GET upgrades a persisted placeholder stem to the recorded year lock", () => {
assert.equal(
preferConcreteChoicePrompt(
"2016 年前后,有没有学业或考试发挥失常、压力特别大的时候?",
"当前这几个候选 · 学业、考试发挥或学习压力出现明显变化",
),
"2016 年前后,有没有学业或考试发挥失常、压力特别大的时候?",
);
assert.equal(
preferConcreteChoicePrompt(
"2016 年前后,有没有学业或考试发挥失常、压力特别大的时候?",
"2016 年前后 · 学业、考试发挥或学习压力出现明显变化",
),
"2016 年前后,有没有学业或考试发挥失常、压力特别大的时候?",
);
assert.equal(
preferConcreteChoicePrompt(
"2018 年前后,有没有开始一段认真关系、分手或结婚?",
"2018 年前后,有没有认真关系进入、结束或关系观明显转变?",
),
"2018 年前后,有没有开始一段认真关系、分手或结婚?",
);
assert.equal(
preferConcreteChoicePrompt(
"2018 年前后,有没有家人结婚、添丁或住院?",
"那段时间,有没有家人相关的明显变化?",
),
"2018 年前后,有没有家人结婚、添丁或住院?",
);
});
test("choice frame completes existence options and rejects illegal or non-renderable varga styles", () => {
const build = (style_options: DiscriminatingEventProbe["style_options"], extra: Partial<DiscriminatingEventProbe> = {}) => buildChoiceFrame({
method_id: "d4_home",
ask_theme: "home_change",
domain: "relocation",
user_prompt_hint: "unused",
}, { probes: [{ ...MOVE_PROBE, style_options, ...extra }] });
assert.ok(build(DYNAMIC_STYLE_OPTIONS.slice(0, 3)));
assert.ok(build(undefined));
assert.equal(build([
{ label: "巨蟹相处主动热情", answer_class: "yes" },
], { choice_kind: "varga_style" }), null);
});
test("python-shaped existence probe without style_options still builds a four-option card", () => {
const { style_options: _unused, ...pythonProbe } = MOVE_PROBE;
const frame = buildChoiceFrame({
method_id: "d4_home",
ask_theme: "home_change",
domain: "relocation",
user_prompt_hint: "unused",
}, { probes: [pythonProbe] });
assert.ok(frame);
assert.equal(frame.option_a_answer_class, "yes");
assert.equal(frame.option_b_answer_class, "weak_yes");
assert.equal(frame.option_c_answer_class, "no");
assert.equal(frame.option_d_answer_class, "unsure");
assert.equal(frame.unsure_label, "这段记不清楚");
});
test("style options without a real event probe do not generate a card", () => {
assert.equal(buildChoiceFrame({
method_id: "d10_career",
ask_theme: "career_style",
domain: "career",
user_prompt_hint: "unused",
choice_kind: "varga_style",
style_options: DYNAMIC_STYLE_OPTIONS,
}), null);
});
test("agent choice copy rejects appearance, scars, clock times, and incomplete C/D", () => {
assert.equal(parseAgentChoiceCopy({
choice: { prompt: "你长得更像哪一种?", option_a: "外貌偏圆", option_b: "有疤痕", option_c: "都没有", option_d: "不记得" },
}), null);
assert.equal(parseAgentChoiceCopy({
...SAMPLE_COPY,
prompt: "08:12 换升时发生了什么?",
}), null);
assert.equal(parseAgentChoiceCopy({
prompt: SAMPLE_COPY.prompt,
option_a: SAMPLE_COPY.option_a,
option_b: SAMPLE_COPY.option_b,
}), null);
assert.equal(parseAgentChoiceCopy({
...SAMPLE_COPY,
option_c: SAMPLE_COPY.option_a,
}), null);
assert.ok(parseAgentChoiceCopy(SAMPLE_COPY));
});
test("GET card without a persisted focus UUID is not tappable", () => {
const distinguish = projectRectificationChoiceCard({
evidence: [{
status: "confirmed",
domain: "education",
datePrecision: "year",
occurredFrom: "2016-01-01",
occurredTo: null,
}, {
status: "confirmed",
domain: "career",
datePrecision: "year",
occurredFrom: "2019-01-01",
occurredTo: null,
}, {
status: "confirmed",
domain: "relationship",
datePrecision: "year",
occurredFrom: "2018-01-01",
occurredTo: null,
}],
eventProbes: [MOVE_PROBE],
candidateScores: [
{ time: "05:00", score: 34 },
{ time: "05:20", score: 33 },
],
activeFocus: {
intent: "distinguish_candidates",
targetDomain: "relocation",
targetKind: "home_change",
expectedAnswerSchema: { choice: SAMPLE_COPY },
},
});
assert.equal(distinguish, null);
});
test("GET hides a legacy known-event quality focus and resumes evidence collection", () => {
const card = projectRectificationChoiceCard({
evidence: [{
status: "confirmed",
domain: "education",
datePrecision: "month",
occurredFrom: "2016-09-01",
occurredTo: null,
}],
eventClarificationProbes: [{
year: 2016,
year_label: "2016 年前后",
domain: "education",
event_family: "升学结果或学习环境出现明显变化",
source: "known_event_quality",
tracks: ["vimshottari", "narayana"],
tracks_agree: true,
unique_minute_claim: false,
user_meaning: "已知事件质量",
role: "clarify",
style_options: DYNAMIC_STYLE_OPTIONS,
phase: "event_clarification",
choice_kind: "event_quality",
semantic_key: "education.2016",
candidate_split_hash: "education:2016",
candidate_ids: [],
expected_outcomes: [],
information_gain: 0,
}],
activeFocus: {
id: FOCUS_ID,
intent: "clarify_event",
targetDomain: "education",
targetKind: null,
expectedAnswerSchema: {
choice: SAMPLE_COPY,
probe_id: "probe:education.2016",
semantic_key: "education.2016",
candidate_split_hash: "education:2016",
scoring: true,
choice_kind: "event_quality",
},
},
});
assert.equal(card, null);
const plan = buildMethodFollowupPlan({
evidence: [{
status: "confirmed",
domain: "education",
datePrecision: "month",
occurredFrom: "2016-09-01",
occurredTo: null,
}],
activeFocus: {
id: FOCUS_ID,
intent: "clarify_event",
targetDomain: "education",
targetKind: null,
expectedAnswerSchema: { choice: SAMPLE_COPY },
},
});
assert.equal(plan.next_followup?.method_id, "d9_relationship");
assert.equal(plan.next_followup?.choice_frame, null);
});
test("GET card stays hidden on an empty ledger even if the Agent already wrote choice copy", () => {
const withoutCopy = projectRectificationChoiceCard({ evidence: [] });
assert.equal(withoutCopy, null);
const leftoverOpening = projectRectificationChoiceCard({
evidence: [],
activeFocus: {
id: FOCUS_ID,
intent: "collect_method_evidence",
targetDomain: null,
targetKind: null,
expectedAnswerSchema: { choice: SAMPLE_COPY },
},
});
assert.equal(leftoverOpening, null);
const distinguish = projectRectificationChoiceCard({
evidence: [{
status: "confirmed",
domain: "education",
datePrecision: "year",
occurredFrom: "2016-01-01",
occurredTo: null,
}, {
status: "confirmed",
domain: "relationship",
datePrecision: "year",
occurredFrom: "2018-01-01",
occurredTo: null,
}, {
status: "confirmed",
domain: "career",
datePrecision: "year",
occurredFrom: "2019-01-01",
occurredTo: null,
}, {
status: "confirmed",
domain: "family",
datePrecision: "year",
occurredFrom: "2020-01-01",
occurredTo: null,
}, {
status: "confirmed",
domain: "occupation",
datePrecision: "unknown",
occurredFrom: null,
occurredTo: null,
}],
observations: [{ layer: "d9", candidates_differ: true, ask_theme: "relationship_style" }],
eventProbes: [{
year: 2018,
year_label: "2018 年前后",
domain: "relationship",
event_family: "认真关系进入、结束或关系观明显转变",
source: "dasha_activation",
tracks: ["vimshottari", "narayana"],
tracks_agree: true,
unique_minute_claim: false,
user_meaning: "年份锁定 2018 年前后。事件家族:认真关系进入、结束或关系观明显转变。请写成一句自然语言是/否题。不得改年份。",
role: "distinguish",
style_options: DYNAMIC_STYLE_OPTIONS,
information_gain: 0.4,
candidate_ids: ["05:00", "05:20"],
expected_outcomes: [
{ answer_class: "yes", supports: ["05:00"], conflicts: ["05:20"] },
{ answer_class: "no", supports: ["05:20"], conflicts: ["05:00"] },
],
}],
activeFocus: {
id: FOCUS_ID,
intent: "distinguish_candidates",
targetDomain: "relationship",
targetKind: "relationship_change",
expectedAnswerSchema: { choice: SAMPLE_COPY },
},
});
assert.equal(distinguish?.prompt, SAMPLE_COPY.prompt);
assert.equal(distinguish?.options[2]?.label, SAMPLE_COPY.option_c);
assert.ok(parseRectificationChoiceCard(distinguish));
});
test("opening follow-up asks for a dated event in natural language, not a choice card", () => {
const plan = buildMethodFollowupPlan({ evidence: [] });
assert.equal(plan.next_followup?.method_id, "dasha_events");
assert.equal(plan.next_followup?.choice_frame, null);
assert.doesNotMatch(plan.next_followup?.user_prompt_hint ?? "", /A\/B\/C\/D/);
assert.match(plan.next_followup?.user_prompt_hint ?? "", /自然语言/);
assert.match(plan.next_followup?.user_prompt_hint ?? "", /不要调用 set-focus/);
});
test("distinguish follow-up copy forbids competing-chart ranking", () => {
const plan = buildMethodFollowupPlan({
evidence: [{
status: "confirmed",
domain: "education",
datePrecision: "year",
occurredFrom: "2016-01-01",
occurredTo: null,
}, {
status: "confirmed",
domain: "relationship",
datePrecision: "year",
occurredFrom: "2018-01-01",
occurredTo: null,
}, {
status: "confirmed",
domain: "career",
datePrecision: "year",
occurredFrom: "2019-01-01",
occurredTo: null,
}, {
status: "confirmed",
domain: "family",
datePrecision: "year",
occurredFrom: "2020-01-01",
occurredTo: null,
}, {
status: "confirmed",
domain: "occupation",
datePrecision: "unknown",
occurredFrom: null,
occurredTo: null,
}, {
status: "confirmed",
domain: "horary",
datePrecision: "day",
occurredFrom: "2024-01-01",
occurredTo: null,
}],
precisionStage: "d4_refine",
eventProbes: [MOVE_PROBE],
birthDate: "1997-08-08",
});
assert.equal(plan.next_followup?.choice_frame?.period, "2016 年前后");
assert.doesNotMatch(plan.next_followup?.choice_frame?.option_a_hint ?? "", /更像哪一件|两套盘|可能性/);
assert.doesNotMatch(plan.next_followup?.choice_frame?.option_b_hint ?? "", /更像哪一件|两套盘|可能性/);
assert.match(plan.next_followup?.user_prompt_hint ?? "", /自己写一句追问/);
assert.match(plan.next_followup?.user_prompt_hint ?? "", /不得发明年份/);
});
test("GET A/B card stays visible after coverage when candidates remain tied", () => {
const card = projectRectificationChoiceCard({
evidence: [{
status: "confirmed",
domain: "education",
datePrecision: "year",
occurredFrom: "2016-01-01",
occurredTo: null,
}, {
status: "confirmed",
domain: "relationship",
datePrecision: "year",
occurredFrom: "2018-01-01",
occurredTo: null,
}, {
status: "confirmed",
domain: "career",
datePrecision: "year",
occurredFrom: "2019-01-01",
occurredTo: null,
}, {
status: "confirmed",
domain: "family",
datePrecision: "year",
occurredFrom: "2020-01-01",
occurredTo: null,
}, {
status: "draft",
domain: "occupation",
datePrecision: "unknown",
occurredFrom: null,
occurredTo: null,
eventKind: "occupation_note",
}],
eventProbes: [MOVE_PROBE],
selectionAllowed: true,
proposeAllowed: true,
candidateScores: [
{ time: "05:00", score: 34 },
{ time: "05:01", score: 33 },
{ time: "05:02", score: 33 },
],
activeFocus: {
id: FOCUS_ID,
intent: "distinguish_candidates",
targetDomain: "relocation",
targetKind: "home_change",
expectedAnswerSchema: { choice: SAMPLE_COPY },
},
});
assert.ok(card);
assert.equal(card.prompt, SAMPLE_COPY.prompt);
});
test("GET A/B card stays hidden once candidates are separated and ready to offer", () => {
const card = projectRectificationChoiceCard({
evidence: [{
status: "confirmed",
domain: "education",
datePrecision: "year",
occurredFrom: "2016-01-01",
occurredTo: null,
}, {
status: "confirmed",
domain: "relationship",
datePrecision: "year",
occurredFrom: "2018-01-01",
occurredTo: null,
}, {
status: "confirmed",
domain: "career",
datePrecision: "year",
occurredFrom: "2019-01-01",
occurredTo: null,
}, {
status: "confirmed",
domain: "family",
datePrecision: "year",
occurredFrom: "2020-01-01",
occurredTo: null,
}, {
status: "draft",
domain: "occupation",
datePrecision: "unknown",
occurredFrom: null,
occurredTo: null,
eventKind: "occupation_note",
}],
eventProbes: [MOVE_PROBE],
selectionAllowed: true,
proposeAllowed: true,
holdoutValidation: "passed",
candidateScores: [
{ time: "05:00", score: 62 },
{ time: "05:01", score: 22 },
{ time: "05:02", score: 16 },
],
});
assert.equal(card, null);
});
test("GET reverse-verify card still appears after a time is accepted", () => {
const card = projectRectificationChoiceCard({
evidence: [{
status: "confirmed",
domain: "career",
datePrecision: "day",
occurredFrom: "2024-04-07",
occurredTo: null,
}],
accepted: true,
sessionOutcome: "adopt_representative",
selectionAllowed: true,
proposeAllowed: true,
eventProbes: [{
year: 2018,
year_label: "2018 年前后",
domain: "career",
event_family: "入职、升职或职责明显加重",
source: "dasha_activation",
tracks: ["vimshottari", "narayana"],
tracks_agree: true,
unique_minute_claim: false,
user_meaning: "年份锁定 2018 年前后。请写成一句自然语言,问是否入职或职责加重。",
role: "reverse_verify",
style_options: DYNAMIC_STYLE_OPTIONS,
}],
activeFocus: {
id: FOCUS_ID,
intent: "reverse_verify",
targetDomain: "career",
targetKind: "career_change",
expectedAnswerSchema: { choice: SAMPLE_COPY },
},
});
assert.equal(card?.prompt, SAMPLE_COPY.prompt);
assert.ok(parseRectificationChoiceCard(card));
});
test("GET choice_card stays after coverage when remaining minutes still split on D24", () => {
const card = choiceCardFromCaseDossier({
evidence: [{
status: "confirmed",
domain: "education",
datePrecision: "year",
occurredFrom: "2016-01-01",
occurredTo: null,
summary: "2016 年大学入学",
}, {
status: "confirmed",
domain: "relationship",
datePrecision: "year",
occurredFrom: "2018-01-01",
occurredTo: null,
}, {
status: "confirmed",
domain: "career",
datePrecision: "year",
occurredFrom: "2019-01-01",
occurredTo: null,
}, {
status: "confirmed",
domain: "family",
datePrecision: "year",
occurredFrom: "2020-01-01",
occurredTo: null,
}, {
status: "draft",
domain: "occupation",
datePrecision: "unknown",
occurredFrom: null,
occurredTo: null,
eventKind: "occupation_note",
summary: "医疗器械算法,第三个(技术执行)",
}],
conversationSummary: {
activeFocus: {
id: "abababab-abab-4bab-8bab-abababababab",
intent: "distinguish_candidates",
targetDomain: "education",
targetKind: "education_milestone",
expectedAnswerSchema: {
choice: SAMPLE_COPY,
probe_id: "contrast:varga.d24.05:00/05:06|05:07",
semantic_key: "varga.d24.05:00/05:06|05:07",
candidate_split_hash: "varga.d24.05:00/05:06|05:07",
},
},
declinedSkippedTopics: [],
},
latestResult: {
resultId: "55555555-5555-4555-8555-555555555555",
selectionAllowed: true,
candidates: [
{ time: "05:00", relativeSupport: 34 },
{ time: "05:06", relativeSupport: 33 },
{ time: "05:07", relativeSupport: 33 },
],
decisionReceipt: {
propose_allowed: true,
discriminating_event_probes: [{
year: 2017,
year_label: "2017 年前后",
domain: "education",
event_family: "学习方向或升学环境出现明显变化",
source: "dasha_activation",
tracks: ["vimshottari", "narayana"],
tracks_agree: true,
unique_minute_claim: false,
user_meaning: "年份锁定 2017 年前后,核对学习方向或升学环境变化。",
role: "distinguish",
phase: "candidate_discriminator",
information_gain: 0.16,
semantic_key: "varga.d24.05:00/05:06|05:07",
candidate_split_hash: "varga.d24.05:00/05:06|05:07",
candidate_ids: ["05:00", "05:06", "05:07"],
expected_outcomes: [
{ answer_class: "yes", supports: ["05:00"], conflicts: ["05:06", "05:07"] },
{ answer_class: "no", supports: ["05:06", "05:07"], conflicts: ["05:00"] },
],
style_options: DYNAMIC_STYLE_OPTIONS,
}],
window_scan: {
scanned: true,
d9_lagna_count: 1,
d10_lagna_count: 3,
d10_candidates_differ: true,
d10_sign_names: ["巨蟹座", "狮子座", "处女座"],
d24_candidates_differ: true,
transitions: [
{ layer: "d10", at: "05:00" },
{ layer: "d10", at: "05:15" },
{ layer: "d24", at: "05:00" },
{ layer: "d24", at: "05:06" },
],
},
inference_state: {
algorithm_version: "rectification-inference-v1",
candidate_set_id: "05:00-05:07:05:00,05:06,05:07",
revision: 1,
phase: "discrimination",
result_status: "discriminating",
range_start: "05:00",
range_end: "05:07",
candidates: [
{ id: "05:00", time: "05:00", cluster_range: ["05:00", "05:00"], prior_score: 34, posterior_score: 34, probability: 0.34, status: "active", rank: 1, strong_conflict_count: 0 },
{ id: "05:06", time: "05:06", cluster_range: ["05:06", "05:06"], prior_score: 33, posterior_score: 33, probability: 0.33, status: "active", rank: 2, strong_conflict_count: 0 },
{ id: "05:07", time: "05:07", cluster_range: ["05:07", "05:07"], prior_score: 33, posterior_score: 33, probability: 0.33, status: "active", rank: 3, strong_conflict_count: 0 },
],
events: [],
answered_probes: [{
probe_id: "probe:education.2016",
semantic_key: "education.2016",
candidate_split_hash: "education.2016",
answer_class: "yes",
classified_from: "evidence",
}],
probes: [{
id: "probe:education.2016",
semantic_key: "education.2016",
candidate_split_hash: "education.2016",
domain: "education",
year: 2016,
question: "2016 年是否入学?",
candidate_ids: ["05:00", "05:06", "05:07"],
information_gain: 0,
source: "known_event_quality",
expected_outcomes: [],
}],
rounds: [],
entropy: 1,
representative_time: "05:00",
credible_range: ["05:00", "05:07"],
},
},
},
case: { acceptedTime: null },
turns: [],
});
assert.ok(card);
assert.equal(card.probe_id, "contrast:varga.d24.05:00/05:06|05:07");
assert.equal(card.prompt, SAMPLE_COPY.prompt);
});
test("GET shows an engine-dated career dasha instead of locking D24 to the recorded education year", () => {
const careerKey = "career.2012.11.dasha_boundary";
const careerCopy = {
prompt: "2012 年 11 月前后,有没有入职、升职或职责明显加重?",
option_a: DYNAMIC_STYLE_OPTIONS[0]!.label,
option_b: DYNAMIC_STYLE_OPTIONS[1]!.label,
option_c: DYNAMIC_STYLE_OPTIONS[2]!.label,
option_d: DYNAMIC_STYLE_OPTIONS[3]!.label,
options: DYNAMIC_STYLE_OPTIONS.map((option, index) => ({
key: (["A", "B", "C", "D"] as const)[index]!,
label: option.label,
answer_class: option.answer_class,
})),
};
const inferenceCandidates = [
{ id: "04:47", time: "04:47", cluster_range: ["04:47", "04:47"] as const, prior_score: 5, posterior_score: 5, probability: 0.05, status: "active", rank: 6, strong_conflict_count: 0 },
{ id: "05:00", time: "05:00", cluster_range: ["05:00", "05:00"] as const, prior_score: 21, posterior_score: 21, probability: 0.21, status: "active", rank: 1, strong_conflict_count: 0 },
{ id: "05:07", time: "05:07", cluster_range: ["05:07", "05:07"] as const, prior_score: 18, posterior_score: 18, probability: 0.18, status: "active", rank: 2, strong_conflict_count: 0 },
{ id: "05:12", time: "05:12", cluster_range: ["05:12", "05:12"] as const, prior_score: 18, posterior_score: 18, probability: 0.18, status: "active", rank: 3, strong_conflict_count: 0 },
{ id: "05:14", time: "05:14", cluster_range: ["05:14", "05:14"] as const, prior_score: 17, posterior_score: 17, probability: 0.17, status: "active", rank: 4, strong_conflict_count: 0 },
{ id: "05:15", time: "05:15", cluster_range: ["05:15", "05:15"] as const, prior_score: 3, posterior_score: 3, probability: 0.03, status: "active", rank: 9, strong_conflict_count: 0 },
];
const candidateSetId = "04:45-05:15:04:47,05:00,05:07,05:12,05:14,05:15";
const d24Key = "varga.d24.04:47/04:51|04:53/04:59/05:00/05:07|05:12/05:14|05:15";
const d24Split = `${candidateSetId}:${d24Key}`;
const d24Outcomes = [
{ answer_class: "yes", supports: ["04:47"], conflicts: ["05:00", "05:07", "05:12", "05:14", "05:15"] },
{ answer_class: "weak_yes", supports: ["05:00", "05:07"], conflicts: ["04:47", "05:12", "05:14", "05:15"] },
{ answer_class: "no", supports: ["05:12", "05:14"], conflicts: ["04:47", "05:00", "05:07", "05:15"] },
{ answer_class: "unsure", supports: [], conflicts: [] },
];
const card = choiceCardFromCaseDossier({
evidence: [{
status: "confirmed",
domain: "education",
datePrecision: "year",
occurredFrom: "2016-01-01",
occurredTo: "2016-01-01",
eventKind: "education_start",
}, {
status: "confirmed",
domain: "career",
datePrecision: "month",
occurredFrom: "2020-04-01",
occurredTo: "2020-04-01",
eventKind: "career_entry",
}, {
status: "confirmed",
domain: "career",
datePrecision: "month",
occurredFrom: "2020-10-01",
occurredTo: "2020-10-01",
eventKind: "career_exit",
}, {
status: "confirmed",
domain: "career",
datePrecision: "day",
occurredFrom: "2024-04-07",
occurredTo: null,
eventKind: "career_entry",
}, {
status: "confirmed",
domain: "relationship",
datePrecision: "month",
occurredFrom: "2024-05-01",
occurredTo: null,
eventKind: "relationship_start",
}, {
status: "confirmed",
domain: "relationship",
datePrecision: "day",
occurredFrom: "2024-08-08",
occurredTo: null,
eventKind: "relationship_end",
}],
conversationSummary: {
activeFocus: {
id: FOCUS_ID,
questionId: `probe:${careerKey}`,
intent: "distinguish_candidates",
targetDomain: "career",
targetKind: null,
expectedAnswerSchema: {
choice: careerCopy,
probe_id: `event:${careerKey}`,
semantic_key: careerKey,
candidate_split_hash: "career.2012.11",
choice_kind: "existence",
},
},
declinedSkippedTopics: [],
},
latestResult: {
resultId: "result-d24-open",
selectionAllowed: true,
confirmationAllowed: false,
candidates: inferenceCandidates.map((item) => ({
time: item.time,
rank: item.rank,
relativeSupport: item.posterior_score,
})),
decisionReceipt: {
discriminating_event_probes: [{
year: 2012,
year_label: "2012 年 11 月前后",
domain: "career",
event_family: "入职、升职或职责明显加重",
source: "dasha_boundary",
tracks: ["vimshottari", "narayana"],
tracks_agree: true,
unique_minute_claim: false,
user_meaning: "时间范围锁定 2012 年 11 月前后。",
role: "distinguish",
phase: "candidate_discriminator",
information_gain: 1.3356,
semantic_key: careerKey,
candidate_split_hash: "career.2012.11",
candidate_ids: ["04:47", "05:00", "05:15"],
expected_outcomes: [
{ answer_class: "yes", supports: ["04:47"], conflicts: ["05:00", "05:15"] },
{ answer_class: "weak_yes", supports: ["04:47"], conflicts: ["05:00", "05:15"] },
{ answer_class: "no", supports: ["05:00", "05:15"], conflicts: ["04:47"] },
{ answer_class: "unsure", supports: [], conflicts: [] },
],
style_options: DYNAMIC_STYLE_OPTIONS,
}],
inference_state: {
algorithm_version: "rectification-inference-v1",
candidate_set_id: candidateSetId,
revision: 1,
phase: "discrimination",
result_status: "discriminating",
range_start: "04:45",
range_end: "05:15",
candidates: inferenceCandidates,
events: [],
probes: [{
id: `contrast:${d24Key}`,
year: 0,
domain: "education",
source: "varga_contrast",
question: "引擎给出的区分机会绑定 D24。",
semantic_key: d24Key,
candidate_ids: inferenceCandidates.map((item) => item.time),
information_gain: 2.503258334775646,
expected_outcomes: d24Outcomes,
candidate_split_hash: d24Split,
}],
answered_probes: [],
rounds: [],
entropy: 2.0,
representative_time: "05:00",
credible_range: ["05:00", "05:14"],
},
},
},
case: { acceptedTime: null, status: "collecting_evidence" },
turns: [],
});
assert.ok(card);
assert.equal(card.focus_id, FOCUS_ID);
assert.match(card.prompt, /2012 年 11 月前后,有没有入职、升职或职责明显加重?/);
assert.doesNotMatch(card.prompt, /2016 年前后/);
assert.doesNotMatch(card.prompt, /当前这几个候选/);
assert.doesNotMatch(card.prompt, / · /);
assert.equal(card.options.length, 4);
assert.equal(card.options.every((option) => option.role === "primary"), true);
});
test("GET choice_card stays hidden without a persisted focus after 没有了", () => {
const card = choiceCardFromCaseDossier({
evidence: [{
status: "confirmed",
domain: "education",
datePrecision: "year",
occurredFrom: "2016-01-01",
occurredTo: null,
}, {
status: "confirmed",
domain: "relationship",
datePrecision: "year",
occurredFrom: "2018-01-01",
occurredTo: null,
}, {
status: "confirmed",
domain: "career",
datePrecision: "year",
occurredFrom: "2019-01-01",
occurredTo: null,
}, {
status: "confirmed",
domain: "family",
datePrecision: "year",
occurredFrom: "2020-01-01",
occurredTo: null,
}, {
status: "draft",
domain: "occupation",
datePrecision: "unknown",
occurredFrom: null,
occurredTo: null,
eventKind: "occupation_note",
}],
conversationSummary: {
activeFocus: null,
declinedSkippedTopics: [],
},
latestResult: {
selectionAllowed: true,
candidates: [
{ time: "05:00", relativeSupport: 34 },
{ time: "05:06", relativeSupport: 33 },
{ time: "05:07", relativeSupport: 33 },
],
decisionReceipt: { propose_allowed: true },
},
case: { acceptedTime: null },
turns: [{ role: "user", text: "没有了" }],
});
assert.equal(card, null);
});
test("dynamic option labels canonicalize to yes/weak_yes/no/unsure order", () => {
const styleOptions = [
{ label: "明确没有发生", answer_class: "no" },
{ label: "这段记不清楚", answer_class: "unsure" },
{ label: "明确发生且时间吻合", answer_class: "yes" },
{ label: "发生过但程度较弱", answer_class: "weak_yes" },
] as const;
const frame = buildChoiceFrame({
method_id: "d4_home",
ask_theme: "home_change",
domain: "relocation",
user_prompt_hint: "unused",
choice_kind: "existence",
style_options: styleOptions,
}, { probes: [{ ...MOVE_PROBE, style_options: styleOptions }] });
assert.ok(frame);
const copy = serverOwnedChoiceCopy(frame);
assert.deepEqual(copy?.options, [
{ key: "A", label: "明确发生且时间吻合", answer_class: "yes" },
{ key: "B", label: "发生过但程度较弱", answer_class: "weak_yes" },
{ key: "C", label: "明确没有发生", answer_class: "no" },
{ key: "D", label: "这段记不清楚", answer_class: "unsure" },
]);
});
test("choice card requires the persisted focus to match the discriminator identity", () => {
assert.equal(identityCard({ semantic_key: "relationship.2016" }), null);
assert.equal(identityCard({ candidate_split_hash: "different-split" }), null);
const card = identityCard();
assert.ok(card);
assert.equal(card.focus_id, FOCUS_ID);
assert.equal(card.question_id, "persisted-question-id");
});
test("GET card prompt keeps the agent's year-locked question", () => {
const fallback = {
...SAMPLE_COPY,
prompt: "2018 年前后 · 认真关系进入、结束或关系观明显转变",
};
const card = projectRectificationChoiceCard({
evidence: [{
status: "confirmed",
domain: "education",
datePrecision: "year",
occurredFrom: "2016-01-01",
occurredTo: null,
}, {
status: "confirmed",
domain: "relationship",
datePrecision: "year",
occurredFrom: "2017-01-01",
occurredTo: null,
}, {
status: "confirmed",
domain: "career",
datePrecision: "year",
occurredFrom: "2019-01-01",
occurredTo: null,
}],
eventProbes: [{
year: 2018,
year_label: "2018 年前后",
domain: "relationship",
event_family: "认真关系进入、结束或关系观明显转变",
source: "dasha_activation",
tracks: ["vimshottari", "narayana"],
tracks_agree: true,
unique_minute_claim: false,
user_meaning: "年份锁定 2018 年前后。",
role: "reverse_verify",
style_options: DYNAMIC_STYLE_OPTIONS,
}],
activeFocus: {
id: FOCUS_ID,
intent: "distinguish_candidates",
targetDomain: "relationship",
targetKind: "relationship_change",
expectedAnswerSchema: { choice: fallback, probe_id: "relationship.2018" },
},
latestAssistantText: "记下了。2018 年前后,有没有一段认真的关系开始或结束?",
});
assert.ok(card);
assert.equal(card.prompt, "2018 年前后,有没有一段认真的关系开始或结束?");
assert.doesNotMatch(card.prompt, /有没有明显认真关系进入/);
});
test("career event_quality uses the supplied dynamic labels", () => {
const frame = buildChoiceFrame({
method_id: "d10_career",
ask_theme: "career_style",
domain: "career",
user_prompt_hint: "unused",
choice_kind: "event_quality",
}, {
probes: [{
year: 2020,
year_label: "2020 年前后",
domain: "career",
event_family: "入职、升职或职责明显加重",
source: "known_event_quality",
tracks: ["vimshottari", "narayana"],
tracks_agree: true,
unique_minute_claim: false,
user_meaning: "年份锁定 2020 年前后。已有相关经历。请写成一句自然语言,问入职、升职或职责明显加重有没有发生过。不得改年份。",
role: "distinguish",
style_options: DYNAMIC_STYLE_OPTIONS,
choice_kind: "event_quality",
}],
});
assert.ok(frame);
const copy = serverOwnedChoiceCopy(frame);
assert.ok(copy);
assert.match(copy.prompt, /2020 年前后/);
assert.match(copy.prompt, /入职、升职或职责明显加重/);
assert.match(copy.prompt, /有没有/);
assert.doesNotMatch(copy.prompt, / · /);
assert.equal(copy.option_a, DYNAMIC_STYLE_OPTIONS[0].label);
assert.doesNotMatch(copy.option_a, /失常/);
});
test("dasha existence cards lock the event and use supplied dynamic labels", () => {
const frame = buildChoiceFrame({
method_id: "d4_home",
ask_theme: "home_change",
domain: "relocation",
user_prompt_hint: "unused",
choice_kind: "existence",
}, { probes: [MOVE_PROBE] });
assert.ok(frame);
const copy = serverOwnedChoiceCopy(frame);
assert.ok(copy);
assert.match(copy.prompt, /2016 年前后/);
assert.match(copy.prompt, /搬家、离乡或长期异地/);
assert.doesNotMatch(copy.prompt, /有没有明显/);
assert.equal(copy.option_a, DYNAMIC_STYLE_OPTIONS[0].label);
assert.equal(copy.option_c, DYNAMIC_STYLE_OPTIONS[2].label);
});
const D9_STALE_KEY = "varga.d9.05:00|05:06/05:07";
const CURRENT_SET_ID = "05:00-05:07:05:00,05:06,05:07";
// The probe was minted while the candidate set still held 05:05 instead of 05:06.
const STALE_SET_ID = "05:00-05:07:05:00,05:05,05:07";
const D9_STYLE_OPTIONS = [
{ sign: "天秤座", label: "和谐、美感、合作", answer_class: "yes" },
{ sign: "天蝎座", label: "深刻、占有欲、转化", answer_class: "weak_yes" },
{ sign: "射手座", label: "自由、哲学、冒险", answer_class: "no" },
{ label: "这段记不清楚", answer_class: "unsure" },
] as const;
function staleSplitDossier(schemaHash: string) {
return {
evidence: [
{ id: "e-career-a", status: "confirmed", domain: "career", datePrecision: "month", occurredFrom: "2020-04-01", occurredTo: "2020-04-01", eventKind: "career_entry" },
{ id: "e-career-b", status: "confirmed", domain: "career", datePrecision: "month", occurredFrom: "2020-10-01", occurredTo: "2020-10-01", eventKind: "career_exit" },
{ id: "e-rel-end", status: "confirmed", domain: "relationship", datePrecision: "day", occurredFrom: "2024-08-08", occurredTo: "2024-08-08", eventKind: "relationship_end" },
{ id: "e-rel-start", status: "confirmed", domain: "relationship", datePrecision: "month", occurredFrom: "2024-05-01", occurredTo: "2024-05-31", eventKind: "relationship_start" },
],
conversationSummary: {
activeFocus: {
id: FOCUS_ID,
questionId: `probe:${D9_STALE_KEY}`,
intent: "distinguish_candidates",
targetDomain: "relationship",
targetKind: null,
expectedAnswerSchema: {
choice: {
prompt: "2024 年前后,相处方式更接近其中一种?",
option_a: D9_STYLE_OPTIONS[0].label,
option_b: D9_STYLE_OPTIONS[1].label,
option_c: D9_STYLE_OPTIONS[2].label,
option_d: D9_STYLE_OPTIONS[3].label,
options: [
{ key: "A", label: D9_STYLE_OPTIONS[0].label, answer_class: "yes" },
{ key: "B", label: D9_STYLE_OPTIONS[1].label, answer_class: "weak_yes" },
{ key: "C", label: D9_STYLE_OPTIONS[2].label, answer_class: "no" },
{ key: "D", label: D9_STYLE_OPTIONS[3].label, answer_class: "unsure" },
],
},
probe_id: `contrast:${D9_STALE_KEY}`,
semantic_key: D9_STALE_KEY,
candidate_split_hash: schemaHash,
choice_kind: "varga_style",
},
},
declinedSkippedTopics: [],
},
latestResult: {
resultId: "66666666-6666-4666-8666-666666666666",
selectionAllowed: false,
candidates: [
{ time: "05:00", relativeSupport: 34 },
{ time: "05:06", relativeSupport: 33 },
{ time: "05:07", relativeSupport: 33 },
],
decisionReceipt: {
window_scan: {
scanned: true,
d9_candidates_differ: true,
d9_sign_names: ["天秤座", "天蝎座", "射手座"],
transitions: [
{ layer: "d9", at: "05:06", from_sign: "天秤座", to_sign: "天蝎座" },
{ layer: "d9", at: "05:07", from_sign: "天蝎座", to_sign: "射手座" },
],
},
inference_state: {
algorithm_version: "rectification-inference-v1",
candidate_set_id: CURRENT_SET_ID,
revision: 1,
phase: "discrimination",
result_status: "discriminating",
range_start: "05:00",
range_end: "05:07",
candidates: [
{ id: "05:00", time: "05:00", cluster_range: ["05:00", "05:00"], prior_score: 34, posterior_score: 34, probability: 0.34, status: "active", rank: 1, strong_conflict_count: 0 },
{ id: "05:06", time: "05:06", cluster_range: ["05:06", "05:06"], prior_score: 33, posterior_score: 33, probability: 0.33, status: "active", rank: 2, strong_conflict_count: 0 },
{ id: "05:07", time: "05:07", cluster_range: ["05:07", "05:07"], prior_score: 33, posterior_score: 33, probability: 0.33, status: "active", rank: 3, strong_conflict_count: 0 },
],
events: [
{ id: "e-career-a", domain: "career", year: 2020, precision: "month", usage: "training" },
{ id: "e-career-b", domain: "career", year: 2020, precision: "month", usage: "training" },
{ id: "e-rel-end", domain: "relationship", year: 2024, precision: "day", usage: "training" },
{ id: "e-rel-start", domain: "relationship", year: 2024, precision: "month", usage: "holdout" },
],
answered_probes: [],
probes: [{
id: `contrast:${D9_STALE_KEY}`,
semantic_key: D9_STALE_KEY,
// minted one scoring round earlier, so the prefix names the old set
candidate_split_hash: `${STALE_SET_ID}:${D9_STALE_KEY}`,
domain: "relationship",
year: 0,
question: "亲密关系里更接近下面哪一种相处方式?",
candidate_ids: ["05:00", "05:06", "05:07"],
information_gain: 1.53,
source: "varga_contrast",
choice_kind: "varga_style",
style_options: D9_STYLE_OPTIONS,
expected_outcomes: [
{ answer_class: "yes", supports: ["05:00"], conflicts: ["05:06", "05:07"] },
{ answer_class: "weak_yes", supports: ["05:06"], conflicts: ["05:00", "05:07"] },
{ answer_class: "no", supports: ["05:07"], conflicts: ["05:00", "05:06"] },
],
}],
rounds: [],
entropy: 1.5,
representative_time: "05:00",
credible_range: ["05:00", "05:07"],
},
},
},
case: { acceptedTime: null },
turns: [],
};
}
test("GET still renders the card when the probe hash carries an older candidate set prefix", () => {
const card = choiceCardFromCaseDossier(
staleSplitDossier(`${STALE_SET_ID}:${D9_STALE_KEY}`) as never,
);
assert.ok(card, "a stale candidate-set prefix must not silence the persisted card");
assert.equal(card.probe_id, `contrast:${D9_STALE_KEY}`);
assert.equal(card.question_id, `probe:${D9_STALE_KEY}`);
});
test("GET keeps hiding the card when the persisted split belongs to another probe", () => {
const card = choiceCardFromCaseDossier(
staleSplitDossier(`${CURRENT_SET_ID}:varga.d10.05:00|05:06/05:07`) as never,
);
assert.equal(card, null);
});