Engine asked_probe_keys no longer include varga split hashes that 400 the scorer, failed compares become visible and retry, user stop can still deliver a range on a stale snapshot, and holdout no longer reasks domains already in the ledger. Co-authored-by: Cursor <cursoragent@cursor.com>
204 lines
7.5 KiB
TypeScript
204 lines
7.5 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
|
|
import {
|
|
buildMethodFollowupPlan,
|
|
datedLedgerAnchor,
|
|
existenceProbeAsked,
|
|
remainingReverseVerifyProbes,
|
|
type MethodFollowupEvidence,
|
|
} from "../src/lib/rectification-agentic/v9/method-followup.ts";
|
|
import type { DiscriminatingEventProbe } from "../src/lib/rectification-agentic/v9/refinement-packet.ts";
|
|
import type { CandidateContrastPacket } from "../src/lib/rectification-agentic/core/candidate-contrast-packet.ts";
|
|
import { askedSemanticKeysForEngine } from "../src/lib/rectification-agentic/v9/inference-adapter.ts";
|
|
import { engineRequestBody, toEngineEvents } from "../src/lib/rectification-agentic/v9/engine-client.ts";
|
|
|
|
function existenceProbe(
|
|
domain: DiscriminatingEventProbe["domain"],
|
|
year: number,
|
|
extra: { month?: number; source?: DiscriminatingEventProbe["source"]; key?: string } = {},
|
|
): DiscriminatingEventProbe {
|
|
const month = extra.month;
|
|
const source = extra.source ?? "dasha_boundary";
|
|
const key = extra.key
|
|
?? (month
|
|
? `${domain}.${year}.${String(month).padStart(2, "0")}.${source}`
|
|
: `${domain}.${year}.${source}`);
|
|
return {
|
|
year,
|
|
year_label: month ? `${year} 年 ${month} 月前后` : `${year} 年前后`,
|
|
month,
|
|
domain,
|
|
event_family: "入职、升职或职责明显加重",
|
|
source,
|
|
tracks: ["vimshottari", "narayana"],
|
|
tracks_agree: true,
|
|
unique_minute_claim: false,
|
|
user_meaning: `时间范围锁定 ${year} 年。`,
|
|
role: "distinguish",
|
|
information_gain: 1.1,
|
|
semantic_key: key,
|
|
candidate_split_hash: key,
|
|
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"] },
|
|
],
|
|
choice_kind: "existence",
|
|
};
|
|
}
|
|
|
|
function dated(
|
|
id: string,
|
|
domain: string,
|
|
eventKind: string,
|
|
occurredFrom: string,
|
|
): MethodFollowupEvidence {
|
|
return {
|
|
id,
|
|
status: "confirmed",
|
|
domain,
|
|
datePrecision: "month",
|
|
occurredFrom,
|
|
occurredTo: null,
|
|
eventKind,
|
|
};
|
|
}
|
|
|
|
const D10_STYLE: CandidateContrastPacket["probes"][number] = {
|
|
probeId: "contrast:varga.d10.巨蟹座/狮子座",
|
|
candidateSetVersion: "05:00-05:20",
|
|
question: "平时做事,你更接近下面哪一种?",
|
|
expectedOutcomes: [
|
|
{ outcomeId: "yes", supportsCandidateIds: ["05:00"], conflictsCandidateIds: ["05:20"] },
|
|
{ outcomeId: "weak_yes", supportsCandidateIds: ["05:20"], conflictsCandidateIds: ["05:00"] },
|
|
],
|
|
candidateSplitHash: "varga.d10.巨蟹座/狮子座",
|
|
informationGain: 1.4,
|
|
sourceFeatures: [{ technique: "D10", calculationResultId: null }],
|
|
domain: "career",
|
|
year: null,
|
|
semanticKey: "varga.d10.巨蟹座/狮子座",
|
|
choiceKind: "varga_style",
|
|
styleOptions: [
|
|
{ label: "做事以照顾人为主,在意团队里的感受", answerClass: "yes", sign: "巨蟹座" },
|
|
{ label: "习惯带头,也不排斥站到台前", answerClass: "weak_yes", sign: "狮子座" },
|
|
],
|
|
};
|
|
|
|
test("existenceProbeAsked treats the same career year and nearby years as already asked", () => {
|
|
const asked = ["career.2018.05.dasha_boundary"];
|
|
assert.equal(existenceProbeAsked(asked, "career", 2018), true);
|
|
assert.equal(existenceProbeAsked(asked, "career", 2017), true);
|
|
assert.equal(existenceProbeAsked(asked, "career", 2019), true);
|
|
assert.equal(existenceProbeAsked(asked, "career", 2020), false);
|
|
assert.equal(existenceProbeAsked(asked, "finance", 2018), false);
|
|
});
|
|
|
|
test("remaining reverse-verify probes drop same-domain nearby years after a month probe", () => {
|
|
const remaining = remainingReverseVerifyProbes(
|
|
[
|
|
existenceProbe("career", 2018, { month: 5 }),
|
|
existenceProbe("career", 2018, { source: "dasha_activation" }),
|
|
existenceProbe("career", 2017, { month: 5 }),
|
|
existenceProbe("career", 2019, { month: 5 }),
|
|
existenceProbe("career", 2020, { month: 5 }),
|
|
],
|
|
[],
|
|
new Set(),
|
|
new Set(["career.2018.05.dasha_boundary"]),
|
|
);
|
|
const years = remaining.filter((item) => item.domain === "career").map((item) => item.year);
|
|
assert.equal(years.includes(2017), false);
|
|
assert.equal(years.includes(2018), false);
|
|
assert.equal(years.includes(2019), false);
|
|
assert.equal(years.includes(2020), true);
|
|
});
|
|
|
|
test("datedLedgerAnchor names the confirmed same-domain month", () => {
|
|
const anchor = datedLedgerAnchor([
|
|
dated("e-career-month", "career", "career_entry", "2018-07-01"),
|
|
], "career");
|
|
assert.ok(anchor);
|
|
assert.equal(anchor?.label, "2018 年 7 月");
|
|
assert.equal(datedLedgerAnchor([
|
|
dated("e-edu", "education", "education_start", "2016-09-01"),
|
|
], "career"), null);
|
|
});
|
|
|
|
test("unanchored D10 varga_style cards are dropped; anchored cards mention the ledger month", () => {
|
|
const baseEvidence = [
|
|
dated("e-edu", "education", "education_start", "2016-09-01"),
|
|
dated("e-edu-2", "education", "education_completion", "2020-06-01"),
|
|
dated("e-rel", "relationship", "relationship_start", "2024-05-01"),
|
|
dated("e-fin", "finance", "finance_loss", "2021-01-01"),
|
|
];
|
|
const packet = {
|
|
candidateSetVersion: "05:00-05:20",
|
|
vargaDifferences: [] as const,
|
|
probes: [D10_STYLE],
|
|
};
|
|
const unanchored = buildMethodFollowupPlan({
|
|
evidence: baseEvidence,
|
|
contrastPacket: packet,
|
|
candidatesSeparated: false,
|
|
});
|
|
assert.equal(
|
|
unanchored.dropped_probes.some((item) => item.reason === "unanchored_varga_style"),
|
|
true,
|
|
);
|
|
assert.notEqual(unanchored.next_followup?.semantic_key, D10_STYLE.semanticKey);
|
|
|
|
const anchored = buildMethodFollowupPlan({
|
|
evidence: [...baseEvidence, dated("e-career", "career", "career_entry", "2018-07-01")],
|
|
contrastPacket: packet,
|
|
candidatesSeparated: false,
|
|
});
|
|
assert.equal(anchored.next_followup?.semantic_key, D10_STYLE.semanticKey);
|
|
assert.equal(anchored.next_followup?.choice_kind, "varga_style");
|
|
assert.match(anchored.next_followup?.user_prompt_hint ?? "", /2018 年 7 月/);
|
|
assert.doesNotMatch(anchored.next_followup?.choice_frame?.prompt ?? "", /2018/);
|
|
});
|
|
|
|
test("after a D9-style answer the compare request body stays legal", () => {
|
|
const hash = "04:45-05:15:04:47,04:51,04:53,04:59,05:00,05:06,05:08,05:13,05:15:varga.d9.04:47|04:51/05:00|05:06|04:59|04:53/05:08|05:13|05:15";
|
|
assert.equal(hash.length, 128);
|
|
const receipt = {
|
|
inference_state: {
|
|
answered_probes: [{
|
|
probe_id: "contrast:varga.d9.相处",
|
|
semantic_key: "varga.d9.巨蟹座/狮子座",
|
|
candidate_split_hash: hash,
|
|
answer_class: "yes",
|
|
classified_from: "choice",
|
|
}],
|
|
},
|
|
};
|
|
const asked = askedSemanticKeysForEngine(receipt, []);
|
|
assert.equal(asked.includes(hash), false);
|
|
assert.ok(asked.every((key) => key.length <= 120 && !key.includes(":varga.")));
|
|
const body = engineRequestBody({
|
|
baselineBirthSnapshot: {
|
|
birth_date: "1997-08-08",
|
|
latitude: 36.42,
|
|
longitude: 114.21,
|
|
timezone_offset: 8,
|
|
},
|
|
candidateRange: { start_time: "04:45", end_time: "05:15" },
|
|
events: toEngineEvents([{
|
|
id: "00000000-0000-4000-8000-000000000001",
|
|
sourceTurnId: "33333333-3333-4333-8333-333333333333",
|
|
subject: "self",
|
|
eventKind: "education_start",
|
|
domain: "education",
|
|
occurredFrom: "2016-09-01",
|
|
occurredTo: "2016-09-30",
|
|
datePrecision: "month",
|
|
summary: "大学入学",
|
|
}]),
|
|
askedProbeKeys: asked,
|
|
});
|
|
const keys = (body.asked_probe_keys as string[] | undefined) ?? [];
|
|
assert.ok(keys.every((key) => key.length <= 120 && !key.includes(":varga.")));
|
|
});
|