fix(home): request the daily card on the same condition that renders it #37

Open
jesse wants to merge 0 commits from codex/fix-daily-starlanguage-guard-20260818 into staging
Owner

现象

staging 上出生资料完整的账号打开首页,「今日星语」卡片永久停在「正在结合你的星盘写今天的星语。」,Agent 写的文案从不出现。同时首页 hero 标题仍是静态池里的一句,按时段问候没生效;/api/onboarding 返回的 Agent 欢迎语在页面上没有任何渲染点。

根因

  1. 每日星语 effect 的守卫是 birthTimeDisplayState(profile) 为真就 return,而该函数恰好在出生时间为 candidate/accepted/confirmed 时返回非 null。条件语义与卡片渲染条件 personalChartAvailable 相反,请求从未发出。守卫早于 Agent 化改造,此前被客户端写死兜底遮住;BUG-265 删兜底、留守卫,暴露成永久等待态。
  2. /api/chart 是唯一没有 .catch() 的引擎调用,engineTimeoutMs 仅 8 秒、agentTimeoutMs 仅 30 秒,而线上实测端到端 30.6 秒;失败原因被压成同一个字符串。
  3. 首页存在三套问候实现,用户要求的按时段问候在没被 hero 使用的那一套里。

改动

  • 取数条件与渲染条件对齐为 personalChartAvailable,失败后延迟 5 秒重试一次,卸载清理定时器。
  • /api/chart 补 catch;失败原因拆为 chart_unavailable / model_unavailable / agent_generation_failed;引擎超时 20 秒、模型超时 45 秒,仍在 maxDuration = 60 内。
  • createStartGreeting 拆出 createStartGreetingParts,hero 第一行用 salutation、h1 用 question;删除 starter-prompt.tsgreetingForHour
  • 不再覆盖 Agent 欢迎语,onboarding.greeting 落到 hero 说明行,原静态文案作兜底。

验证

  • 线上先证明后端可用:带登录 Cookie 直调 staging /api/daily-starlanguage,冷路径 30.6 秒返回真实 {trend, action, caution},二次 1.6 秒命中 agent_cache/api/health 确认部署 SHA 即 origin/staging 头部、jyotishApi ok,排除部署落后与引擎故障。
  • 新增 6 条回归:取数条件必须等于 personalChartAvailable 且源码不得再出现 birthTimeDisplayState(profile)、失败重试一次且清理定时器、/api/chart 必须带 catch 且三种失败原因可辨、两个超时预算有下限断言、hero salutation/question 拆分与 Agent 欢迎语落点、禁止静态标题池复活。
  • 前端非数据库套件 1711/1724 通过(13 个失败均为本机 Docker/PostgreSQL fixture,与本次无关);tsc --noEmit、改动文件 ESLint、next build 均通过。

未验证

没有在浏览器里看过修好后的首页——本机无 Python 引擎与模型密钥,起不了完整栈。卡片从 pending 到 ready 的观感、一次重试是否足够、hero 换行后的排版,需要本 PR 合入 staging 发布后确认。已记入 docs/BUG_HISTORY.md BUG-267。

