docs: BUG-1053 record, progress, real-device checklist, changelog and board row

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
This commit is contained in:
Jesse_Chen
2026-09-27 01:04:27 +08:00
co-authored by Claude Opus 5.5
parent eef0cb7486
commit 3f8e180238
5 changed files with 232 additions and 0 deletions
+7
View File
@@ -1,5 +1,12 @@
# 印度占星 Skill 更新日志
## 2026-09-27 — 普通对话:回答改由看过星盘的那一步直接写(待验收)
- 以前本命提问算完盘后,看过计算结果的那一步写的回答被丢掉,用户看到的是另一个没看过星盘的步骤重写的(BUG-1053,staging 自 08-23 起;生产不受影响)。表现为回答说「没有这方面的盘面证据」,或引用和星盘页对不上的上升、月亮、宫位。
- 现在算完盘的那一步直接写回答,不再另写一遍;回答写太长被截时,续写也带着本轮计算结果。开场与四个标题(先回答你的问题 / 盘里支持这个判断的地方 / 时间怎么看 / 这周可以做的一件事)不变;「深入看今日」仍是三节。
- 等待:少了一次重写,通常更快;最长仍约 3 分钟(算盘最多 110 秒,写回答 70 秒从算完那一刻起算)。第一段字会在写出第一个小标题或约 160 字后一起出现。回答没写完时照旧提示「回答未完成」、不扣点。
- Skill 版本不 bump。不改数据库。
## 2026-09-27 — 登录后、直接打开网址都进空白首页,不再落回上一次对话(待验收)
- 以前登录后(尤其是停在某条对话里时登录过期)、或在地址栏直接打开网站,会回到上一次的对话,甚至是上一次的生时校正;用户以为在首页提问,其实问进了旧对话(BUG-1052)。
+30
View File
@@ -14156,3 +14156,33 @@
- 相关记录:BUG-1038(登录返回存根与 `bootstrapSelectionFromLookup` 来源参数,本条推翻其存根部分)、BUG-599(裸 `/` 不自动开校正、默认落咨询,本条收紧为空白首页)、BUG-1015(`?new=1` 新建意图与恢复不抢落点,规则被推广)、BUG-1040(暖返回,同规则、首帧无加载环不变)、BUG-989 / BUG-929 / BUG-1001(首问前不落库、空草稿不进列表)、BUG-705(`?c=` lookup 不变)、BUG-936(首屏兜底不变)。
- 复发自:无(产品规则变更 + BUG-1038 / BUG-599 规则叠加的组合路径)。
- 修复版本:`codex/home-landing-blank-20260927`(本地提交,未推送)。
## BUG-1053 | 普通咨询用户看到的回答没看过星盘:本命路径由看不到计算结果的第二个流来写
- 状态:resolved(本地修复 `codex/consult-single-pass-answer-20260927`,待部署 staging;真机清单待产品走)
- 首次发现 / 最近更新:2026-09-27 / 2026-09-27
- 影响面:`POST /api/consult` 本命路径(`runAgenticConsultation` 的 natal 分支,含首页「深入看今日」入口);`frontend/src/lib/stream-agent-response.ts`(`consumeAttempt` / `publishFindings` / `composeOnce` / `finishPass4`);`frontend/src/lib/consultation-thinking-plan.ts`(`consultationComposePrompt`);`frontend/src/mastra/consultation-tools.ts`(时间常数)。申报时段与无出生分钟路径没有 compose,不受本缺陷影响,但一并改为同一套取答规则与时钟。生产(`7b620c7a`,08-16)没有这条路径,**不受影响**。
- 用户现象:staging 上本命提问的回答与盘面对不上。gpt-5.6-luna 直接写「没有父母主题的盘面证据」;DeepSeek 写得像模像样,但上升、月亮、宫位等「盘面事实」并非来自本轮计算。**2026-08-23 以来 staging 上 DeepSeek 的本命回答可能引用过没有根据的盘面事实。**
- 触发条件:任何一轮本命咨询(每轮都会触发,与问题内容无关)。
- 根因:三段式里的第三段是瞎写的。
1. 主工具循环调用 `run-jyotish-consultation` 后,下一步模型**看得到**约 4 万 token 的计算结果,也写了回答,但这段正文在 `consumeAttempt` 里被 `drainSpoken` 整段丢弃。
2. 随后 `composeAnswer` 另开一个 `agent.stream`,输入只有 `[...baseMessages, { user: consultationComposePrompt() }]`(`toolChoice: "none"`、`maxSteps: 1`)。本命路径的 `baseMessages` 只有历史 + 本轮问题,从不追加工具结果;Agent 在两次 stream 之间没有记忆。
3. `interpretFindings` 只回思考计划的 id、没有文本,所以 compose 提示词里的「判断依据」恒为空,却写着「服务器计算已经完成」。用户看到的回答就是这个没看过星盘的流写的。`continueAfterLength` 同样只拿历史 + 已写正文,续写也是盲的;只有保留工具的 `retryForAnswer` 能重新取回同请求缓存。
4. 顺带:「深入看今日」入口的用户轮要求三节(今日趋势 / 适合推进 / 一个行动),compose 提示词却强制本命四标题,两条指令互相矛盾。
- 引入:`04463e9a`(2026-08-23,「sliced compose」:compose 前丢弃主循环正文);BUG-944(`94c1e81f`)把分段写作改为一次成文时保留了这个结构。
- 为什么测试没拦住:compose 相关测试全部是手造的生成器流,没有一条断言「写回答的那次模型调用看到了什么」。`consultation-agentic-runtime.test.ts` 的「composeAnswer drains leftover first-stream text and writes one body」反而把「丢掉看过证据的正文」当成期望行为锁住。BUG-1051 的回归只看结束方式,同样不看 compose 的输入。
- 修复(产品 2026-09-27 决策 D1–D3):
- D1 删掉第三段:删除 `composeAnswer` / `interpretFindings` / `publishFindings` / `composeOnce` / `drainSpoken`、`consultationComposePrompt` / `consultationSectionPrompt`(后者自 BUG-944 起已是死代码)、`AGENT_SLICE_MAX_STEPS`、`ThinkFinding`。主循环在工具结果之后的那一步写回答,正文保留。
- 取答边界:新选项 `stepScopedAnswer`(本命、申报时段)。按 Mastra 的 `step-start` / `tool-call` / `step-finish` 分步:一步里的正文先扣住,出现 Markdown 标题或满 160 字才放出;这一步如果调用了工具,扣住的正文整段丢弃;计算结果到手之前的正文沿用原规则(不进回答、只留作降级材料)。所以工具前后的过程说明都进不了回答。
- 写作要求搬家:原 compose 提示词里的「开场无标题、一次写完四个二级标题、不写统一参数与技法审计表、不写思考过程」改由主循环看到的用户轮携带(`natalAnswerShapeInstruction()`;「深入看今日」入口 `dailyAnswerShapeInstruction()`),并加一句「拿到本轮计算结果后直接写回答,只用结果里的盘面事实」。系统提示里的 VOICE §7 开场形态与四标题规则不变。
- 续写有据:`streamAgentResponse` 记下计算工具的结果,`continueAfterLength(output, evidence)` 由 `consultationContinueMessages()` 把它作为一条用户消息放在已写正文之前(申报时段已预计算的包已在 `baseMessages` 里,不重复)。
- Pass 4 整篇被拒:原先的 compose 重写改为带 `PASS4_RETRY_HINT` 的 `retryForAnswer`(保留工具、命中同请求缓存);已放出过句子时仍就地丢弃、不重写(BUG-950)。
- 时间预算:`createConsultationRunClock()` 一轮两只钟。工具与申报时段预计算仍用 110 秒的 `toolSignal`(每领域 31 秒、领域墙钟 65 秒不变);模型循环的 `loopSignal` 在计算结果到手之前跟随工具阶段,到手后(`onAnswerPhase`)交给 70 秒答案时钟(`CONSULTATION_ANSWER_TIMEOUT_MS`,由 `CONSULTATION_COMPOSE_TIMEOUT_MS` 改名),续写与回答重试共用同一只答案钟。计算刚好在 110 秒前完成、消费端还没看到时,由 `answerReady` 判断交接而不是掐断。最坏仍是 110 + 70 = 180 秒,`maxDuration` 240 不变。
- BUG-1051 保持:结算只认写回答那一步的 `stop`。Mastra 循环在一步以 `other` / `unknown` / 无工具调用的 `tool-calls` 结束后会再跑一步,所以结束原因取「最后一个写出正文的步」而不是整条流的 `finish`;`length` → 续写;其余非 `stop` 且有正文 → `answer_truncated`、不扣点、记 `compose-abort`(名字保留,现指写回答那一步)。
- D2 观测:`composeFinishReason` / `composeAborted` / `answerVisibleChars` 名字不变,含义改为「写回答那一步」,仍只有枚举 / 布尔 / 计数。
- 验证:新增 `frontend/tests/consult-single-pass-answer-20260927.test.ts`(15 条,真实 `getJyotishAgent` + 真实 skill 绑定 + 真实计算工具 + 记录提示词的假模型,计算数据来自 `fixtures/consultation-workflow-report-blocked-repairs-golden.json`):写回答的调用提示里有工具结果与 golden 盘面数值;工具结果之后只有一次模型调用;工具前、工具之间的过程说明不进回答;四标题与无标题开场保留;`length` 续写提示里有计算结果;`content-filter` / `tool-calls` / `other` / `unknown` 截断不扣点;答案钟掐断 → 截断、`compose-abort`;工具阶段到期不掐写回答;空回答走带工具的回答重试且不重复宣布计算;Pass 4 整篇被拒带提示重试;路由源码合同。修复前用同一套真实 Agent 复现:3 次模型调用,只有第 2 次提示里有工具结果,用户看到的是第 3 次写的。既有 compose 用例改写并附「原值 / 新值 / 原因」(`consultation-agentic-runtime` 6 条、`consult-answer-truncation-20260926` 全文件、`consultation-thinking-plan` 2 条、`consultation-workflow-contract` 3 条、`consultation-stream-recovery` 1 条、`application-billing-contract` 1 条)。数字见 `docs/tasks/PROGRESS-consult-single-pass-answer-20260927.md`。
- 未做(D3 范围外):约 4 万 token 的工具结果瘦身与按领域选技法、家庭拆父母 / 子女、43 行审计表。真实供应商下写回答步的耗时、`composeFinishReason` 分布与盘面引用是否对得上,需部署后按 `docs/testing/consult-single-pass-answer-20260927.md` 复核。
- 防复发:用户可见正文必须由看过本轮证据的那次模型调用写出。新增任何写回答的流,都要有「这次调用的提示里有工具结果」的真实 Agent 回归(记录提示词的假模型),不得只断言结束方式或正文形状。续写、重试这类新流必须显式带上证据或保留工具。
- 相关记录:BUG-612(分段写作再调工具,同一 compose 结构)、BUG-942 / BUG-943 / BUG-944(三通道重做,保留了丢弃主循环正文的结构)、BUG-1051(写回答时钟与结算规则,本单沿用并搬进主循环)、BUG-305、BUG-937(主循环开 thinking,不得用非 `auto` 的 toolChoice)。
- 复发自:无(新缺陷)。
- 修复版本:待提交
@@ -0,0 +1,124 @@
# PROGRESS · 普通咨询回答改由看过星盘的那一步写(BUG-1053)· 2026-09-27
- 执行方式:直接执行(产品负责人授权子代理执行;Claude 事后独立验收)
- 基线:`origin/staging` `5f2e007f` 开工;提交前变基到 `03c7c0a9`(BUG-1052 首页落点单与数据卡调研任务书,只与本单的 `CHANGELOG.md` / `docs/BUG_HISTORY.md` / `docs/tasks/README.md` / `frontend/DESIGN.md` 重叠,已并存)
- 分支:`codex/consult-single-pass-answer-20260927`(本地提交,未推送)
- BUG 编号:1053(开工与提交时核对,1052 由并行的首页落点单占用)
- 引入:`04463e9a`(2026-08-23);相关 BUG-612 / BUG-942–944 / BUG-1051
## 结论
| 项 | 结果 |
| --- | --- |
| 缺陷复核 | 确认。用同一套真实 `getJyotishAgent` + 记录提示词的假模型跑修复前代码:3 次模型调用,只有第 2 次(主循环工具结果之后)的提示里有工具结果和 golden 盘面数值;用户看到的正文是第 3 次(compose)写的,它的提示里两者都没有 |
| D1 删掉第三段 | 完成:删 `composeAnswer` / `interpretFindings` / `publishFindings` / `composeOnce` / `drainSpoken` / `ThinkFinding`、`consultationComposePrompt` / `consultationSectionPrompt`、`AGENT_SLICE_MAX_STEPS`;主循环最后一步的正文就是回答 |
| 取答边界 | `stepScopedAnswer`:按步扣住正文,这一步调用了工具就整段丢;见下文 |
| 写作要求 | 搬进主循环看到的用户轮:`natalAnswerShapeInstruction()` / `dailyAnswerShapeInstruction()` |
| 续写有据 | `continueAfterLength(output, evidence)` + `consultationContinueMessages()`,三条路线共用一个构造函数 |
| 时间预算 | `createConsultationRunClock()`:工具 110 秒不变,循环拿到计算结果后交给 70 秒答案钟;最坏 180 秒 |
| BUG-1051 | 保持:结算只认写回答那一步的 `stop`;`length` 续写;其余截断不扣点 |
| D2 观测 | 名字不变、含义改为写回答那一步(见下文) |
| D3 | 未碰:工具结果瘦身、家庭拆分、审计表、Python 引擎、Skill 路由 |
## 回答怎么和工具前后的过程说明隔开
Mastra 的 `fullStream` 每个模型步都有 `step-start` → `text-delta…` → `tool-call`(可选)→ `tool-result` → `step-finish(reason)`。`consumeAttempt` 在 `stepScopedAnswer` 下:
| 情况 | 处理 |
| --- | --- |
| 计算结果到手之前的正文 | 与原来一样:不进回答,只存进 `uncontractedText` 作降级材料(BUG-961) |
| 计算结果到手之后,这一步的正文 | 先扣住;出现 Markdown 标题(`#`–`###`)或满 `ANSWER_RELEASE_CHARS = 160` 字才放出,之后本步照常流式(Pass 4 按句放行) |
| 这一步出现 `tool-call` | 扣住的正文整段丢弃,本步后续正文也不收 |
| `step-finish` 时还扣着 | 结束原因不是 `tool-calls` 就放出(短回答),是就丢 |
| 残余风险 | 一步先写了 ≥160 字或一个标题、再调用工具:那段已放出、无法撤回。系统提示要求不重读已交付的方法段,实测形状里过程说明都是一句话,未见此情况;部署后留意 |
160 字的依据:工具前的过程说明通常一句(「我再读一下参考」);本命开场规定 3–6 句、≤400 字,160 字大约是开场的两三句,第一段字晚一两秒出现。
## 写作要求现在在哪里
| 位置 | 内容 |
| --- | --- |
| 系统提示(未改) | `productConversationVoice`、`natalSpokenReportContract`、VOICE §7 开场形态、`consultationSpokenHeadingRule("natal")` 四个 H2 |
| 用户轮 `natalInstruction`(改) | 原句「事业/财富/婚恋/家庭先给口语开场,再按四个标题写结论…」换成 `natalAnswerShapeInstruction()`:拿到本轮计算结果后直接写回答、只用结果里的盘面事实、工具前后不写过程说明;开场无标题;一次写完四个 `##` 标题;不写统一参数 / 技法审计表 / 思考过程清单 / 内部 JSON。仍以「如需新的个人星盘结论,必须调用服务器绑定的排盘工具」开头,不与工具调用要求冲突(旧 compose 提示的「不要再调用排盘工具」没有搬过来) |
| 「深入看今日」入口 | `dailyAnswerShapeInstruction()`:三节写法原文保留,加同一句取证要求。旧 compose 提示强制本命四标题,与入口三节矛盾,这次一并消除 |
## 时间预算与每一层超时
| 层 | 修复前 | 修复后 |
| --- | --- | --- |
| 工具 / 申报时段预计算 | `agentAbortSignal` 110 秒 | 不变:`runClock.toolSignal` 110 秒;每领域 31 秒、领域墙钟 65 秒不变 |
| 主循环模型流 | 110 秒(与工具共用) | `runClock.loopSignal`:计算结果到手前跟随工具阶段 110 秒;到手后(`onAnswerPhase`)只受 70 秒答案钟约束 |
| 写回答 | compose 另起 70 秒答案钟(第一次写回答流打开时起算) | 同一只 70 秒答案钟,从计算结果到手那一刻起算,覆盖主循环剩余步骤 |
| 续写 / 回答重试 | 共用答案钟 | 不变 |
| 竞态 | — | 计算刚在 110 秒前完成、消费端还没读到 `tool-result` 时,`answerReady()`(`state.consultationToolCompleted`)让循环交接而不是被掐 |
| 最坏总等待 | 110 + 70 = 180 秒 | 仍是 180 秒:计算必须在 110 秒内完成,答案钟最晚 110 秒起算 |
| 路由 `maxDuration` | 240 | 240 不变(源码合同锁 110 + 70 < 240 且 ≤ 180) |
| Node / Caddy / 客户端 / 账务 / 断线 | BUG-1051 已逐层核对(`PROGRESS-consult-answer-truncation-20260926.md`) | 本单没有拉长最坏时长,结论不变;未改 `deploy/`、`.gitea/workflows` |
为什么选「计算结果到手时起算的答案钟」而不是「整条主循环 180 秒」:两者都保证写回答至少 70 秒,但整条 180 秒时,主循环若到 180 秒才停在 `length`,续写再拿 70 秒会到 250 秒,超过 `maxDuration`;答案钟方案让写回答、续写、重试共享同一个 70 秒,总时长封顶 180 秒。
写回答那一步开着 thinking(它是主循环的一步),思考 token 也从这 70 秒里出;修复前主循环工具结果后那一步同样在 110 秒里思考并写完一遍(然后被丢弃),再由 compose 重写。现在少一次整篇写作,正常情况应更快。
申报时段路线:预计算完成即合同就绪,写回答从流开始就走答案钟(修复前是 110 秒减去预计算的剩余时间)。无出生分钟路线:没有工具、不交接,主流仍 110 秒,续写 / 重试 70 秒,行为不变。
## 各种结束方式的行为
结束原因取「最后一个写出正文的步」的 `step-finish` 原因;没有分步信息时取整条流的 `finish`。原因:Mastra 循环在一步以 `other` / `unknown` / 无工具调用的 `tool-calls` 结束后会再跑一步,如果那一步什么也没写、以 `stop` 结束,整条流的 `finish` 就是 `stop`,半截回答会被当成完成(测试里实测到)。
| 写回答的那一步 | 有正文 | 无正文 |
| --- | --- | --- |
| `stop` | `run.completed`,扣点一次 | `answer-retry`(保留工具、命中同请求缓存,不重复宣布计算)→ 仍空 `empty_answer` |
| `length` | 续写一次,带计算结果;续写 `stop` → 完成;续写仍 `length` / 被掐 / 其他 → `answer_truncated` | 同左 |
| 答案钟掐断(Mastra `abort` + `finish(tripwire)`) | `answer_truncated`,记 `compose-abort`,半句不外发 | 不扣点 |
| `content-filter` / `tool-calls` / `other` / `unknown` / `error` | `answer_truncated`,不扣点 | `empty_answer` 路径 |
| Pass 4 把整篇都拒了 | — | `answer-retry` 带 `PASS4_RETRY_HINT` |
| Pass 4 拒了部分句子 | 就地丢弃,不重写(BUG-950) | — |
计算结果到手之前被掐记 `tool-abort`,之后记 `compose-abort`(名字沿用 BUG-1051,现指写回答那一步)。
## D2 观测字段
| 字段 | 修复前含义 | 修复后含义 |
| --- | --- | --- |
| `composeFinishReason` | compose 流的结束原因 | 写回答那一步的结束原因(续写 / 重试时取最后一次写回答的流) |
| `composeAborted` | compose 流是否被掐 | 写回答那一步是否被掐 |
| `answerVisibleChars` | 回答字数 | 不变 |
| `modelFinishReason`(只进日志) | 最后一个流的 `finish` | 不变(整条流的 `finish`,可能与上面不同) |
名字保留是为了和 BUG-1051 刚部署的埋点连续;仍只有枚举 / 布尔 / 计数,公开回执不带。
## 删掉了什么
| 删除 | 说明 |
| --- | --- |
| `composeAnswer`(路由 + 流选项) | 看不到计算结果的第二个流 |
| `interpretFindings` / `publishFindings` / `ThinkFinding` | 只回计划 id、文本恒空;`think.step` 只是把行从 running 翻到 done。计划行现在由第一条 `answer.delta` 或 `run.*` 收口;事件 schema 与客户端 reducer 不动(兼容) |
| `composeOnce` 与 `phase.started/completed`(interpret / compose) | 同上 |
| `drainSpoken` | 丢弃主循环正文的开关 |
| `consultationComposePrompt`、`consultationSectionPrompt`、`ConsultationSectionPromptReason` | 前者被写作要求取代;后者自 BUG-944 起已是死代码 |
| `AGENT_SLICE_MAX_STEPS` | 只有 compose 用 |
| `createConsultationAnswerClock`、`CONSULTATION_COMPOSE_TIMEOUT_MS` | 并进 `createConsultationRunClock`,常量改名 `CONSULTATION_ANSWER_TIMEOUT_MS`(值 70 秒不变) |
未删:`think-step-gate.ts`(`public-thinking.test.ts` 与 `rectification-step-answer.test.ts` 仍在用);`consultationSliceGenerationSettings` 与 `sliceAddedVisibleText`(开工前就已无调用,不在本单范围)。
## 测试
| 项 | 结果 |
| --- | --- |
| 新回归 `consult-single-pass-answer-20260927.test.ts` | 15 条全绿:真实 `getJyotishAgent`(真实 skill 绑定、真实计算工具、真实 prepareStep)+ 记录提示词的假模型,计算数据来自 `fixtures/consultation-workflow-report-blocked-repairs-golden.json`(引擎真实输出,虚构身份) |
| 修复前对照 | 同一套真实 Agent 跑修复前的 `stream-agent-response` + compose 接线:3 次调用,工具结果与 golden 月亮度数只出现在第 2 次提示里,用户正文来自第 3 次 |
| 改写的既有用例 | 全部附「原值 / 新值 / 原因」:`consultation-agentic-runtime` 6 条(其中 5 条改名,旧名写在原值栏)、`consult-answer-truncation-20260926` 全文件(名字不变,文件头统一说明 + 3 条单独说明)、`consultation-thinking-plan` 2 条(名字保留)、`consultation-workflow-contract` 3 处、`consultation-stream-recovery` 1 处、`application-billing-contract` 1 处 |
| `tsc --noEmit` | 0 错 |
| `npm run lint` | 0 error(127 warning,均为既有;本单改动文件里的 2 条 warning 开工前就有) |
| 全量 `npm test`(Node 22.14,变基前) | 4084 条,fail 24 / skip 28;失败名单与基线 `ct-test.log`(4069 / 24 / 28)逐条一致,0 新增;消失的 5 个名字均为上面改名的用例(原值栏记旧名),新增 20 个名字 |
| 全量 `npm test`(变基到 `03c7c0a9` 后) | 4093 条(多出的 9 条是 BUG-1052 单自带的),fail 24 / skip 28;失败名单与基线逐条一致,0 新增 |
| Python 门禁集 | 948 passed / 1 skipped(与基线一致;本单未改 Python,也没有 Python 合同读这几份前端文件) |
| `npm run build -- --webpack` | 通过,`/` 为 `○` Static |
| 首屏 gzip(rootMainFiles) | 131,253 B,基线 130,933 B,+0.24%(±2% 内) |
| 杂项 | 已删构建留下的 `frontend/frontend/` |
## 没做 / 留给真机
- 真实供应商下:写回答那一步的耗时、`composeFinishReason` 分布、引用的上升 / 月亮 / 宫位是否与星盘页一致——无模型凭据,按 `docs/testing/consult-single-pass-answer-20260927.md` 部署后走。
- 已知取舍:第一段字要等标题或 160 字;「一步先写长段再调工具」时那段会留在正文里(见上文残余风险)。
- D3 范围外(另行决策):约 4 万 token 工具结果瘦身与按领域选技法、家庭拆父母 / 子女、43 行审计表。
+1
View File
@@ -129,6 +129,7 @@
| — (产品 09-27 拍板 D1–D4,直接执行) | [PROGRESS](PROGRESS-home-landing-blank-20260927.md) | **登录后 / 裸 `/` 落空白首页**:真机登录后在「首页」提问其实问进了上一次生时校正。删登录返回存根(401 / 次级页链接写、登录后写回 `?c=` 打开),裸 `/` 不再落最近会话,一律当前人物的空白首页(复用空草稿);`?c=` / `?new=1` / 对话内刷新不变;推翻 BUG-1038 存根与 BUG-599 默认落点 | 已验收(真机欠) | `codex/home-landing-blank-20260927`(BUG-1052,本地未推) |
| — (产品 09-26 口头拍板 D1–D3,直接执行) | `PROGRESS-consult-answer-truncation-20260926.md` | **普通咨询回答写到一半被掐断仍扣点(BUG-1051,复发自 BUG-305)**:工具循环与写回答共用 110 秒 signal;Mastra 1.50 超时不抛错(`abort` 块 + `finish(tripwire)` 后正常关流),结算只认抛错与 `length`。D1 写回答自有 70 秒时钟(首用起算,续写 / 回答重试共用,最坏 180 秒,`maxDuration` 240);D2 写回答的最后一个流不是 `stop` 且有正文 → `answer_truncated`、不扣点、记 abort 步、不冲半句,`length` 续写不变;D3 观测加 `composeFinishReason` / `composeAborted` / `answerVisibleChars` | 已验收(真机欠) | `codex/consult-answer-truncation-20260926`(本地,未推送);新回归 15 条用真实 Mastra `Agent`(修复前 11 条红);全量失败名单 0 新增;Python 948/1;`/` ○、gzip 0%;真机清单 `docs/testing/consult-answer-truncation-20260926.md` |
| `TASK-consult-evidence-card-research-20260927.md` | `PROGRESS-consult-evidence-card-research-20260927.md` | **普通对话数据卡调研**:引擎输出逐项分五类计量(现约 4 万 token、父母问题相关约 3.5%);四处领域→技法来源对账并起草各领域数据卡(家庭拆父母/子女);卡体量与逐字一致性;按卡算的提速空间;反馈迭代埋点方案。只调研不改线上 | 待领取 | 分支 `codex/consult-evidence-card-research-20260927`;与 BUG-1053 实现单并行,不碰 consult route / stream-agent-response |
| — (产品 09-27 拍板 D1–D3,直接执行) | `PROGRESS-consult-single-pass-answer-20260927.md` | **普通咨询回答没看过星盘(BUG-1053,引入 `04463e9a`,生产不受影响)**:本命主循环工具结果后那一步看得到证据、正文却被丢弃,用户看到的是另开的 compose 流(只有历史 + 问题、判断依据恒空)写的。D1 删 compose / interpret / drain,主循环最后一步的正文即回答(按步取答,调用工具的那一步正文整段丢);写作要求搬进用户轮;续写带计算结果;工具 110 秒不变,拿到计算结果后循环交给 70 秒答案钟,最坏 180 秒;BUG-1051 结算规则保留(按写回答那一步判定)。D2 观测字段名不变、含义改为写回答那一步 | 待验收 | `codex/consult-single-pass-answer-20260927`(本地,未推送);新回归 15 条用真实 `getJyotishAgent` + 记录提示词的假模型 + golden 计算数据;全量失败名单 0 新增;Python 948/1;`/` ○、gzip +0.24%;真机清单 `docs/testing/consult-single-pass-answer-20260927.md` |
| `TASK-scroll-anchor-hook-fixes-20260926.md` | `PROGRESS-scroll-anchor-hook-fixes-20260926.md` | **滚动锚两处老问题**:直接打开已有会话时监听未挂上(BUG-1043)、校正长回答钉顶后因 96px 阈值被拉到底(BUG-1044)。排在 BUG-1042 合入后。挂载改由容器元素本身驱动(每次提交比对元素 / active / resetKey);钉顶只由用户滚动手势解除 | 已验收(Claude 09-26 直接执行:子代理复现两处根因并修复;Claude 独立复验 tsc/lint 0、全量 3970 条失败名单与基线逐条一致、四路由 ○、gzip 不变;iOS 惯性滚动留真机清单) | `da2613ff`(随 `f1d16405` 部署,health 一致) |
| `TASK-latest-turn-actions-gap-20260926.md` | — | **最后一轮正文与点赞 / 踩之间空大半屏**:BUG-930 钉顶留白(`min-height: 视口 − 本轮开头`)加在 `.message-assistant` 上,把兄弟节点 `.message-actions` 推到留白之后;改为加在整轮外层,按钮紧贴正文、空白落在后面;不动滚动 hook | 已验收(Claude 09-26 直接执行:子代理实现,Claude 独立复验 tsc/lint 0、全量 3961 条失败名单与基线逐条一致、四路由 ○、gzip 不变;CDP 实测间距 450–600px → 23px,钉顶仍在) | `080ea5ca`(已部署 `509987b9`,health 一致) |
| `TASK-starter-home-polish-20260926.md` | `PROGRESS-starter-home-polish-20260926.md` | **首页开场小字与图标**:今日趋势(每日模型生成,非写死)移到问候下方副行;入口下方提示只在有未完成校正或非本人时出现,删两句固定文案并修正已校正仍显示首次文案的分支;今日星语图标 MoonStar、点数图标 Coins。排在 BUG-1038、1040 之后。分支误判实为入口摘要解析读错键名(BUG-1041) | 已验收(Claude 09-26 直接执行:子代理实现并查出 BUG-1041 入口摘要驼峰/下划线字段不一致;Claude 改恢复提示文案为「可以在历史对话里接着做」;独立复验 tsc/lint 0、全量 3960 条失败名单与基线逐条一致、四路由 ○、gzip 不变) | `f04da103`(已部署 `62d4c9c4`,health 一致) |
@@ -0,0 +1,70 @@
# 真机清单 · 普通咨询回答改由看过星盘的那一步写(BUG-1053)· 2026-09-27
部署含 `codex/consult-single-pass-answer-20260927` 的 staging 后照做。先确认 `https://staging.jyotisha.chat/api/health` 的 `deployment.gitCommit` 是这次部署的提交。
## 这次改了什么(给自己看的一句话)
以前本命提问算完盘后,看过星盘的那一步写的回答被丢掉,你看到的是另一个没看过星盘的步骤重写的,所以回答里的上升、月亮、宫位可能和星盘页对不上,或者直接说「没有盘面证据」。现在算完盘的那一步直接写给你。
## 准备
- 一个已校验星盘的账号(出生时间已确认的那种)。
- 另开一个标签页打开这个人的「星盘」页,停在本命盘,记下:上升星座、月亮星座与所在宫、太阳星座与所在宫。下面每一轮回答都拿来对照。
## 1. 默认模型:回答里的盘面事实对得上
1. 普通对话,默认模型,问:「我和父母的关系怎么样?」
2. 等它写完。
预期:
- 开头是几句没有标题的口语回答,然后是四个标题:先回答你的问题 / 盘里支持这个判断的地方 / 时间怎么看 / 这周可以做的一件事。
- 「盘里支持这个判断的地方」里提到的上升、月亮、宫位,和星盘页记下的一致。**只要有一处对不上,截图正文和星盘页一起发给我。**
- 正文开头**没有**「我先排一下盘」「我来调用工具」这类过程说明。
- 不再说「没有父母主题的盘面证据」这类话。
## 2. gpt-5.6-luna:同一个问题再问一次
1. 模型切到 gpt-5.6-luna,新开一个对话,问同一句「我和父母的关系怎么样?」。
预期:同第 1 条。以前这个模型会直接说没有盘面证据;现在应当引用和星盘页一致的事实。
## 3. 换个领域再对一次
1. 默认模型,问:「我明年的事业和财运怎么样?」
预期:同第 1 条;另外「时间怎么看」里提到的大运 / 年份,和星盘页「大运」栏大致对得上(不要求逐日)。
## 4. 等待时间
对第 1–3 条各记一次:从点发送到最后一个字出来,大约多少秒。
预期:
- 一般比以前快(少了一次重写);最慢不超过约 3 分钟。
- 活动区一直有进度:读取方法 → 计算本命盘 → 思考行 → 正在组织回答。
- 第一段字出现前会有一两秒停顿(要等写出第一个小标题或约 160 字才一起出来),之后是连续出字,这是预期,不是卡住。
## 5. 首页「深入看今日」
1. 首页点「深入看今日」。
预期:正文是三节(「今日趋势」「适合推进 / 需要避开」「一个行动」),**不是**本命的四个标题;最后一节有技法审计表和「探索性日提示,不是确定预测」。
## 6. 没写完的回答(平时留意即可)
这一条很难故意制造。遇到时对照:
- 正文停在最后一个完整的句子上。
- 输入框上方出现「回答未完成,已保留现有内容;本次不会扣点。」
- 点数不变;刷新后那段没写完的回答还在。
## 7. 后台核对(管理员账号,可选)
1. `/admin/consultations` 找到第 1–3 条:状态 `completed`。
2. `/admin/usage` 同一时间的那几行:耗时不超过约 `180000 ms`。
## 发现问题时发我什么
- 对不上的那一轮:正文截图 + 星盘页截图 + 用的哪个模型 + 大概时间。
- 等了很久的那一轮:秒数 + 模型 + 大概时间。