From 96917a3e59cadaa1cfc2f67b3096914872da3baf Mon Sep 17 00:00:00 2001 From: Jesse_Chen Date: Sun, 26 Jul 2026 00:02:11 +0800 Subject: [PATCH] fix: reconcile consultation mode with saved birth time --- docs/BUG_HISTORY.md | 15 +++++++ frontend/src/app/api/consult/route.ts | 2 +- frontend/src/app/page.tsx | 36 ++++++++++------ .../src/lib/consultation-route-service.ts | 41 ++++++++++++++----- frontend/src/lib/guided-jyotish-topics.ts | 12 ++++++ .../tests/consultation-entrypoint.test.ts | 4 +- .../tests/consultation-route-service.test.ts | 36 ++++++++++++---- frontend/tests/starter-questions.test.ts | 20 ++++++++- 8 files changed, 131 insertions(+), 35 deletions(-) diff --git a/docs/BUG_HISTORY.md b/docs/BUG_HISTORY.md index f3818d45..510ea263 100644 --- a/docs/BUG_HISTORY.md +++ b/docs/BUG_HISTORY.md @@ -1368,3 +1368,18 @@ - 防复发:零证据首轮不得执行分钟级技术计算或模型调用;非关键会话同步不得阻塞已持久化 case 的首轮交互;可选 handoff 读取必须由实际 handoff 状态触发。 - 相关记录:BUG-055、BUG-065、BUG-067 - 修复版本:待提交(本地可测) + +## BUG-073 | 咨询入口与持久化出生时间能力不一致 + +- 状态:resolved +- 首次发现:2026-07-25 +- 最近更新:2026-07-25 +- 影响面:首页状态文案、每日观察入口、推荐初始问题、`/api/consult` 出生时间模式判定 +- 用户现象:一类用户没有具体出生分钟,首页却仍诱导个人星盘问题;另一类用户已经保存准确到分钟的填报时间,旧标签页或旧客户端仍可能把咨询请求标为 `general_no_birth_time`,随后错误提示当前一般咨询模式不能生成个人星盘结论。 +- 触发条件:无分钟资料仍出现个人入口,或数据库已保存合法 `family_exact` / `hospital_record` / `approximate` 填报分钟,但客户端咨询模式停留在旧的 `general_no_birth_time`。 +- 根因:首页没有复用出生时间路由结果来约束入口能力;同时 `/api/consult` 只在客户端请求星盘模式时加载 profile,收到 `general_no_birth_time` 时完全信任客户端状态,没有用持久化资料纠正陈旧模式。 +- 修复:首页复用 `resolveBirthTimeConsultationRoute()`:无具体分钟时只显示一般知识文案和问题,有合法填报分钟时保留个人星盘入口。服务端对一般咨询请求也 best-effort 读取 profile;若持久化资料含合法未校正填报分钟则提升为 `unverified_birth_time`,若为 `confirmed` 且有合法 active time 则提升为 `verified_chart`,并继续由服务端 profile 构建星盘输入。`period_only` / `unknown` 仍保持一般咨询,不虚构分钟,也不把用户填报时间伪装成已校正时间。 +- 验证:聚焦测试覆盖无分钟首页入口、陈旧 general 请求被准确分钟 profile 提升为 `unverified_birth_time`,以及无具体分钟仍保持 `general_no_birth_time`;目标 ESLint、Webpack 构建与 `git diff --check` 通过。 +- 防复发:首页可点击入口必须与 `resolveBirthTimeConsultationRoute()` 的能力结果一致;服务端不得把客户端咨询模式当作出生资料真源,具体填报分钟必须进入 `unverified_birth_time`,只有 `confirmed + active_birth_time` 才能进入 `verified_chart`。 +- 相关记录:BUG-009 +- 修复版本:待提交(本地可测) diff --git a/frontend/src/app/api/consult/route.ts b/frontend/src/app/api/consult/route.ts index b76315a2..e2c798ea 100644 --- a/frontend/src/app/api/consult/route.ts +++ b/frontend/src/app/api/consult/route.ts @@ -439,7 +439,7 @@ export async function POST(request: Request) { try { const { history } = parsed.data; const name = prepared.serverChart?.name ?? parsed.data.name; - const consultationMode: ConsultationBirthTimeMode = parsed.data.consultationMode; + const consultationMode: ConsultationBirthTimeMode = prepared.consultationMode; if (!shouldRunBirthChartWorkflow(consultationMode)) { const result = await getGeneralJyotishAgent(selectedModel).stream([ { diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx index 098d9da0..88753e40 100644 --- a/frontend/src/app/page.tsx +++ b/frontend/src/app/page.tsx @@ -75,7 +75,7 @@ import { isGuidedBirthTimePreview, previewRectificationJourney, } from "@/lib/birth-time-guided-preview"; -import { defaultGuidedJyotishTopics } from "@/lib/guided-jyotish-topics"; +import { defaultGuidedJyotishTopics, generalGuidedJyotishTopics } from "@/lib/guided-jyotish-topics"; import { keepFocusWithin } from "@/lib/focus-trap"; import { chatMessageViews, type ChatMessage } from "@/lib/chat-message-view"; import { writeChatSession } from "@/lib/chat-session-write-contract"; @@ -1123,6 +1123,9 @@ export default function Home() { }, [accountId, profile]); const profileComplete = isProfileComplete(profile); + const birthTimeRoute = resolveBirthTimeConsultationRoute(profile, birthTimeConsultationConsent, activeSessionId); + const personalChartAvailable = birthTimeRoute.kind === "consult" && birthTimeRoute.mode !== "general_no_birth_time"; + const starterThemes = personalChartAvailable ? themes : generalGuidedJyotishTopics; const dailyStarlanguage = dailyStarlanguageCard ?? (profileComplete ? buildDailyStarlanguageCard(profile) : null); const onboardingPending = profileComplete && !onboarding && !onboardingError; const currentOnboardingMessage = onboardingJustCompleted @@ -1137,8 +1140,9 @@ export default function Home() { const shouldStreamOnboarding = !profileComplete; const presetMessageFinished = !shouldStreamOnboarding || presetMessageLength >= currentOnboardingMessage.length; const onboardingCardReady = presetMessageFinished || birthTimeAssessmentPhase !== null; - const starterSuggestions = themes.map((theme) => onboarding?.suggestions.find((item) => item.theme === theme.id) - ?? { theme: theme.id, text: theme.prompt }); + const starterSuggestions = starterThemes.map((theme) => personalChartAvailable + ? onboarding?.suggestions.find((item) => item.theme === theme.id) ?? { theme: theme.id, text: theme.prompt } + : { theme: theme.id, text: theme.prompt }); const starterHomeVisible = profileComplete && presetMessageFinished && !onboardingPending @@ -2031,7 +2035,11 @@ export default function Home() { } function draftDailyStarlanguageQuestion() { - chooseSuggestedQuestion("深入看今日", "timing", "daily_starlanguage"); + chooseSuggestedQuestion( + personalChartAvailable ? "深入看今日" : "印度占星通常如何观察每日趋势?", + "timing", + personalChartAvailable ? "daily_starlanguage" : null, + ); } function synchronizeRectificationQuestion( @@ -3109,7 +3117,7 @@ export default function Home() { ? (consultationPhase === "undo" ? "即将发送,可撤回" : activeStreamingText ? "正在回答" : "正在核对星盘信息") : rectificationSurfaceOpen || (!profileComplete && onboardingStep === "rectification") ? "正在校正出生时间" - : "基于星盘证据回答"} + : personalChartAvailable ? "基于星盘证据回答" : "回答一般占星知识"}