## 现象 staging 上出生资料完整的账号打开首页,「今日星语」卡片永久停在「正在结合你的星盘写今天的星语。」,Agent 写的文案从不出现。同时首页 hero 标题仍是静态池里的一句,按时段问候没生效;`/api/onboarding` 返回的 Agent 欢迎语在页面上没有任何渲染点。 ## 根因 1. 每日星语 effect 的守卫是 `birthTimeDisplayState(profile)` 为真就 return,而该函数恰好在出生时间为 `candidate`/`accepted`/`confirmed` 时返回非 null。条件语义与卡片渲染条件 `personalChartAvailable` 相反,请求从未发出。守卫早于 Agent 化改造,此前被客户端写死兜底遮住;BUG-265 删兜底、留守卫,暴露成永久等待态。 2. `/api/chart` 是唯一没有 `.catch()` 的引擎调用,`engineTimeoutMs` 仅 8 秒、`agentTimeoutMs` 仅 30 秒,而线上实测端到端 30.6 秒;失败原因被压成同一个字符串。 3. 首页存在三套问候实现,用户要求的按时段问候在没被 hero 使用的那一套里。 ## 改动 - 取数条件与渲染条件对齐为 `personalChartAvailable`,失败后延迟 5 秒重试一次,卸载清理定时器。 - `/api/chart` 补 catch;失败原因拆为 `chart_unavailable` / `model_unavailable` / `agent_generation_failed`;引擎超时 20 秒、模型超时 45 秒,仍在 `maxDuration = 60` 内。 - `createStartGreeting` 拆出 `createStartGreetingParts`,hero 第一行用 salutation、`h1` 用 question;删除 `starter-prompt.ts` 与 `greetingForHour`。 - 不再覆盖 Agent 欢迎语,`onboarding.greeting` 落到 hero 说明行,原静态文案作兜底。 ## 验证 - 线上先证明后端可用:带登录 Cookie 直调 staging `/api/daily-starlanguage`,冷路径 30.6 秒返回真实 `{trend, action, caution}`,二次 1.6 秒命中 `agent_cache`;`/api/health` 确认部署 SHA 即 `origin/staging` 头部、`jyotishApi` ok,排除部署落后与引擎故障。 - 新增 6 条回归:取数条件必须等于 `personalChartAvailable` 且源码不得再出现 `birthTimeDisplayState(profile)`、失败重试一次且清理定时器、`/api/chart` 必须带 catch 且三种失败原因可辨、两个超时预算有下限断言、hero salutation/question 拆分与 Agent 欢迎语落点、禁止静态标题池复活。 - 前端非数据库套件 1711/1724 通过(13 个失败均为本机 Docker/PostgreSQL fixture,与本次无关);`tsc --noEmit`、改动文件 ESLint、`next build` 均通过。 ## 未验证 没有在浏览器里看过修好后的首页——本机无 Python 引擎与模型密钥,起不了完整栈。卡片从 pending 到 ready 的观感、一次重试是否足够、hero 换行后的排版,需要本 PR 合入 staging 发布后确认。已记入 `docs/BUG_HISTORY.md` BUG-267。
jesse added 1 commit 2026-08-18 12:05:37 +08:00
fix(home): request the daily card on the same condition that renders it
Independent Staging Quality Gate / validate (pull_request) Successful in 9m16s
Independent Staging Quality Gate / publish (pull_request) Has been skipped
Independent Staging Quality Gate / validate (push) Successful in 9m44s
Independent Staging Quality Gate / publish (push) Successful in 8m41s
a12f57970b
The daily starlanguage card sat on "正在结合你的星盘写今天的星语。" forever for
every account whose birth time was usable. Its effect bailed out on
birthTimeDisplayState(profile), which returns a value precisely when the
birth time is candidate, accepted or confirmed, so the request went out
only for accounts that had nothing to read. The guard predates the Agent
rewrite and was masked by the written-in client fallback that rewrite
deleted. It now gates on personalChartAvailable, the same fact the card
uses to render personal content, and retries once before admitting that
today has no card.

The route stops letting one engine call take the whole card down
silently: /api/chart fails into a named reason like the other four
layers, and the engine and agent budgets leave room for a cold chart and
an observed 30s generation inside the 60s ceiling.

The home also had three greeting implementations. The hero heading drew
from a static pool while the time-aware greeting lived elsewhere and the
Agent's own greeting was overwritten client-side into a field nothing
rendered. createStartGreeting now exposes its salutation and question
halves, the hero uses both, and the served greeting reaches the hero note.

Co-authored-by: Cursor <cursoragent@cursor.com>
jesse force-pushed codex/fix-daily-starlanguage-guard-20260818 from 4d1a77be9e to a12f57970b 2026-08-18 12:05:37 +08:00 Compare
Some checks are pending
Independent Staging Quality Gate / validate (pull_request) Successful in 9m16s
Independent Staging Quality Gate / publish (pull_request) Has been skipped
Independent Staging Quality Gate / validate (push) Successful in 9m44s
Independent Staging Quality Gate / publish (push) Successful in 8m41s
This branch is already included in the target branch. There is nothing to merge.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin codex/fix-daily-starlanguage-guard-20260818:codex/fix-daily-starlanguage-guard-20260818
git checkout codex/fix-daily-starlanguage-guard-20260818
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: root/Jyotisha#37