docs(memory): 记录第二批修复与「Python write_text 会改行尾」这个坑

- 2026-10-29.md:第二批 9 项改动与验证数据(含投票结果 2 万条 0.211s→0.023s),
  以及剩余待办清单(级联删除事务、配额漂移、JSON-LD/RSS、箱主数据面板等)
- MEMORY.md:构建测试段补 write_text 行尾陷阱与排查手法(看 git diff --stat / git show),
  其它约定段补 /healthz 与 /readyz 的语义边界(存活探针不查依赖)
- topics/quality.md:标注第二批已完成的范围

附带说明:本轮我自己也踩了 write_text 的坑,把 14 个 LF 文件写成了 CRLF,
靠 git diff --stat 的「整文件重写」发现、再用 git show HEAD:<file> 的行尾比对恢复。
This commit is contained in:
tamakyi
2026-10-29 16:29:02 +08:00
parent 03cb5ddcf0
commit 89e263cbd4
3 changed files with 57 additions and 4 deletions
+45 -2
View File
@@ -60,7 +60,50 @@ gzip 实现质量高、后台移动端短标签方案做得细。
- Python 的 **bytes 字面量不支持 `\uXXXX`**(只有 str 支持),写字面量 `b'...\uff08'` 会原样写入
`\uff08` 六个字符。CRLF 文件的字节级替换要用 `\xef\xbc\x88` 或 `.encode()`。
### 第二批(P2 + 高价值 P3,Docker 按用户要求跳过)
| # | 改动 | 验证 |
|---|---|---|
| 7 | ReadTimeout 30s→120s(8MB 图需 ≥68KB/s;ReadHeaderTimeout 仍 10s 防 slowloris) | 参数修正 |
| 8 | 投票结果改 stale-while-revalidate:过期先返旧值 + 后台按投票去重重算;Submit 从「删缓存」改「标记过期」(新增 `cache.Expire` / `GetWithExpiry`) | 2 万条:冷启 0.211s → 过期首读 0.023s(9.2x) |
| 9 | 三处幂等:`MarkDeletedByOwner` 条件更新+RowsAffected、`SetPinnedIfCurrent`、追问「上一条已回复」移进事务 | DB 测试 3 项全过 |
| 10 | 私聊首条三写入合并为一个事务(`CreateWithFirstMessage`) | message_count 与实际消息数一致 |
| 11 | `/healthz` + `/readyz`(DB ping 失败 503) | 停 PG 后 healthz 200 / readyz 503 |
| 12 | 验证码失败改同请求渲染,不再丢正文 | 200 + 正文回填 + 不建提问 |
| 13 | `tbBeginSubmit()` 抽出,reCAPTCHA 回调补防重复 | 静态验证(7 个模板受益) |
| 14 | waline 按页加载、`loading="lazy"`、safe-area、三处硬编码接字典(+4 key×4 语言) | /login 无 waline;en 页面零中文残留 |
| 15 | 5 处裸类型断言改带 ok | 编译 + 单测 |
新增 `verify_round3.py`(6 项)。第二批回归:6/6、4/4、19/19、6/6、3/3,全量单测 + build 通过。
**判据随实现更新**:`verify_p1_fixes.py` 的 p1-2b 原来用「是否 302」判断验证码先于密码,
第 12 项改成 200 后判据失效 → 改为「200 且页面报『验证码错误』」。语义不变,判据跟着渲染方式走。
### 这次踩的第三个坑(重要,我自己造成的)
**Windows 上 `Path.write_text()` 默认把 `\n` 转成 `\r\n`**,用它改 LF 文件会让整个文件行尾翻车。
- 症状:`gofmt -l` 突然把整文件标为未格式化。
- 后果:`git diff --stat` 会显示整文件重写。
- 正确写法:`path.write_text(s, encoding="utf-8", newline="\n")`,或用 bytes。
- **排查手段**:`git diff --stat` 是判断行尾污染最快的信号 —— 真实改动应该只有几十行,
整文件重写一定是行尾变了。恢复方式:`git show HEAD:<file>` 取其行尾,再统一替换回来。
另:本项目 `core.autocrlf=true`,仓库里存 LF、工作区 checkout 成 CRLF,
所以「工作区看到 CRLF」不等于「仓库里是 CRLF」,判断基准要看 `git show`。
### 待办
六项改动仍未 commit;P2/P3 清单在 `outputs/review-2026-10-29.md` 第四、五节。
建议下一批:投票结果聚合 O(N²)、三处幂等缺陷、ReadTimeout 30s 与 8MB 上传冲突、Dockerfile 构建不出来。
本批改动已 commit。剩余清单在 `outputs/review-2026-10-29.md` 第四、五节,尚未做的:
- 删除投票的级联 4 步无事务(`route/user/vote.go:1048-1076`)
- 配额递增失败只 Warn → `quota_count` 与真实行数永久漂移(3 处调用点)
- 改写追问回答会重复发「您的提问有回复」邮件
- `isQuestioner` 用裸 `==` 比 token(与中间件口径不一致)
- CSV 导出选项内容未做公式注入转义
- `FeatureStateOf` 查询异常时 fail-open
- AutoMigrate 无版本化(改列名会静默丢数据)
- 无备份脚本(用户图片全在对象存储,只备份 DB 恢复后全是裂图)
- 32 个 `<label>` 无 `for=`、语义标签对比度 1.9:1
- 真 404 页(现在全 302 到首页)、500 纯文本页
产品向(`review-2026-10-29.md` 第六节,按 ROI):提问者用 localStorage 记住自己的提问、
箱主数据面板(全站无 page view 数据)、Telegram/Webhook 通知、JSON-LD + RSS、图片前端压缩。
+7
View File
@@ -24,6 +24,11 @@
`[recaptcha] captcha_type = math`、Windows 侧 127.0.0.1:5877 被占要用 WSL eth0 IP。
HTTP 端到端与 P1-3 的双路径 A/B 都能在这里做(回环=可信、跨主机=不可信)。
- python urllib 不稳定(用 curl);python 别用 `/tmp`;PIL 在 `~/.workbuddy/binaries/python/envs/default`。
- **Windows 上 `Path.write_text()` 默认把 `\n` 写成 `\r\n`** —— 改 LF 文件必须传 `newline="\n"`
或走 bytes,否则整个文件行尾翻车。症状:`gofmt -l` 突然把整文件标为未格式化。
**排查看 `git diff --stat`**:真实改动应是几十行,整文件重写就是行尾变了;
恢复用 `git show HEAD:<file>` 取其行尾再统一替换。
另:本项目 `core.autocrlf=true`,仓库存 LF、工作区 checkout 成 CRLF —— 判断基准要看 `git show`。
## 行尾 / 模板 / embed(topics/embed.md)
@@ -86,6 +91,8 @@
## 其它约定(topics/misc.md)
- 健康检查:`/healthz` 永远 200(不碰任何依赖,只看进程活着)+ `/readyz` 查 DB(失败 503)。
别把 DB 检查并进 healthz —— 数据库抖动会让进程被反复重启,对恢复毫无帮助。
- 校验用 `valid:"required;maxlen:N"` 标签。
- 只有箱主 `/user` 面板,**无管理员角色、无站方后台**(用户要求不要加):站方动作只走 CLI / 邮件 / 改配置重启。
- CLI 有两个构建入口必须同步:根 `go build .` 与 Dockerfile 的 `./cmd/`。
+5 -2
View File
@@ -2,8 +2,11 @@
安全向的结论在 `sec.md`。这里是非安全向的四类,完整清单见 `outputs/review-2026-10-29.md`。
> **状态**:下列「已实测确认的缺陷」「处置覆盖面」「Redis」三块已于同日修复并端到端验证,
> 条目保留是为了记住**为什么**会踩、以及验证该怎么做。P2/P3 仍未动。
> **状态**:下列「已实测确认的缺陷」「处置覆盖面」「Redis」三块已于同日修复并端到端验证。
> 紧接着做了第二批(P2 + 高价值 P3,共 9 项):投票结果 stale-while-revalidate、
> 三处幂等、私聊首条事务、`/healthz` `/readyz`、验证码失败保正文、`tbBeginSubmit`、
> waline 按页加载 / lazy / safe-area / i18n、5 处裸断言。
> 条目保留是为了记住**为什么**会踩、以及验证该怎么做。
## 已修:两个 P0(都是实测出来的)