Files
Jyotisha/docs/tasks/PROGRESS-starter-greeting-20260917.md
T
Jesse_ChenandClaude Fable 5.1 ff0427cf08
Independent Staging Quality Gate / validate (push) Failing after 6m23s
Independent Staging Quality Gate / publish (push) Skipped
feat(home): 首页开场语改成一行问候,占位符改「想聊什么都可以」
开场语从「称呼行 + 追问句」收成 claude.ai 式的单行问候:时段池、
星期池、回访池按顺序拼成一个数组,按 variantSelection 确定性取一条;
名字为空时跳过带称呼的条目。副标题行与 .starter-salutation 下线,
h1 降到 clamp(24px, 2.8vw, 30px) / line-height 1.25。追问改由输入框
占位符承担。

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JUei7K13cYxLHE3Axe4A45
2026-09-17 15:54:20 +00:00

79 lines
9.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PROGRESS · 首页开场语改成一行问候(2026-09-17)
- 基线 commit`b51e7aff``origin/staging`2026-09-17 取)
- 分支:`codex/starter-greeting-20260917`worktree `.worktrees/starter-greeting-20260917`
- 模式:直接执行(产品拍板,非 Bug,不占 BUG 号,未写 `docs/BUG_HISTORY.md`
- 未推送。
## 1. 做了什么
| # | 改动 | 文件 |
| --- | --- | --- |
| 1 | 开场语从「称呼行 + 追问句」五时段十五条,换成三个池子的单行问候 | `frontend/src/lib/starter-greeting.ts` |
| 2 | `createOnboardingFallbackGreeting` 改成 `欢迎,{名字}` | 同上 |
| 3 | `createStartGreetingParts` 返回 `{ text }`,两个导出都多一个 `hasSessions` 形参 | 同上 |
| 4 | `StarterGreeting` 删掉 `<p className="starter-salutation">`,只留 `<h1 id="starter-heading">{starterGreeting.text}</h1>` | `frontend/src/components/starter-home.tsx` |
| 5 | `hasSessions` 由既有 `sessions` 列表派生(`sessions.some((session) => session.id !== activeSession?.id)`),未新增 `useState` / `useRef` | `frontend/src/app/(app)/page.tsx` |
| 6 | 删 `.starter-salutation` 规则;`.starter-greeting-block h1` 字号 `clamp(26px, 3.2vw, 34px)``clamp(24px, 2.8vw, 30px)``line-height` 1.3 → 1.25`--font-display` / 500 / `-.02em` / `text-wrap: balance` 保持;`.starter-greeting-block` 未动 | `frontend/src/app/globals.css` |
| 7 | 普通输入框占位符末行 `例如:未来半年是否适合换工作?``想聊什么都可以`(其它分支未动) | `frontend/src/lib/rectification-session-composer-guard.ts` |
| 8 | DESIGN / VOICE / CHANGELOG / 任务索引 | `frontend/DESIGN.md``frontend/docs/VOICE.md``CHANGELOG.md``docs/tasks/README.md` |
### 选择规则(实现口径)
给定 `(name, now, variantSelection ∈ [0,1), hasSessions)` 确定性地得到一行:
1. 时段池按 `now.getHours()`(早晨 5–11 / 中午 1114 / 下午 1418 / 傍晚 18–23 / 深夜其余),沿用改动前的划分;
2. 星期池按 `now.getDay()`,只有周一 / 周五 / 周六 / 周日各一条,其余星期不贡献条目;
3. 回访池只在 `hasSessions` 为真时拼进去;
4. 三池按「时段 → 星期 → 回访」顺序拼成一个数组;`name.trim()` 为空时先滤掉所有带 `{名字}` 的条目(时段池每段都留有不带称呼的条目,所以结果永不为空);
5. 下标 `clamp(floor(variantSelection * pool.length), 0, pool.length - 1)`,再把 `{名字}` 换成称呼。
句尾无句号;`今天过得怎么样?``最近还好吗,{名字}` 保留问号。
## 2. 测试数字
| 项 | 基线 `b51e7aff` | 本轮 | 结论 |
| --- | --- | --- | --- |
| `./node_modules/.bin/tsc --noEmit` | 0 错 | 0 错 | 通过 |
| `npm run lint` | 0 error / 118 warning | 0 error / 118 warning | 通过(warning 数量未变,未顺手修) |
| `npm test` 总数 | 3458 | 3465 | +7 |
| `npm test` pass | 3407 | 3414 | +7 |
| `npm test` fail | 36 | 36 | 失败清单逐条相同(见下) |
| `npm test` skipped | 15 | 15 | — |
| `next build``/` | `○ Static` | `○ Static` | 通过 |
| 首屏 gzip`.next/static` 全部 `*.js` 逐个 gzip 后字节合计,68 个文件,同机同命令各测一次) | 1,450,864 B | 1,450,774 B | 90 B,−0.006%,在 ±2% 内 |
失败清单逐条比对:基线 36 条与本轮 36 条排序后 `diff` 为空(`admin code functions…``rectification agent maps setup failures…``generating does not disable the textarea…`、若干 `database` / `ephemeris` / `live staging sync` 套件等)。全部是无 Docker / 无数据库 / 无外部引擎的既有环境缺口,与本轮无关。
`next build` 环境备忘:worktree 里把 `node_modules` 软链到 `.worktrees/accept-20260916/frontend/node_modules` 时,Turbopack 直接 panic`Symlink [project]/frontend/node_modules is invalid, it points out of the filesystem root`)。按开工说明改成 `rm node_modules && npm ci` 后构建正常。基线数字的取法:`git diff > /tmp/work.patch``git checkout -- frontend/` → 构建取数 → `git apply /tmp/work.patch`(未用 `git stash`AGENTS §3.5)。
## 3. 被改的既有断言(原值 / 新值 / 原因)
| 文件 · 测试 | 原值 | 新值 | 原因 |
| --- | --- | --- | --- |
| `tests/onboarding-presentation.test.ts` · `terminal and fallback greetings follow the current profile name` | `createStartGreeting("周宁", SUNDAY(8), 0)``fallbackGreeting === "周宁,从你此刻最关心的问题开始吧。"` | `createStartGreeting("周宁", SUNDAY(8), 0.25)`= `早上好,周宁`);`fallbackGreeting === "欢迎,周宁"` | 时段池第一条改成不带称呼的「早上好」,要取带称呼的条目得换下标;兜底问候按产品口径改成单行。两条「必须带当前称呼、不得带旧称呼」的断言原样保留,另加了逐字相等断言,强度不降 |
| 同上 · `the starter hero splits one time-aware greeting…``the starter greeting is one line drawn from daypart, weekday and returning pools` | 断言 `parts.salutation === "中午好,周宁。"``parts.question === "现在最想理清哪件事?"`、两半拼起来等于整行、每时段至少 12 条不同问句 | 断言 `parts.text` 按下标取到「中午好」/「中午好,周宁」,`createStartGreeting``parts.text` 相等,`variantSelection` 为 1 / 0.999999 不越界 | 「招呼语 + 问句」两半的形状被产品取消,问句池不再存在,原断言的被测对象没了。边界不越界这一条原样保留 |
| 同上 · `the starter hero stays at a salutation and a question``the starter hero is one heading and nothing else` | 断言 `<p className="starter-salutation">{starterGreeting.salutation}</p>``<h1 …>{starterGreeting.question}</h1>` 同时存在 | 断言只剩 `<h1 id="starter-heading">{starterGreeting.text}</h1>`,且 `starter-salutation``starterGreeting.salutation|question` 在源码与 `globals.css` 里都不得出现 | 副标题行连同它的样式一起下线;断言从「必须有两行」改成「只有一行且不得有第二行」,是收紧不是放松 |
| `tests/consultation-entrypoint.test.ts` · `the starter heading is drawn per visit…` | `<h1 id="starter-heading">{starterGreeting.question}</h1>` | `<h1 id="starter-heading">{starterGreeting.text}</h1>` | 同上;「每次进首页重抽一次」(`useState(() => Math.random())` + 离开首页重抽)两条断言原样保留 |
| `tests/consultation-entrypoint.test.ts` · `the starter greeting keeps the display stack and display weight` | `font-size: clamp(26px,` | `font-size: clamp(24px, 2.8vw, 30px);`,并新增 `line-height: 1.25;` | 单行之后不需要 34px 上限那一档。原断言只匹配前缀,新断言匹配完整 clamp 并多钉一条 `line-height`,强度提高;`--font-display` / `font-weight: 500` / 不得是 `--font-body` 三条原样保留 |
| `tests/chat-composer-queue.test.ts` · `a queued card renders above the live textarea` | fixture `placeholder: "例如:未来半年是否适合换工作?"` | `placeholder: "想聊什么都可以"` | 只是渲染 `ChatComposer` 时传的样例 prop,不是被断言的对象;跟着产品文案更新以免留下过期字面量。断言本身未动 |
## 4. 新增测试(`tests/onboarding-presentation.test.ts`3 条 → 10 条)
| 测试 | 覆盖 |
| --- | --- |
| `late night has its own three lines and none of them asks a follow-up` | 深夜三条逐字;23 点与 4 点同属深夜 |
| `a blank name leaves only the lines that carry no name` | 名字为空(含全空白)只出不带称呼的条目;周一条目与回访池整条不可达;结果非空、不残留 `{名字}`、不以逗号收尾 |
| `the weekday pool only opens on its own day` | 周五能选到 `周五快乐`,周三选不到且池子恰好 3 条;周一 / 周日各自的条目可达 |
| `the returning pool needs at least one session behind the account` | `hasSessions=false` 时四条回访句一条都选不到(池子 3 条);`hasSessions=true` 时四条全部可达(池子 7 条) |
| `the same inputs always produce the same line` | 同一 `(name, now, variantSelection, hasSessions)` 连调两次结果相同 |
| `no greeting line uses a metaphor or trails off into a sentence` | 7 天 × 24 小时 × 2 种称呼 × 2 种 `hasSessions` × 100 个 selection:任何条目不含 `星` `月` `陪`、不以 `。` 结尾、长度 ≤ 12 |
| `the greeting knows whether the account already has sessions` | `hasSessions` 必须由既有 `sessions` 列表派生,`page.tsx` 不得另开状态 |
`frontend/tests/home-shell-growth-contract.test.ts` 未改动且仍绿:`page.tsx` 只多了一行 `const starterHasPriorSessions = …``useState` / `useRef` 计数不变。
## 5. 环境缺口
- 无登录态、无浏览器走查:真实首页上「一行问候居中、不再一大一小、占位符文案」的观感未在浏览器里确认,仅有 `next build` + 源码/样式合同。
- 本轮未跑 `npm run test:db`(未动数据库结构)、未跑 Python 测试(无 Python 改动)。