Files
Jyotisha/frontend/tests/rectification-precision-gate-20260916.test.ts
T
jesse-ux cfb41daf3d
Independent Staging Quality Gate / validate (push) Failing after 6m28s
Independent Staging Quality Gate / publish (push) Skipped
feat(rectification): 出卡加精度门槛,补经历改成系统点名
宽度超过 10 分钟或头名并列时不再出交付卡,改为按大运边界逐条问、
用类型芯片和年/月选择器录入。跳过的线换问法再问一次;答「这类事
都没有过」的不再问。用户说「没有了」仍立刻给目前范围。Skill 10.0.27。

BUG-740~743
2026-09-16 18:35:27 +08:00

132 lines
4.3 KiB
TypeScript

import assert from "node:assert/strict";
import test from "node:test";
import { RECTIFICATION_POLICY } from "../src/lib/rectification-policy.ts";
import {
decideRectification,
mayDeliverOnPrecision,
publicCanAdopt,
sessionOutcomeAllowsDelivery,
} from "../src/lib/rectification-agentic/core/rectification-decision.ts";
import { computePrecisionGateMet } from "../src/lib/rectification-agentic/core/precision-gate.ts";
import { RANGE_DELIVERY_TIE_PERCENT } from "../src/lib/rectification-agentic/user-copy.ts";
import { OPEN_ENGINE_CAPABILITY_CEILING } from "./rectification-v9-test-support.ts";
const TIED_FIVE = [
{ time: "04:51", score: 13 },
{ time: "04:53", score: 13 },
{ time: "04:56", score: 13 },
{ time: "04:58", score: 13 },
{ time: "05:11", score: 13 },
] as const;
function input(overrides: Partial<Parameters<typeof decideRectification>[0]> = {}) {
return {
engineCeiling: OPEN_ENGINE_CAPABILITY_CEILING,
methodCoverageAll: true,
trainingGateOpen: true,
candidateScores: TIED_FIVE.map((item) => ({ time: item.time, score: item.score })),
holdoutValidation: "unavailable" as const,
datedEventCount: 5,
datedDomainCount: 3,
discriminatorProbe: null,
targetedCollectExhausted: true,
refreshExhausted: true,
inferenceCredibleRange: ["04:51", "05:11"] as const,
openingCandidateRange: ["04:45", "05:15"] as const,
...overrides,
};
}
test("policy defines deliveryMaxWidthMinutes once", () => {
assert.equal(RECTIFICATION_POLICY.deliveryMaxWidthMinutes, 10);
assert.equal(RANGE_DELIVERY_TIE_PERCENT, 3);
});
test("precision gate requires width, display gap, and no exact tie", () => {
assert.equal(computePrecisionGateMet({
range: ["04:51", "05:11"],
topTwoPercents: [26, 26],
tiedForFirst: true,
}), false);
assert.equal(computePrecisionGateMet({
range: ["04:51", "04:59"],
topTwoPercents: [40, 35],
tiedForFirst: false,
}), true);
assert.equal(computePrecisionGateMet({
range: ["04:51", "04:59"],
topTwoPercents: [26, 26],
tiedForFirst: true,
}), false);
});
test("20 minute tied range keeps collecting with a guided question", () => {
const decision = decideRectification(input({
precisionGateMet: false,
guidedCollectExhausted: false,
}));
assert.equal(decision.nextAction, "ask_fact_collection");
assert.equal(decision.canOfferRange, false);
assert.equal(sessionOutcomeAllowsDelivery(decision.sessionOutcome), false);
assert.equal(publicCanAdopt(decision), false);
});
test("8 minute range with a 5 point lead delivers", () => {
const decision = decideRectification(input({
candidateScores: [
{ time: "04:51", score: 20 },
{ time: "04:53", score: 15 },
{ time: "04:56", score: 10 },
],
inferenceCredibleRange: ["04:51", "04:59"],
precisionGateMet: true,
guidedCollectExhausted: false,
targetedCollectExhausted: true,
refreshExhausted: true,
}));
assert.equal(decision.canOfferRange, true);
assert.equal(sessionOutcomeAllowsDelivery(decision.sessionOutcome), true);
});
test("8 minute exact tie keeps collecting", () => {
const decision = decideRectification(input({
candidateScores: [
{ time: "04:51", score: 13 },
{ time: "04:53", score: 13 },
],
inferenceCredibleRange: ["04:51", "04:59"],
precisionGateMet: false,
guidedCollectExhausted: false,
}));
assert.equal(decision.nextAction, "ask_fact_collection");
assert.equal(decision.canOfferRange, false);
});
test("gate unmet but guided collect exhausted still delivers", () => {
const decision = decideRectification(input({
precisionGateMet: false,
guidedCollectExhausted: true,
}));
assert.equal(decision.canOfferRange, true);
assert.equal(sessionOutcomeAllowsDelivery(decision.sessionOutcome), true);
});
test("userStopped delivers even when the precision gate is unmet", () => {
const decision = decideRectification(input({
userStopped: true,
precisionGateMet: false,
guidedCollectExhausted: false,
}));
assert.equal(decision.canOfferRange, true);
assert.equal(sessionOutcomeAllowsDelivery(decision.sessionOutcome), true);
});
test("omitted precision flags keep the helper path delivering", () => {
assert.equal(mayDeliverOnPrecision({
methodCoverageAll: true,
candidateScores: [],
engineCeiling: OPEN_ENGINE_CAPABILITY_CEILING,
}), true);
});