Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0199rbQDTsUbCVw84wc8BTFe
77 lines
10 KiB
Markdown
77 lines
10 KiB
Markdown
# PROGRESS · 普通对话回答问的那句话(2026-09-27)
|
||
|
||
任务书:`TASK-consult-answer-the-question-20260927.md`。执行方:Claude 子代理(产品要求直接执行)。分支 `codex/consult-answer-the-question-20260927`,工作树 `.worktrees/consult-answer-the-question-20260927`,未推送。
|
||
|
||
## 基线
|
||
|
||
- `origin/staging` = `2ce3c216`(任务书含首轮原文与 R6 的那一版)。D8 已由产品确认,T6 已做。
|
||
- 开工实测(Node 22.14,`npm test`):4192 条 / pass 4096 / fail 66(TAP 行 24 条 `not ok`,均为无 Docker 的 DB / 部署套件)/ skipped 30。失败清单存 scratchpad `baseline-fails.txt`。
|
||
- BUG 编号:`BUG_HISTORY.md` 最大 1063,任务书预留至 1069,本单从 1070 起。
|
||
|
||
## 做了什么
|
||
|
||
| 任务 | 改动 | 落点 |
|
||
| --- | --- | --- |
|
||
| T1 口气层 | 反差的 A、B 限定为盘面结构,问人时写宫位与代表星;删「这句我按『……』理解了」改成两种读法才写「我按 A 答」;新增「不揣测」段(六个禁写短语 + 禁替用户 / 当事人陈述动机需求感受);是非题答法;Good / Bad 是非题样例(虚构盘面);合同 Never 段加「写盘把人放在哪,不写人要什么」 | `frontend/src/mastra/product-voice.ts`、`frontend/docs/VOICE.md` |
|
||
| T6 首轮只说一遍(D8) | `REPORT_HEADING` 去掉 `question`(申报窗口保留 `WINDOW_OPEN_HEADING`);开场不带行动;正文三标题;依据节只写开场没说过的、表格与正文二选一;行动只在最后一节;首轮 ≤ 900 字。四处同步:`natalSpokenReportContract`、`natalAnswerShapeInstruction()`、`NATAL_REPORT_SKELETON`、`index.ts` 写作句;`route.ts` grounded 兜底两处内联指令合并为一份 `legacyNatalInstruction`;续写提示与 `consultationSpokenHeadingRule("natal")` 同步 | `consultation-thinking-plan.ts`、`product-voice.ts`、`skill-binding.ts`、`index.ts`、`route.ts` |
|
||
| T2 追问轮 | `followUpAnswerShapeInstruction()`、`hasPriorAssistantAnswer(history)`、`natalUserTurnShape({ entrypoint, history })`;route 用户轮按它切;grounded 兜底同样切;agent context 与思考计划带 `followUpTurn`。工具仍每轮调用 | `consultation-thinking-plan.ts`、`route.ts`、`consultation-tools.ts` |
|
||
| T3 清单是核对项 | `index.ts` 加「The checklist is a list of things to check, not a list of paragraphs to write…」;合同第 2 条加「cite only the fields that support this judgment, and only what the opener did not already say」 | `index.ts`、`product-voice.ts` |
|
||
| T4 步骤栏 | 第一节标题 `OPENER_THINKING_TITLE = "先回答你问的这件事"`;首轮步骤「用盘上的反差回答这个问题」,追问轮「直接回答这句话」;该节 heading 与「盘里支持」共用 | `consultation-thinking-plan.ts`、`frontend/DESIGN.md` |
|
||
| T5 记录 | BUG-1070~1073(`fixed_pending_acceptance`)、CHANGELOG 一条(Skill 不 bump)、真机清单、本文件、README 索引 | `docs/**`、`CHANGELOG.md` |
|
||
|
||
### 思考栏节的 heading 选择(任务书允许执行方自选)
|
||
|
||
开场节保留为思考栏第一节,`heading` 指向第一个正文 H2(「盘里支持这个判断的地方」):第一个正文 H2 出现时开场节与依据节一起收口;追问轮整篇无 H2,四节在结算时收口(`applyThinkingSectionProgress` 的 `settled` 分支已有)。没有删节,`thinkPlanSteps` 的 id 序列不变,改动量最小。
|
||
|
||
## 测试
|
||
|
||
新增:`frontend/tests/consult-answer-the-question-20260927.test.ts`(2 条:追问轮真实 Agent + 记录提示词假模型 + 公开盘 golden:写作步提示词含追问形状、工具 1 次 / 模型 2 次、无标题短正文 < 160 字整段放出并扣点一次、思考栏步骤「直接回答这句话」;首轮对照);`consultation-thinking-plan.test.ts` +1(追问指令、`hasPriorAssistantAnswer` 四种历史、`natalUserTurnShape` 三种入口、追问计划);`consultation-voice-contract.test.ts` +1(禁写短语、反差限盘面、是非题答法、样例、行动位置)。测试支撑 `consult-natal-agent-test-support.ts` 加 `instruction` / `followUpTurn` 两个可选项(默认值不变)。
|
||
|
||
### 改既有断言(原值 / 新值 / 原因,注释也写在测试里)
|
||
|
||
| 文件 | 原值 | 新值 | 原因 |
|
||
| --- | --- | --- | --- |
|
||
| `consultation-voice-contract.test.ts` | `match(voice, /## 先回答你的问题/)` | `doesNotMatch` + 三标题顺序、开场无行动、Say each thing once、≤ 900 字、只引支撑字段、行动只在最后一节、合同末句改追问轮 | D8 / BUG-1073 |
|
||
| `consultation-voice-contract.test.ts` | `match(voice, /这句我按『……』理解了,不对你纠正我/)` | `doesNotMatch` + 「两种实质不同的读法时才写『我按 A 答』」「单义的问题直接答,不改写它」 | D4 / BUG-1070 |
|
||
| `consultation-thinking-plan.test.ts` | 四节 heading `[question, support, timing, action]` | `[support, support, timing, action]`,首节 title「先回答你问的这件事」,不含「先抓住你真正在问的事」 | D5 / D8 |
|
||
| `consultation-thinking-plan.test.ts` | window heading = `REPORT_HEADING.question` | `WINDOW_OPEN_HEADING`(字面不变) | 正文标题表删掉 question,申报窗口不在本单范围 |
|
||
| `consultation-thinking-plan.test.ts` | 拆分测试四标题、首节切片含「外松内紧」 | 三标题、开场留在 preamble | D8 |
|
||
| `consultation-thinking-plan.test.ts` | 写出 `## 先回答你的问题` → 首节 done、第二节 active | 无标题时首节 active;写出 `## 盘里支持` 后前两节 done、时间节 active | 开场与依据节共用 heading |
|
||
| `consultation-thinking-plan.test.ts` | 指令含四个标题 | 三个标题 + 开场不写行动、只在这里出现一次、≤ 900 字、不写「先回答你的问题」、反差只写盘上 | D8 |
|
||
| `consultation-thinking-plan.test.ts` | 续写夹具 / 续写标题清单用 question | 用 support;续写提示不含「## 先回答你的问题、」 | D8 |
|
||
| `consultation-run-timeline.test.ts` | 正文夹具 `## 先回答你的问题`;思考行「先抓住你真正在问的事」;写作行 `write-先回答你的问题` | 口语开场 + `## 盘里支持…`;「先回答你问的这件事」;`write-盘里支持这个判断的地方` | D5 / D8(BUG-1072/1073) |
|
||
| `consultation-run-timeline.test.ts` | settled 夹具以 `## 先回答你的问题` 开头 | 口语开场无标题再接「盘里支持」 | D8 |
|
||
| `consult-single-pass-answer-20260927.test.ts` | `match(route, /natalAnswerShapeInstruction\(\)/)` | `natalUserTurnShape({ entrypoint: consultEntrypoint, history })`、`followUpTurn` 接线、`doesNotMatch` 旧调用 | D3 / D6(BUG-1071) |
|
||
| `consult-single-pass-answer / condensed-checklist / evidence-lookup / gender-card` 四个 ANSWER 夹具 | 含 `## ${REPORT_HEADING.question}` 一节 | 该节删除,开场直接到 `## 盘里支持` | D8 |
|
||
| `consult-answer-truncation-20260926.test.ts` | 夹具标题 `REPORT_HEADING.question` | `REPORT_HEADING.support`(只需任意一个标题) | D8 |
|
||
| `consultation-agentic-runtime.test.ts` | `sections.some(heading === REPORT_HEADING.question)`;5 处正文夹具标题 question | `sections.some(title === OPENER_THINKING_TITLE)`;夹具改 support | D5 / D8 |
|
||
| `consultation-smalltalk.test.ts` | `match(contract, /One natal … question still uses the opener-plus-skeleton/)` | `/The first natal … answer of a session uses the opener-plus-skeleton above/` + 追问轮句 | D3(BUG-1071) |
|
||
|
||
`frontend/tests/agent-voice-copy-contract.test.ts` 里的 `marriageConsultOpen: ["## 先回答你的问题", …]` 是 Task 0 冻结的「修前快照」数据,不是对现状的断言,未改。`chat-answer-split.ts` 的 `shortenAnswerHeading` 保留「先回答你的问题 → 先回答」给历史消息渲染。Python `tests/` 无按这些文案断言的用例(已 grep)。
|
||
|
||
## 门禁数字(完工实测,Node 22.14,本工作树)
|
||
|
||
| 项 | 开工基线 | 完工 | 结论 |
|
||
| --- | --- | --- | --- |
|
||
| `tsc --noEmit` | — | 0 错 | 通过 |
|
||
| `npm run lint` | — | 0 error(127 warning,既有) | 通过 |
|
||
| `npm test` 总数 | 4192 | 4196(+4:新文件 2、thinking-plan 1、voice 合同 1) | 通过 |
|
||
| `npm test` pass / fail / skipped | 4096 / 66(TAP 顶层 `not ok` 24 条)/ 30 | 4142 / 24 / 30 | 失败名单与基线 24 条逐条一致(`diff` 为空),均为无 Docker 的 DB / 部署套件;退出码 1 即这 24 条 |
|
||
| 消失的测试名 | — | 0(只有新增) | 通过 |
|
||
| `next build --webpack` | — | 退出 0;`/`、`/chart`、`/ephemeris`、`/people` 均 ○ Static | 通过 |
|
||
| 首屏 rootMainFiles gzip(9) | 130,933 B(`PROGRESS-consult-evidence-card-v2` / `single-pass` 口径) | 130,933 B(0.00%) | 通过 |
|
||
| `index.html` 引用的 `_next/static` JS gzip(9) | 660,412~661,444 B(36 个,gender 单口径) | 618,938 B(33 个,本单用正则从 `.next/server/app/index.html` 取,文件数不同,口径未必相同) | 供参考;rootMainFiles 为准 |
|
||
| `frontend/src/app/(app)/page.tsx` | — | 未改 | 通过 |
|
||
|
||
## 提交
|
||
|
||
- `9a42333a` feat(consult):T1/T6/T2/T3/T4 代码与测试(18 个文件,+416/−70)。
|
||
- 第二个提交:T5 记录(BUG-1070~1073、CHANGELOG、VOICE、DESIGN、真机清单、本文件、README、任务书 D8 确认)。
|
||
|
||
## 偏离与说明
|
||
|
||
- 提交分组:任务书要求按 T1/T6、T2/T3、T4、T5 分四次提交;T2(`followUp`)与 T6(标题表)落在同一批文件(`consultation-thinking-plan.ts`、`route.ts`、同一批测试)的相邻改动里,按 hunk 拆分不可靠,改为两次提交:代码 + 测试一次,记录一次。
|
||
- `next build` 默认 Turbopack 对软链的 `node_modules` 报 `Symlink … points out of the filesystem root`(与 `PROGRESS-consult-gender-optional-20260927` 同一现象),改用 `next build --webpack` 量 `/` 状态与首屏 gzip;数字口径与该记录一致(rootMainFiles,gzip level 9)。
|
||
- lint 有 127 条既有 warning(0 error),不在本单范围,未动。
|
||
- 真实模型输出未验(无凭据):见 `docs/testing/consult-answer-the-question-20260927.md`。
|