Files
Jyotisha/docs/tasks/PROGRESS-consult-answer-the-question-20260927.md
T

77 lines
10 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-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`。