From 878ff96dc5e89c3ce7a57c68528e8729b8440e65 Mon Sep 17 00:00:00 2001 From: 732642856 <732642856@qq.com> Date: Tue, 21 Jul 2026 14:40:07 +0800 Subject: [PATCH] feat: add guided Jyotish topic evidence cards --- frontend/src/app/page.tsx | 9 ++-- frontend/src/lib/guided-jyotish-topics.ts | 50 +++++++++++++++++++++++ frontend/tests/starter-questions.test.ts | 15 +++++++ 3 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 frontend/src/lib/guided-jyotish-topics.ts diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx index f1023f29..3867440e 100644 --- a/frontend/src/app/page.tsx +++ b/frontend/src/app/page.tsx @@ -41,6 +41,7 @@ import { isGuidedBirthTimePreview, previewRectificationJourney, } from "@/lib/birth-time-guided-preview"; +import { defaultGuidedJyotishTopics } from "@/lib/guided-jyotish-topics"; import { keepFocusWithin } from "@/lib/focus-trap"; import { chatMessageViews, type ChatMessage } from "@/lib/chat-message-view"; import { @@ -155,11 +156,7 @@ type PendingConsultation = { const undoWindowMs = 2_500; const china = chinaLocations.country; -const themes: Array<{ id: Exclude; label: string; prompt: string }> = [ - { id: "career", label: "事业", prompt: "未来一年,事业和收入该关注什么?" }, - { id: "marriage", label: "关系", prompt: "我的关系模式是什么?" }, - { id: "timing", label: "时运", prompt: "未来哪些阶段值得把握?" }, -]; +const themes = defaultGuidedJyotishTopics; const accountDialogTitles = { profile: "个人资料", @@ -2482,7 +2479,7 @@ export default function Home() { const theme = themes.find((candidate) => candidate.id === item.theme); return ( ); diff --git a/frontend/src/lib/guided-jyotish-topics.ts b/frontend/src/lib/guided-jyotish-topics.ts new file mode 100644 index 00000000..cde6ee58 --- /dev/null +++ b/frontend/src/lib/guided-jyotish-topics.ts @@ -0,0 +1,50 @@ +import type { ConsultationTheme } from "./consultation-workflow-request"; + +export type GuidedJyotishTopic = { + id: ConsultationTheme; + label: string; + prompt: string; + strictWorkflowRoute: string; + evidencePreview: string[]; + confidenceCap: "low" | "medium"; + claimBoundary: string; +}; + +export const defaultGuidedJyotishTopics: GuidedJyotishTopic[] = [ + { + id: "career", + label: "事业", + prompt: "未来一年,事业和收入该关注什么?", + strictWorkflowRoute: "career", + evidencePreview: ["D1", "D10", "A10", "Vimshottari", "Narayana", "Transit"], + confidenceCap: "medium", + claimBoundary: "输出职业结构与阶段判断;具体日/月只作为候选窗口。", + }, + { + id: "marriage", + label: "关系", + prompt: "我的关系模式是什么?", + strictWorkflowRoute: "marriage", + evidencePreview: ["D1", "D9", "7宫", "DK", "UL", "Vimshottari", "Narayana"], + confidenceCap: "medium", + claimBoundary: "输出关系模式与宽窗口;不承诺某日必然发生事件。", + }, + { + id: "wealth", + label: "财富", + prompt: "我的财富增长方式和风险点是什么?", + strictWorkflowRoute: "wealth", + evidencePreview: ["D1", "D2", "D11", "2/11宫", "财富 Yoga", "Ashtakavarga"], + confidenceCap: "medium", + claimBoundary: "输出财富结构和风险类型;不替代投资建议。", + }, + { + id: "timing", + label: "时运", + prompt: "未来哪些阶段值得把握?", + strictWorkflowRoute: "timing", + evidencePreview: ["Dasha", "Narayana", "Transit", "Varga"], + confidenceCap: "low", + claimBoundary: "精确月/日仍是探索性候选,未通过独立 holdout 前不升级。", + }, +]; diff --git a/frontend/tests/starter-questions.test.ts b/frontend/tests/starter-questions.test.ts index d317cd34..044d30bf 100644 --- a/frontend/tests/starter-questions.test.ts +++ b/frontend/tests/starter-questions.test.ts @@ -5,6 +5,7 @@ import test from "node:test"; const pageSource = readFileSync(new URL("../src/app/page.tsx", import.meta.url), "utf8"); const globalStyles = readFileSync(new URL("../src/app/globals.css", import.meta.url), "utf8"); const appSidebarSource = readFileSync(new URL("../src/components/app-sidebar.tsx", import.meta.url), "utf8"); +const guidedTopicsSource = readFileSync(new URL("../src/lib/guided-jyotish-topics.ts", import.meta.url), "utf8"); function sourceBetween(source: string, startMarker: string, endMarker: string) { const start = source.indexOf(startMarker); @@ -28,6 +29,20 @@ test("keeps starter questions visible while the user edits a draft", () => { assert.doesNotMatch(starterVisibilityGuard, /\bdraft\b/); }); +test("default starter questions are guided Jyotish topics with evidence and claim boundaries", () => { + assert.match(pageSource, /defaultGuidedJyotishTopics/); + assert.match(pageSource, /theme\.evidencePreview\.join/); + assert.match(pageSource, /theme\.claimBoundary/); + assert.match(guidedTopicsSource, /strictWorkflowRoute/); + assert.match(guidedTopicsSource, /evidencePreview/); + assert.match(guidedTopicsSource, /confidenceCap/); + assert.match(guidedTopicsSource, /claimBoundary/); + assert.match(guidedTopicsSource, /D10/); + assert.match(guidedTopicsSource, /D9/); + assert.match(guidedTopicsSource, /Ashtakavarga/); + assert.match(guidedTopicsSource, /独立 holdout/); +}); + test("keeps follow-up suggestions visible while the user edits a draft", () => { // Given: the follow-up suggestion block and its render guard. const suggestionGuard = sourceBetween(