import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import test from "node:test"; import { ACCEPTED_RANGE_READING_INSTRUCTION, createBirthTimeModeOutputGuard, } from "../src/lib/consultation-birth-time-mode.ts"; import { RANGE_READING_COPY } from "../src/lib/rectification-agentic/v9/adopt-narration.ts"; import { createConsultationRuntimeState, createWindowConsultationTools, } from "../src/mastra/consultation-tools.ts"; import { consultationWorkflowReceipt, minuteSensitiveThemesFromBirthTimeSensitivity, } from "../src/mastra/consultation-workflow.ts"; const toolContext = { observe: { span: async (_name: string, fn: () => Promise) => fn(), log() {} }, } as never; test("theme_sensitivity maps sensitive keys onto the consultation answer policy", () => { const themes = minuteSensitiveThemesFromBirthTimeSensitivity({ theme_sensitivity: { career: { status: "stable" }, marriage: { status: "sensitive" }, wealth: { status: "stable" }, }, }); assert.deepEqual(themes, ["marriage"]); const receipt = consultationWorkflowReceipt({ consumer_context: { route: "career", core_status: "ready", available_layers: [], missing_route_layers: [], hard_blockers: [], answer_policy: { can_answer_direction: true, can_answer_precise_timing: true, minute_sensitive_themes: ["marriage"], }, }, }); assert.deepEqual(receipt.minuteSensitiveThemes, ["marriage"]); }); test("minute-sensitive or timing themes use the precise-timing output guard", () => { const text = "Rahu 大运为 2013年11月21日 至 2031年11月22日。"; const marriage = createBirthTimeModeOutputGuard("verified_chart", true, { currentTheme: "marriage", minuteSensitiveThemes: ["marriage"], })(text); assert.match(marriage, /具体时间已省略/); const career = createBirthTimeModeOutputGuard("verified_chart", true, { currentTheme: "career", minuteSensitiveThemes: ["marriage"], })(text); assert.equal(career, text); const timing = createBirthTimeModeOutputGuard("verified_chart", true, { currentTheme: "timing", minuteSensitiveThemes: [], })(text); assert.match(timing, /具体时间已省略/); }); test("declared window consultation merges range-reading themes and says it is a coarse look", async () => { const state = createConsultationRuntimeState(); const tools = createWindowConsultationTools({ userId: "u", sessionId: "s", requestId: "r-window", consultationMode: "declared_birth_window", declaredWindow: { name: "测试", toolInput: { year: 1997, month: 8, day: 8, city: "邯郸", lat: 36.4, lon: 114.2, tz: 8, ayanamsa: "raman", rangeStart: "14:00", rangeEnd: "18:00", }, truth: { birthDate: "1997-08-08", birthTimeSource: "period_only", birthTimePeriod: "afternoon", birthTimeStatus: "reported", wrapsMidnight: false, placeLabel: "邯郸", placeCodes: { countryCode: "CN", provinceCode: null, cityCode: null, districtCode: null, }, placeId: null, placeType: null, placeProvider: null, timezoneId: null, timezoneSource: null, latitude: 36.4, longitude: 114.2, timezoneOffset: 8, }, }, state, fetchWindowChart: async () => ({ declared_range: { start: "14:00", end: "18:00", wraps_midnight: false }, probe_count: 3, probes: [ { clock: "14:00", role: "range_start" as const }, { clock: "16:00", role: "interior" as const }, { clock: "18:00", role: "range_end" as const }, ], stable_layers: { planet_signs: { sun: "Cancer" } }, varying_layers: { ascendant_signs: ["Libra", "Scorpio"] }, blocked_layers: ["precise-timing"], answer_policy: { can_answer_direction: true, can_answer_precise_timing: false as const, birth_time_confidence: "declared_window" as const, candidate_is_confirmed: false as const, }, result_hash: "fictional-window", }), runRangeReading: async () => ({ stableThemes: ["career"], sensitiveThemes: ["marriage"], claimBoundary: RANGE_READING_COPY.boundary, themeSensitivity: {}, window: null, }), }); const result = await tools["run-jyotish-window-consultation"].execute!( { question: "婚姻如何" }, toolContext, ) as { answer_policy: { minute_sensitive_themes: string[] }; evidence_contract: { user_facing_limitation: string }; }; assert.deepEqual(result.answer_policy.minute_sensitive_themes, ["marriage"]); assert.match(result.evidence_contract.user_facing_limitation, /这只是粗看/); assert.deepEqual(state.workflowReceipt?.minuteSensitiveThemes, ["marriage"]); const route = readFileSync(new URL("../src/app/api/consult/route.ts", import.meta.url), "utf8"); assert.match(route, /这只是粗看/); assert.match(route, /ACCEPTED_RANGE_READING_INSTRUCTION/); assert.match(ACCEPTED_RANGE_READING_INSTRUCTION, /不是已确认的唯一出生分钟/); });