Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
9.4 KiB
9.4 KiB
PROGRESS · 生时校正开场改大白话 + 步骤回执去重(2026-09-26)
- 模式:直接执行(产品授权 subagent 实现;无单独任务书,决策 D1/D2 由 Claude 转述)
- 基线:
origin/staginge53052a2 - 分支 / worktree:
codex/rectification-opening-plain-20260926/.worktrees/rectification-opening-plain-20260926(本地提交,未推) - BUG:BUG-1049(开场无例子 + 行话,复发自 BUG-504)、BUG-1050(步骤回执内部名 + 重复)
- Skill:10.0.30 → 10.0.31
诊断核对
Claude 的诊断成立,补充两点:
- 例子丢失是两步叠加:
aa7ccb30(09-09,BUG-604)把例子从GENERIC_COLLECT_QUESTION挪进正文第三句,同时把 BUG-504 的断言改成反向(题干不含「比如」);dd8f35f7(09-11,BUG-646~648)把第三句改写成以题干前 12 个字开头,BUG-585 的前缀去重(4e0db55f起)因此把它删掉。09-11 起刷新路径看不到例子,BUG-1045(e4c1c7a3)后实时路径也看不到。BUG-504 的测试没拦住,是因为它被 BUG-604 有意改反了,而接替它的正文检查只测正文字符串,没有走 GET 组装 / 客户端合并。 - 模型写的开场正文在服务端也先被同一去重剥掉例子句 → 不满足「至少五类」→ 换兜底正文。所以真机看到的是兜底正文去掉第三句,而不是模型的原话。
- 步骤重复:持久化回执按工具去重,但实时轨迹每次调用一行,结算后保留实时轨迹;「已完成 3 步」数的是调用次数。刷新后才变两行。
决策落地
| 决策 | 实现 |
|---|---|
| D1 正文 | openingSpokenBody:两句,逐字按产品文案;无窗口时省掉「现在先在…之间找」。buildOpeningBrief 与 agentic-rectification.ts 开场说明同一意思。模型正文验收 isAcceptableOpeningBody(body, range):须含「星盘」「年月」与窗口两端,≤3 句,无问号 / 年份 / 行话(OPENING_BODY_JARGON:大运、盘面、分盘、代表分钟、精确到秒、候选、区间、Dasha),最多提 2 个例子;否则换兜底。 |
| D1 题干 | GENERIC_COLLECT_QUESTION 逐字按产品文案(74 字,低于 SPOKEN_PROMPT_MAX 120)。新增:零证据开场题干由服务端固定——rectification-set-focus 仍校验模型的 spokenPrompt(坏调用照旧失败、照旧计数,BUG-586 的「两次无效不落库」不变),校验通过后存 GENERIC_COLLECT_QUESTION,不存模型改写。判定抽成 isOpeningCollectFollowup(与 spokenFollowupForUser 原 openingOther 条件相同)。理由:只靠提示词让模型照抄题干,例子迟早会被改写掉,这正是 BUG-504 这一类的防线。brief 因此改成「spokenPrompt 写『先说一两件你记得的大事』即可,题干由服务端固定」,brief 本身仍不含年份(既有断言)。 |
| D1 题干其他用途 | GENERIC_COLLECT_QUESTION 只在零证据开场使用(spokenFollowupForUser 的 openingOther 分支);另两处是文案清单 listUserVisibleCopy 与事故回放夹具 accidentCaseHardcodedTurns.openingCollect,都代表开场。无需拆分。 |
| D1 年份 | 示例回答里的 2015 只在题干;正文仍禁止年份(OPENING_YEAR 只作用于正文);题干没有年份校验路径(validateSpokenPrompt 的年份校验只对 choice_frame 题)。「不得用生日推年份」不受影响,Skill 里注明示例年份是固定文案。 |
| D1 去重 | isQuestionSentence:正文句与题干整体或题干任一句相同(去空白、句末标点),或字符二元组 Dice ≥ 0.8(STEM_NEAR_EQUAL_THRESHOLD)才算复述;以问号结尾照旧删除;删去 12 字前缀规则。BUG-584/585/1045 相关测试全部照旧通过。 |
| D1 范围句 | 开场不再说「最后给区间和代表分钟,不给精确到秒」。检查过:VOICE / DESIGN 没有要求开场必须说;Skill §4 原来要求(已改);交付卡 REPRESENTATIVE_MINUTE_DISCLAIMER 未动。 |
| D2 标签 | rectification-activity-labels.ts 十四个完成名、十四个进行中句、六个点选活动句全部改大白话(对照表在 VOICE「生时校正开场与步骤名」)。进行中句复用 BUG-1047 已批准的三句。慢步骤句改为「还在 + 进行中句」(原先拼接完成名,改成过去式后读不通)。 |
| D2 去重 | rectificationTimelineRows 对已完成步骤按显示名去重(保留第一行;进行中、失败行不动),rectificationCompletedTrail 同样去重。失败行改为「进行中句去掉『正在…』+ 未完成」(「重新对照盘面未完成」),避免「重新对照了盘面未完成」。BUG-1047 阶段句逻辑未动。 |
改动的既有断言(均带原值 / 新值 / 原因注释)
agent-voice-copy-contract.test.ts「opening body lists domains…」:正文 ≥5 例子 → ≤2 且六个例子都在题干;正文含范围句 → 不含范围句与行话;题干不含「比如」→ 新题干逐字、含「比如」「例如」。rectification-server-focus.test.ts:题干匹配 /先说你最容易想起的一两件/ → /先说一两件你记得的大事,比如/;「GENERIC_COLLECT_QUESTION invites…」逐字与源码锁改为新题干,年份断言由「无年份」改为「唯一年份是示例里的 2015」。rectification-v9-agent.test.tsbrief 断言:旧题干 → brief 写明题干服务端固定、两句正文、不重复例子、不含范围句与旧题干(仍不含年份)。agent-activity-progress.test.ts、rectification-adopt-flow-20260902.test.ts、rectification-agentic-entry.test.ts、rectification-timeline-adapter.test.ts、rectification-latency-20260926.test.tsx:旧步骤名 → 新步骤名(后两处另加断言,不弱化)。- 版本号:
skill-registry.test.ts(sha51a91251…13c1)与 16 个测试文件里的10.0.30→10.0.31(18 处字面量 + 4 处version:正则)。遥测夹具里的10.0.30是任意样例值、不绑定当前版本,未改。
新增测试
frontend/tests/rectification-opening-plain-20260926.test.ts(7 条):(a) 零证据题干含比如 / 例如 / 六例 / 唯一年份 2015;带日期经历或重问时不用;模型改写 spokenPrompt 时 set-focus 存服务端题干。(b) 服务端拼接、GET 组装、客户端合并三路正文两句都在、题干 1 次;09-26 staging 旧正文例子句在新去重下保留;逐句 / 近似复述仍删。(c) 正文无行话、旧兜底与一句招呼不被接受、窗口不对不被接受。(d) read-case + set-focus×2 → 两行、「已完成 2 步」;共用名字只一行;全部步骤名无内部词。frontend/tests/rectification-opening-plain-20260926.test.tsx(2 条):真实RectificationAgenticChat自动开场(流式 → 结算 → 快照合并),正文与题干各种存法下都只显示一次题干、六例各 1 次、开场这一轮无行话、回执「已完成 2 步」。
修复前验证:把 e53052a2 的 collect-prompt.ts 单独取出实跑,旧兜底正文 + 旧题干经 stripQuestionSentences 的输出恰好是真机看到的两句(例子句被删),与真机一致。另两项按代码推断、未在旧代码上实跑:旧 set-focus 直接存模型的 spokenPrompt(withSpokenPrompt(…, spoken.prompt));旧 rectificationTimelineRows 逐条映射实时轨迹,read-case + set-focus×2 得三行「已完成 3 步」。
验证(Node 22.14,/exec-daemon)
| 项 | 结果 |
|---|---|
tsc --noEmit |
0 错 |
npm run lint |
0 error,128 warning(与基线同一批文件、同数) |
npm test |
4054 tests / 4002 pass / 24 fail / 28 skip;基线 4045 / 3992 / 25 / 28。失败名单 0 新增;基线的「Gitea quality gate validates before publishing an immutable ACR manifest」在本分支通过(e53052a2 恢复了 upload-artifact 文件,基线日志取自其前);24 条均为 Docker/DB。测试名 0 消失、9 条新增 |
| Python 门禁集 | 948 passed / 1 skipped |
npm run build -- --webpack |
/ ○ Static;rootMainFiles gzip 130933 B(基线 130933,0%) |
| 浏览器 | next start + Chrome 无头 + CDP 虚构接口,自动开场:题干 1 次、正文两句各 1 次、「已完成 2 步」、行「看了你的资料」「准备好下一个问题」、开场这一轮无行话;截图 docs/testing/rectification-opening-plain-20260926/(390 / 1280,收起 / 展开) |
环境缺口
- 无登录态真机、无模型凭据:模型实际写出的开场正文是否通过新验收(否则用兜底)、真实开场的步骤序列,留给
docs/testing/rectification-opening-plain-20260926.md。 - 未推送、未部署。
验收(Claude,2026-09-26)
独立复跑(Node 22.14,基于 e53052a2):tsc 0;lint 0 error;npm test 4054 / 24 fail / 28 skip,对照 cs-test.log(4045 / 25)失败名单仅少一条(「Gitea quality gate validates before publishing an immutable ACR manifest」因 e53052a2 恢复 vendored 文件转绿),无新增失败、无消失测试名;Python 门禁集退出 0;/ ○ Static,rootMainFiles gzip 130933 B(±0%);提交无删除、未碰 .gitea/、vendor/。截图核对:开场正文两句大白话、题目带六个例子和答法示例且只出现一次、步骤栏「已完成 2 步:看了你的资料 / 准备好下一个问题」。真实模型开场通过率待真机清单。