fix(rectification): ask a ready discriminator before dated collect

Family coverage still continues dated collection when nothing can split leftover minutes, but an already-built choice card must not be displaced by spoken finance collect.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-09-05 10:34:24 +08:00
parent 309c74249e
commit cd704a92e7
8 changed files with 232 additions and 70 deletions
@@ -751,6 +751,54 @@ test("distinguish follow-up copy forbids competing-chart ranking", () => {
assert.match(plan.next_followup?.user_prompt_hint ?? "", /不得发明年份/);
});
test("family coverage without a renderable discriminator still collects the next dated domain", () => {
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",
birthDate: "1997-08-08",
});
assert.equal(plan.next_followup?.method_id, "d2_finance");
assert.equal(plan.next_followup?.intent, "collect_method_evidence");
assert.equal(plan.next_followup?.choice_frame, null);
assert.equal(plan.deferred_followup, null);
});
test("GET A/B card stays visible after coverage when candidates remain tied", () => {
const card = projectRectificationChoiceCard({
evidence: [{
@@ -248,7 +248,10 @@ test("career evidence alone still does not cover occupation", () => {
contrastPacket: { candidateSetVersion: "04:47-05:15", vargaDifferences: [], probes: [] },
});
assert.equal(plan.methods.find((item) => item.method_id === "occupation")?.status, "uncovered");
assert.equal(plan.next_followup?.method_id, "occupation");
// 原值: occupation
// 新值: d2_finance
// 原因: 家人已覆盖且无区分卡时,BUG-546 继续收未用带年份域;职业仍未覆盖,只是还没轮到
assert.equal(plan.next_followup?.method_id, "d2_finance");
});
test("training gate open does not mint yearless existence or quality varga cards", () => {
@@ -256,7 +259,10 @@ test("training gate open does not mint yearless existence or quality varga cards
assert.equal(plan.methods.find((item) => item.method_id === "occupation")?.status, "uncovered");
assert.doesNotMatch(plan.next_followup?.semantic_key ?? "", /^varga\.d(24|7|4|5)\./);
assert.equal(plan.dropped_probes.some((item) => item.reason === "yearless_ungrounded_contrast"), true);
assert.equal(plan.next_followup?.method_id, "occupation");
// 原值: occupation
// 新值: d2_finance
// 原因: yearless 存在/质量卡被丢掉后没有可渲染区分卡,BUG-546 先收财务采集
assert.equal(plan.next_followup?.method_id, "d2_finance");
assert.equal(plan.next_followup?.intent, "collect_method_evidence");
assert.equal(plan.next_followup?.choice_frame, null);
});