fix(health): complete consultation evidence contract

This commit is contained in:
Jesse_Chen
2026-09-04 03:29:34 +08:00
parent cf6c8a9c36
commit 837bd0820d
4 changed files with 185 additions and 4 deletions
@@ -754,6 +754,90 @@ test("generatePersonalReport returns a ready document that passes the server par
assert.equal(reparsed.ok, true);
});
test("generatePersonalReport keeps health writer output non-medical and parameter-sensitive", async () => {
const base = bundleV2Fixture();
const d1 = base.charts.find((chart) => chart.id === "D1");
const chartTemplate = base.charts.find((chart) => chart.id === "D10");
assert.ok(d1);
assert.ok(chartTemplate);
const techniques = ["D1", "D6", "D8", "D30", "Vimshottari"] as const;
const techniqueIds = techniques.map((name) => `ev-tech-${name.toLowerCase()}`);
const bundle = finalizeReportEvidenceBundleV2({
...withoutBundleHash(base),
requestedThemes: ["health_pressure"],
charts: [
d1,
...(["D6", "D8", "D30"] as const).map((id) => ({
...chartTemplate,
id,
title: `${id} health divisional chart`,
})),
],
claimCards: [{
id: "ev-claim-health-pressure",
theme: "health_pressure",
section: "健康压力(非医疗)",
conclusion: "D6/D8/D30 与 Vimshottari 只支持非医疗的压力与恢复节奏观察。",
supportingFacts: techniqueIds.map((evidenceRef, index) => ({
id: `ev-fact-health-${index + 1}`,
label: evidenceRef,
value: "该层已执行并仅用于非医疗叙事。",
evidenceRef,
status: "verified" as const,
})),
counterFacts: [],
executedTechniqueRefs: techniqueIds,
assertionLevel: "parameter_sensitive",
timingBoundary: null,
verificationQuestions: [],
}],
blockedSections: [],
executionLedger: techniqueIds.map((id, index) => ({
id,
technique: techniques[index],
status: "verified" as const,
executed: true,
note: "健康主题最低证据已执行",
})),
evidenceRefs: techniqueIds.map((id, index) => ({
id,
technique: techniques[index],
status: "verified" as const,
})),
});
const calls = { count: 0 };
const result = await generatePersonalReport({
reportId: "22222222-2222-4222-8222-222222222222",
bundle,
depth: "standard",
agent: fakeAgent(agentOutput({
thematicNarrative: [{
id: "theme-health_pressure",
theme: "health_pressure",
title: "健康压力(非医疗)",
narrative: "本段仅描述压力负荷与恢复节奏,不构成医疗诊断或治疗建议。",
actions: ["如有持续不适,请咨询合格医疗专业人员。"],
caveats: ["非医疗边界:占星内容不能替代专业诊疗。"],
claimStatus: "parameter_sensitive",
evidenceRefs: techniqueIds,
}],
}), calls),
now: () => new Date("2026-09-03T00:00:00.000Z"),
});
assert.equal(calls.count, 1);
assert.equal(bundle.claimCards[0].assertionLevel, "parameter_sensitive");
assert.equal(result.status, "ready");
if (result.status !== "ready") return;
const parsed = safeParseServerReportDocument(result.document);
assert.equal(parsed.ok, true);
if (!parsed.ok) return;
const health = parsed.document.thematicNarrative.find((section) => section.id === "theme-health_pressure");
assert.ok(health);
assert.match(`${health.narrative} ${health.caveats.join(" ")}`, /非医疗|不构成医疗/);
assert.equal(health.claimStatus, "parameter_sensitive");
});
test("generatePersonalReport fails with report_guard_rejected on guard rejection", async () => {
const bundle = bundleV2Fixture();
const result = await generatePersonalReport({