开场语从「称呼行 + 追问句」收成 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
9.0 KiB
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) 确定性地得到一行:
- 时段池按
now.getHours()(早晨 5–11 / 中午 11–14 / 下午 14–18 / 傍晚 18–23 / 深夜其余),沿用改动前的划分; - 星期池按
now.getDay(),只有周一 / 周五 / 周六 / 周日各一条,其余星期不贡献条目; - 回访池只在
hasSessions为真时拼进去; - 三池按「时段 → 星期 → 回访」顺序拼成一个数组;
name.trim()为空时先滤掉所有带{名字}的条目(时段池每段都留有不带称呼的条目,所以结果永不为空); - 下标
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 改动)。