merge origin/staging into the release-path fix branch

Co-Authored-By: Grok (agent loop)
This commit is contained in:
jesse-ux
2026-10-14 15:54:45 +08:00
co-authored by Grok (agent loop)
105 changed files with 23235 additions and 7982 deletions
@@ -0,0 +1,66 @@
# 磁盘缓存留存 A/B(2026-10-14)
对照的是本分支的父提交 `66cd60081f37a57680274633fcb3fb942d01bb2f`(建分支时的 `origin/staging`)。任务书里写的 `77057a819` 已经不是当前测试线头。A 用 `git show` 把父提交的接口文件载入同一进程,并把它的仓库路径指回本工作树,否则临时副本找不到引擎。B 是本分支。
演练用虚构盘,不写真实出生资料。文件都在系统临时目录,不写工作树里的 `scratch/`。
主测量挡住了 `jhora` 和 `vedastro` 的导入。本机装了 VedAstro SDK,并且能连上官方端口;另有一组不挡 SDK、但仍关闭外网取数,见文末。
## 命令
```powershell
.venv\Scripts\python.exe scripts\research\api_chart_cache_byte_diff.py
.venv\Scripts\python.exe scripts\research\api_disk_cache_ab.py
.venv\Scripts\python.exe scripts\research\api_disk_cache_ab.py --with-sdk --sdk-probe
```
## 命中率
20 张虚构盘 × 3 种写法 × 快速/完整 × 7 天 × 每种重复 3 次 = 2520 次取键。取键用的是真实缓存键函数,没有把 2520 次都做成完整排盘。
| | 改前 A | 改后 B | 变化 |
| --- | --- | --- | --- |
| 不同缓存键 | 840 | 280 | 少 560 |
| 命中次数 | 1680 | 2240 | 多 560 |
| 命中率 | 0.6667 | 0.8889 | B / A = 1.333 |
目标是混合写法下 B 至少为 A 的 2.5 倍。按任务书规定的「重复 3 次」算,没有达到:A 自己靠重复就已经有三分之二命中,写法合并只能再抬到约 89%。若不算这 3 次重复、只看三种写法各问一次,A 的命中率是 0,B 是 0.6667。目标数字不改。
## 七天后的文件
留存演练写的是短记录,用来数文件,不是完整盘面。期限 900 秒,只有当天的键还没过期。
| | 改前 A | 改后 B |
| --- | --- | --- |
| 清理前文件数 | 840 | 280 |
| 清理前字节 | 109200 | 36400 |
| 清理后文件数 | 840(旧代码没有这份清理) | 40 |
| 当天仍有效的键 | 120 | 40 |
B 清理后的文件数等于当天有效键数,达到「不超过当天活跃键」的目标。
审计文件:B 在默认关闭时写出 0 个。达到目标。
负缓存:种入当天和前一天各一份,清理后剩 1 份(当天)。达到目标。
## 清理耗时
| 场景 | 结果 |
| --- | --- |
| 预置 10000 个已过期排盘缓存后,整次清理 | 20.174 秒,排盘目录 20170.902 毫秒,删掉 10000,剩下 0 |
| 上面七天演练里的排盘目录 | 370.161 毫秒 |
目标是 10000 个文件在 2 秒内、且不在请求线程。本次在后台函数里测,不在请求线程;耗时没有进 2 秒。这是 Windows 上逐个读文件再删除的实测,目标不改。默认清理间隔仍是 1800 秒,失败快照短期限仍是 300 秒,不因为这次没进 2 秒就改默认值。
## 排盘耗时(一次虚构盘,快速排盘,外网关闭)
| | 中位数 |
| --- | --- |
| 未命中 3 次 | 23.036 毫秒 |
| 命中 3 次 | 5.249 毫秒 |
## 响应是否还是同一张盘
数值等价的写法(小时 12 / 12.0 / "12",纬度数字和字符串,时区 5.5 和 "5.5",秒缺省和 0)在快速排盘下去掉 `runtime_cache` 后逐字节相同。完整排盘只差官方快照缓存上的写入时刻和到期时刻,盘面没有别的差异。父提交和本分支对同一张快速排盘、去掉 `runtime_cache` 后逐字节相同。因此这些字段可以合并进同一把缓存键。
不挡 SDK 的一组:本机有 VedAstro SDK,官方端口能连通。探针仍关闭外网取数。一次完整排盘 4.167 秒,没有报错。没有拉取真实快照。
+3 -3
View File
@@ -8,11 +8,11 @@
| 1 | 新人第一次进站 | 一个从没用过的邮箱;手机 Safari | 打开登录页 → 勾选同意 → 输入邮箱 → 发验证码 → 输入固定码 → 填出生资料(城市、日期、时间) | 不要求设密码;建盘后先看到群星汇聚过场,**不先弹兑换窗**;过场后进入首页 | BUG-1080、1152;`staging-otp-skip-password-20261001.md`、`birth-sky-cover-checklist.md` | | | |
| 2 | 首页 | 第 1 条的账号 | 停留首页、刷新一次 | 不卡在「正在载入账户」;今日星语有当天内容(不是「没写出来」);会话列表正常 | BUG-936、283 / 299;`home-first-load-20260930.md`、`session-list-rebuild-20260921.md` | | | |
| 3 | 寒暄不扣点 | 记下当前点数 | 新对话发「你好」 | 一句简短回应,不排盘、不出长解读;点数不变 | BUG-976、977;`consult-smalltalk-fastpath-20260920.md` | | | |
| 4 | 普通对话 + AI 标识 | 有点数 | 问一个事业问题,再追问一句 | 回答几段人话、不念内部清单;输入框下方有「回答由 AI 生成,仅供参考……」一行;iPhone 上正文右侧无大块空白、不抖;收起键盘页面不上移 | BUG-1252、1253、1255、920、内测主路径单 T2;`consult-readable-20261006.md`、`mobile-viewport-scroll-lock-20260917.md` | | | |
| 4 | 普通对话 + AI 标识 | 有点数 | 问一个事业问题,再追问一句;再打开一条生时校正看输入框 | 回答几段人话、不念内部清单;两处输入框下方都有「回答由 AI 生成,仅供参考,不构成医疗、法律或投资建议。」,窄屏不换行、不挡住发送;iPhone 上正文右侧无大块空白、不抖;收起键盘页面不上移 | BUG-1252、1253、1255、920、1347、内测主路径单 T2;`consult-readable-20261006.md`、`mobile-viewport-scroll-lock-20260917.md` | | | |
| 5 | 明说要校正 | 档案出生时间是「大约」 | 新对话说「帮我做一下生时纠正」;另开一个对话说「这个解读我不认同」 | 第一句直接进入校正,不先写解读;第二句**不**进入校正,只改读法 | BUG-1306、1317;`rectification-explicit-entry-20261012.md` 第 1、1b、4、9 步 | | | |
| 6 | 校正开场 | 第 5 条进入的校正 | 看开场三句 | 说出填的时间离最近换段差几分钟、两边哪几件事不同;离得近时有「这里连本命上升都换」;不出现秒、「记录时间是错的」 | BUG-1307、1309;`rectification-nearest-boundary-opening-20261012.md` | | | |
| 7 | 人物档案不串人 | 人物档案里加一位家人 | 切换到家人 → 设为默认 → 回到本人 → 再切家人 | 每次显示的资料都是对应的人,名字、出生资料不串 | BUG-1030;`people-archive-p1-20260924.md` | | | |
| 8 | 给别人出报告 | 第 7 条的家人;有点数 | 选家人 → 生成报告 → 等完成 → 打开 | 报告能生成完成(不一直排队、不失败退款),标题下有「本报告由 AI 生成,仅供参考。」 | BUG-1063、内测主路径单 T1/T2 | | | |
| 9 | 本人报告 | 本人 | 生成一份中文完整报告并打开;切英文看一眼 | 开篇重点卡正常;英文版无中文残留;结尾免责在 | BUG-1312~1316;`report-translation-gaps-20261013.md`、`report-focus-card-20261013.md` | | | |
| 8 | 给别人出报告 | 第 7 条的家人;有点数 | 选家人 → 生成报告 → 等完成 → 打开 | 报告能生成完成(不一直排队、不失败退款),标题下有「本报告由 AI 生成,仅供参考。」 | BUG-1063、1347、内测主路径单 T1/T2 | | | |
| 9 | 本人报告 | 本人 | 生成一份中文完整报告并打开;切英文看一眼 | 开篇重点卡正常;中文标题下有「本报告由 AI 生成,仅供参考。」,英文标题下是 “This report is AI-generated and for reference only.”;英文版无中文残留;结尾免责在 | BUG-1312~1316、1347;`report-translation-gaps-20261013.md`、`report-focus-card-20261013.md` | | | |
| 10 | 反馈与注销 | 任一测试账号 | 对一条回答点踩并写一句反馈 → 后台「反馈」页查看;账户设置里申请注销 → 再撤销 | 后台能看到反馈;注销申请显示 7 天冷静期,撤销后账户恢复 | `surface-feedback-20260929.md`、`legal-consent-20260930.md`、`compliance-launch-20260930.md` | | | |
| 11 | 限流与排队(容量单合入后) | 两台设备同一账号 | 1 分钟内连发 7 次提问;另找 3 个账号同时做校正 | 第 7 次得到一句「太快了,稍等一下」类提示,不扣点;同时校正的人看到「排一下队」后照常继续,不报错 | 内测容量单 T1/T2 | | | |
@@ -0,0 +1,36 @@
# 发问准备并行:本轮量到的和没量到的(2026-10-14)
开关都还关着。用户发问后的第一行,这轮不会变快。
## 进程内假时钟
命令:`node node_modules/tsx/dist/cli.mjs tests/consult-prep-parallel-ab.mts`(在 `frontend` 目录)。
假延迟:注销检查 50 毫秒,读会话 80 毫秒,解析模型 80 毫秒。这不是数据库实测。
| | 逻辑耗时 | 同时进行的步数 |
| --- | --- | --- |
| 串行 | 210 | 1 |
| 并行 | 160 | 2 |
并行比这三条假延迟的相加更短。它不能代替「首帧中位数下降两成」的开启条件,因为本机没有量 Postgres。
审核密钥不在这台机器上。测试里把审核挂起 1500 毫秒,第一小段在 400 毫秒内已经写出,然后才收到拦截。这是假等待,不是供应商的真实时间。
## 版本缓存
行为测试:15 秒内第二次解析不再查库、不再做地址检查;清缓存后会再查;缓存关掉后每次都查;查库失败和空结果不会被记住。没有量到真实「准备模型」那一段快了多少,所以缓存时间保持 0。
## 两个领域一起算
命令:`.venv\Scripts\python.exe frontend\scripts\research\consult-domain-concurrency-ab.py`
本轮没有启动计算服务,也没有带星盘网络库的镜像。任务书起草时的试算大约只快一成,热缓存时反而更慢,达不到快两成五。默认仍是一个一个算。
## 仍然关闭的原因
| 开关 | 现在 | 要打开还缺什么 |
| --- | --- | --- |
| 发问准备并行 | 关 | 本机 Postgres 上鉴权、注销检查、读会话、读模型各 30 次的中位数,并且首帧中位数至少快两成 |
| 模型版本缓存 | 0 毫秒 | 同上,准备模型那一段至少快一半 |
| 两个领域一起算 | 1 | 带星盘网络库的镜像上墙钟至少快两成五,争用时 429 不增加,响应除约定字段外一致 |
@@ -0,0 +1,61 @@
# 长报告出稿 A/B(2026-10-14)
Windows 本机,Python 3.11.7,`Windows-10-10.0.26200-SP0`。屏蔽 PyJHora(生产镜像不装这个库)。本机本身也没有 PyJHora,所以没有再跑一轮不屏蔽的重复计时。计时开了 tracemalloc,绝对秒数比任务书里的 Linux 基线高,只比较同一进程里的 A 和 B。
A = 两个开关关。B = 两个开关开。四张虚构盘,每组 3 次。生产请求是完整数据版、markdown、中英都要、带事实表。没有模型钥匙。
## 端到端(未命中,秒)
| 盘 | A 三次 | A 中位 | B 三次 | B 中位 | 下降 |
| --- | --- | --- | --- | --- | --- |
| day | 71.31 / 64.03 / 64.01 | 64.03 | 51.05 / 50.77 / 51.74 | 51.05 | 20.3% |
| night | 66.25 / 66.11 / 66.66 | 66.25 | 53.32 / 52.57 / 50.43 | 52.57 | 20.7% |
| south | 66.03 / 66.00 / 62.69 | 66.00 | 49.97 / 52.79 / 52.68 | 52.68 | 20.2% |
| section2 | 71.01 / 108.37 / 74.19 | 74.19 | 57.42 / 57.12 / 71.80 | 57.42 | 22.6% |
门槛是未命中端到端下降至少 35%。四张盘都没到。渲染快捷路径默认关闭。
## 分段中位数(秒)
| 盘 | 中文渲染 A → B | 英文渲染 A → B | 建包 A → B |
| --- | --- | --- | --- |
| day | 23.55 → 17.04(−27.6%) | 8.27 → 8.67 | 22.55 → 16.08 |
| night | 23.42 → 17.19(−26.6%) | 8.75 → 8.41 | 23.70 → 17.21 |
| south | 23.89 → 17.39(−27.2%) | 8.66 → 8.74 | 22.90 → 16.87 |
| section2 | 22.26 → 17.80(−20.0%) | 8.14 → 8.54 | 31.24 → 21.08 |
中文渲染门槛是下降至少 40%。没到。没有继续加整篇替换的预检。
## 内存与字节
tracemalloc 峰值:B 约为 A 的 0.87 到 0.88,没有升高。
五份输出(整份响应、中文、英文、事实表、适用性)A、B 未命中、缓存命中的 sha256 全部相同。
| 盘 | 响应字节 | 响应 sha256 前 12 位 |
| --- | --- | --- |
| day | 2289867 | 5b542359d606 |
| night | 2321638 | 89baa960c054 |
| south | 2314369 | 250bf1ab246e |
| section2 | 2238092 | 1d7afd481b1a |
## 同盘缓存(命中,秒)
| 盘 | 三次 | 中位 |
| --- | --- | --- |
| day | 0.059 / 0.054 / 0.057 | 0.057 |
| night | 0.057 / 0.054 / 0.058 | 0.057 |
| south | 0.059 / 0.054 / 0.057 | 0.057 |
| section2 | 0.063 / 0.066 / 0.057 | 0.063 |
命中字节与未命中相同,中位数远低于 1.5 秒。缓存开关默认开。`GITHUB_SHA` 缺失或为 `unknown` 时仍然关。
## 单次溯源哈希(交付包,秒)
关:1.132 / 1.099 / 1.115,中位 1.115。开:0.402 / 0.466 / 0.388,中位 0.402。下降 64%,过了 50% 那一档。它跟渲染快捷路径用同一个开关,所以默认也是关。
## json 与 reference 版
同一份解盘、时钟钉死后,`format=json` 和 reference 版 markdown 在快捷路径关与开时 sha256 相同(`aa1352619b7a`、`cbadf95f549a`)。对比的是整份响应,没有丢掉字段。
连续两次重新解盘会对不齐:有的特质列表挂在类上,第二次会再追加。那不是这条快捷路径改出来的。生产要的完整数据 markdown 在多次重算里仍然逐字节相同。