fix(web): stop rectification interview when remaining minutes no longer split

Coverage-complete ties stayed in discrimination because whole-window D9/D24 follow-ups were treated as probes, and restated dates inserted duplicate evidence. Skip encoded remaining layers, ask leftover D4 or offer a provisional range, and dedupe dated rows by kind and date.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-08-25 19:02:35 +08:00
co-authored by Cursor
parent 946f11185e
commit a658ef8d2b
18 changed files with 1019 additions and 141 deletions
@@ -70,6 +70,29 @@ function candidates(scores: Readonly<Record<string, number>>): InferenceCandidat
}));
}
test("discriminating result does not stay in event_collection", () => {
const state = buildInferenceState({
range_start: "04:50",
range_end: "05:10",
candidates: [
{ id: "05:00", time: "05:00", relative_support: 34 },
{ id: "05:03", time: "05:03", relative_support: 33 },
{ id: "05:04", time: "05:04", relative_support: 33 },
],
events: [
{ id: "e1", domain: "education", year: 2016, precision: "month" },
{ id: "e2", domain: "career", year: 2018, precision: "year" },
{ id: "e3", domain: "relationship", year: 2021, precision: "year" },
{ id: "e4", domain: "family", year: 2023, precision: "year" },
{ id: "e5", domain: "relocation", year: 2017, precision: "year" },
],
probes: [probe({ id: "open", gain: 0.3, yesSupports: ["05:00"], yesConflicts: ["05:03"] })],
phase: "event_collection",
});
assert.equal(state.result_status, "discriminating");
assert.equal(state.phase, "discrimination");
});
test("an informative answer lowers entropy and cannot revive an eliminated candidate", () => {
const conflict = probe({
id: "p1",