fix(rectification): ask from the scored probe catalog, not snapshot leftovers
Empty snapshot candidates were starving remaining D24 splits, so the TypeScript follow-up chain asked the low-gain Python career probe. Read paths now share one inference+engine catalog and yield a stale low-gain distinguish card to the current winner. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -7,8 +7,9 @@ import {
|
||||
publicDecisionFields,
|
||||
} from "../src/lib/rectification-agentic/core/rectification-decision.ts";
|
||||
import { decideNextAction } from "../src/lib/rectification-agentic/core/decide-next-action.ts";
|
||||
import { selectDiscriminatorProbe } from "../src/lib/rectification-agentic/core/candidate-contrast-packet.ts";
|
||||
import { contrastPacketFromDossier, overlayPublicDecision } from "../src/lib/rectification-agentic/v9/decision-from-dossier.ts";
|
||||
import { conversationalSessionOutcome } from "../src/lib/rectification-agentic/v9/method-followup.ts";
|
||||
import { buildMethodFollowupPlan, conversationalSessionOutcome } from "../src/lib/rectification-agentic/v9/method-followup.ts";
|
||||
|
||||
const SEPARATED = [
|
||||
{ time: "04:48", score: 58 },
|
||||
@@ -145,6 +146,158 @@ test("recorded education evidence does not suppress an unasked D24 discriminator
|
||||
assert.equal(packet.probes[0]?.expectedOutcomes.at(-1)?.outcomeId, "unsure");
|
||||
});
|
||||
|
||||
test("scored inference catalog outranks a low-gain Python career probe when snapshot candidates are empty", () => {
|
||||
const careerOutcomes = [
|
||||
{ answer_class: "yes", supports: ["04:45", "05:00", "05:14"], conflicts: ["05:15"] },
|
||||
{ answer_class: "weak_yes", supports: ["04:45", "05:00", "05:14"], conflicts: ["05:15"] },
|
||||
{ answer_class: "no", supports: ["05:15"], conflicts: ["04:45", "05:00", "05:14"] },
|
||||
{ answer_class: "unsure", supports: [], conflicts: [] },
|
||||
];
|
||||
const d24Outcomes = [
|
||||
{ answer_class: "yes", supports: ["04:47"], conflicts: ["04:51", "04:53", "04:59", "05:00", "05:07", "05:12", "05:14", "05:15"] },
|
||||
{ answer_class: "weak_yes", supports: ["04:51", "04:53"], conflicts: ["04:47", "04:59", "05:00", "05:07", "05:12", "05:14", "05:15"] },
|
||||
{ answer_class: "no", supports: ["04:59"], conflicts: ["04:47", "04:51", "04:53", "05:00", "05:07", "05:12", "05:14", "05:15"] },
|
||||
{ answer_class: "unsure", supports: [], conflicts: [] },
|
||||
];
|
||||
const inferenceCandidates = [
|
||||
{ id: "05:00", time: "05:00", cluster_range: ["05:00", "05:00"], prior_score: 22, posterior_score: 22, probability: 0.51, status: "active", rank: 1, strong_conflict_count: 0 },
|
||||
{ id: "05:07", time: "05:07", cluster_range: ["05:07", "05:07"], prior_score: 17, posterior_score: 17, probability: 0.15, status: "active", rank: 2, strong_conflict_count: 0 },
|
||||
{ id: "05:12", time: "05:12", cluster_range: ["05:12", "05:14"], prior_score: 17, posterior_score: 17, probability: 0.15, status: "equivalent", rank: 3, strong_conflict_count: 0 },
|
||||
{ id: "05:14", time: "05:14", cluster_range: ["05:12", "05:14"], prior_score: 17, posterior_score: 17, probability: 0.15, status: "equivalent", rank: 4, strong_conflict_count: 0 },
|
||||
{ id: "04:47", time: "04:47", cluster_range: ["04:47", "04:47"], prior_score: 6, posterior_score: 6, probability: 0.01, status: "active", rank: 5, strong_conflict_count: 0 },
|
||||
{ id: "04:51", time: "04:51", cluster_range: ["04:51", "04:51"], prior_score: 6, posterior_score: 6, probability: 0.01, status: "active", rank: 6, strong_conflict_count: 0 },
|
||||
{ id: "04:53", time: "04:53", cluster_range: ["04:53", "04:53"], prior_score: 6, posterior_score: 6, probability: 0.01, status: "active", rank: 7, strong_conflict_count: 0 },
|
||||
{ id: "04:59", time: "04:59", cluster_range: ["04:59", "04:59"], prior_score: 6, posterior_score: 6, probability: 0.01, status: "active", rank: 8, strong_conflict_count: 0 },
|
||||
{ id: "05:15", time: "05:15", cluster_range: ["05:15", "05:15"], prior_score: 3, posterior_score: 3, probability: 0.004, status: "active", rank: 9, strong_conflict_count: 0 },
|
||||
];
|
||||
const evidence = [
|
||||
{ status: "confirmed", domain: "education", datePrecision: "month", occurredFrom: "2016-09-01", occurredTo: null, eventKind: "education_start" },
|
||||
{ status: "confirmed", domain: "relationship", datePrecision: "day", occurredFrom: "2024-08-08", occurredTo: null, eventKind: "relationship_end" },
|
||||
{ status: "confirmed", domain: "career", datePrecision: "month", occurredFrom: "2020-04-01", occurredTo: null, eventKind: "career_entry" },
|
||||
{ status: "confirmed", domain: "family", datePrecision: "year", occurredFrom: "2018-01-01", occurredTo: null, eventKind: "family_event" },
|
||||
];
|
||||
const dossier = {
|
||||
evidence,
|
||||
conversationSummary: { activeFocus: null, declinedSkippedTopics: [] },
|
||||
latestResult: {
|
||||
resultId: "result-empty-snapshot",
|
||||
candidates: [],
|
||||
decisionReceipt: {
|
||||
discriminating_event_probes: [{
|
||||
role: "distinguish",
|
||||
phase: "candidate_discriminator",
|
||||
year: 2023,
|
||||
year_label: "2023 年前后",
|
||||
domain: "career",
|
||||
event_family: "入职、升职或职责明显加重",
|
||||
source: "dasha_activation",
|
||||
tracks: ["vimshottari", "narayana"],
|
||||
tracks_agree: false,
|
||||
unique_minute_claim: false,
|
||||
user_meaning: "时间范围锁定 2023 年前后;领域锁定 career。",
|
||||
choice_kind: "existence",
|
||||
information_gain: 0.56,
|
||||
semantic_key: "career.2023.dasha_activation",
|
||||
candidate_split_hash: "500ce694938305201fbab9ba",
|
||||
candidate_ids: ["04:45", "05:00", "05:14", "05:15"],
|
||||
expected_outcomes: careerOutcomes,
|
||||
style_options: [
|
||||
{ label: "明确发生且时间吻合", answer_class: "yes" },
|
||||
{ label: "发生过但程度较弱", answer_class: "weak_yes" },
|
||||
{ label: "明确没有发生", answer_class: "no" },
|
||||
{ label: "这段记不清楚", answer_class: "unsure" },
|
||||
],
|
||||
}],
|
||||
inference_state: {
|
||||
algorithm_version: "rectification-inference-v1",
|
||||
candidate_set_id: "04:45-05:15:04:47,04:51,04:53,04:59,05:00,05:07,05:12,05:14,05:15",
|
||||
revision: 1,
|
||||
phase: "discrimination",
|
||||
result_status: "discriminating",
|
||||
range_start: "04:45",
|
||||
range_end: "05:15",
|
||||
candidates: inferenceCandidates,
|
||||
events: [],
|
||||
probes: [{
|
||||
id: "probe:career.2023.dasha_activation:500ce694938305201fbab9ba",
|
||||
year: 2023,
|
||||
domain: "career",
|
||||
source: "dasha_activation",
|
||||
question: "时间范围锁定 2023 年前后;领域锁定 career。",
|
||||
semantic_key: "career.2023.dasha_activation",
|
||||
candidate_ids: ["04:45", "05:00", "05:14", "05:15"],
|
||||
information_gain: 0.56,
|
||||
expected_outcomes: careerOutcomes,
|
||||
candidate_split_hash: "500ce694938305201fbab9ba",
|
||||
}, {
|
||||
id: "contrast:varga.d24.04:47/04:51|04:53/04:59/05:00/05:07|05:12/05:14|05:15",
|
||||
year: 0,
|
||||
domain: "education",
|
||||
source: "varga_contrast",
|
||||
question: "引擎给出的区分机会绑定 D24。",
|
||||
semantic_key: "varga.d24.04:47/04:51|04:53/04:59/05:00/05:07|05:12/05:14|05:15",
|
||||
candidate_ids: ["04:47", "04:51", "04:53", "04:59", "05:00", "05:07", "05:12", "05:14", "05:15"],
|
||||
information_gain: 2.503258334775646,
|
||||
expected_outcomes: d24Outcomes,
|
||||
candidate_split_hash: "04:45-05:15:varga.d24",
|
||||
}],
|
||||
answered_probes: [],
|
||||
rounds: [],
|
||||
entropy: 2.0,
|
||||
representative_time: "05:00",
|
||||
credible_range: ["05:00", "05:14"],
|
||||
},
|
||||
window_scan: {
|
||||
scanned: true,
|
||||
d24_lagna_count: 6,
|
||||
d24_candidates_differ: true,
|
||||
transitions: [
|
||||
{ layer: "d24", at: "04:48", from_sign: "白羊座", to_sign: "金牛座" },
|
||||
{ layer: "d24", at: "04:54", from_sign: "金牛座", to_sign: "双子座" },
|
||||
{ layer: "d24", at: "05:00", from_sign: "双子座", to_sign: "巨蟹座" },
|
||||
{ layer: "d24", at: "05:06", from_sign: "巨蟹座", to_sign: "狮子座" },
|
||||
{ layer: "d24", at: "05:13", from_sign: "狮子座", to_sign: "处女座" },
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
case: { acceptedTime: null },
|
||||
};
|
||||
const packet = contrastPacketFromDossier(dossier);
|
||||
const selected = selectDiscriminatorProbe(packet);
|
||||
assert.match(selected?.semanticKey ?? "", /^varga\.d24\./);
|
||||
assert.ok((selected?.informationGain ?? 0) > 2);
|
||||
assert.doesNotMatch(selected?.semanticKey ?? "", /career\.2023/);
|
||||
|
||||
const plan = buildMethodFollowupPlan({
|
||||
evidence,
|
||||
eventProbes: packet.probes.flatMap((probe) => probe.semanticKey.startsWith("career.")
|
||||
? [{
|
||||
year: 2023,
|
||||
year_label: "2023 年前后",
|
||||
domain: "career",
|
||||
event_family: "入职、升职或职责明显加重",
|
||||
source: "dasha_activation",
|
||||
tracks: ["vimshottari", "narayana"],
|
||||
tracks_agree: false,
|
||||
unique_minute_claim: false,
|
||||
user_meaning: "时间范围锁定 2023 年前后。",
|
||||
role: "distinguish",
|
||||
phase: "candidate_discriminator",
|
||||
information_gain: 0.56,
|
||||
semantic_key: "career.2023.dasha_activation",
|
||||
candidate_split_hash: "500ce694938305201fbab9ba",
|
||||
candidate_ids: ["04:45", "05:00", "05:14", "05:15"],
|
||||
expected_outcomes: careerOutcomes,
|
||||
}]
|
||||
: []),
|
||||
contrastPacket: packet,
|
||||
candidatesSeparated: false,
|
||||
});
|
||||
assert.match(plan.next_followup?.semantic_key ?? "", /^varga\.d24\./);
|
||||
assert.doesNotMatch(plan.next_followup?.semantic_key ?? "", /career\.2023/);
|
||||
});
|
||||
|
||||
test("public candidate cards follow the inference ranking and hide an inconsistent state", () => {
|
||||
const decision = decideRectification({
|
||||
methodCoverageAll: true,
|
||||
|
||||
@@ -1825,6 +1825,52 @@ test("low-gain career event probe does not outrank a renderable high-gain D24 co
|
||||
assert.ok((plan.next_followup?.selection_score ?? 0) > 0.56);
|
||||
});
|
||||
|
||||
test("already-open low-gain career card yields to the high-gain D24 catalog winner", () => {
|
||||
const plan = buildMethodFollowupPlan({
|
||||
evidence: CLASSIC_COVERAGE.filter((item) => item.domain !== "horary"),
|
||||
eventProbes: [{
|
||||
...CAREER_CONFLICT_PROBE,
|
||||
year: 2023,
|
||||
year_label: "2023 年前后",
|
||||
semantic_key: "career.2023.dasha_activation",
|
||||
information_gain: 0.56,
|
||||
candidate_split_hash: "set-test:career:2023",
|
||||
}],
|
||||
contrastPacket: {
|
||||
candidateSetVersion: "05:00-05:14",
|
||||
vargaDifferences: [],
|
||||
probes: [{
|
||||
probeId: "contrast:varga.d24.05:00/05:07|05:10|05:14",
|
||||
candidateSetVersion: "05:00-05:14",
|
||||
question: "当前几个候选在学业盘上还分得开。",
|
||||
expectedOutcomes: [
|
||||
{ outcomeId: "yes", supportsCandidateIds: ["05:00"], conflictsCandidateIds: ["05:07", "05:10", "05:14"] },
|
||||
{ outcomeId: "no", supportsCandidateIds: ["05:07", "05:10", "05:14"], conflictsCandidateIds: ["05:00"] },
|
||||
],
|
||||
candidateSplitHash: "varga.d24.05:00/05:07|05:10|05:14",
|
||||
informationGain: 2.503258,
|
||||
sourceFeatures: [{ technique: "D24", calculationResultId: RESULT_ID }],
|
||||
domain: "education",
|
||||
year: null,
|
||||
semanticKey: "varga.d24.05:00/05:07|05:10|05:14",
|
||||
choiceKind: "event_quality",
|
||||
}],
|
||||
},
|
||||
candidatesSeparated: false,
|
||||
activeFocus: {
|
||||
intent: "distinguish_candidates",
|
||||
targetDomain: "career",
|
||||
targetKind: "career_entry",
|
||||
expectedAnswerSchema: {
|
||||
semantic_key: "career.2023.dasha_activation",
|
||||
candidate_split_hash: "set-test:career:2023",
|
||||
},
|
||||
},
|
||||
});
|
||||
assert.equal(plan.next_followup?.semantic_key, "varga.d24.05:00/05:07|05:10|05:14");
|
||||
assert.doesNotMatch(plan.next_followup?.semantic_key ?? "", /career\.2023/);
|
||||
});
|
||||
|
||||
const DUMP_COVERAGE = [
|
||||
{
|
||||
status: "confirmed" as const,
|
||||
|
||||
Reference in New Issue
Block a user