Files
rond-with-you/.workbuddy/memory/2026-10-01.md
T
tamakyi 5c7cf1a0e1 对访客公开的措辞按身份分支:访客不该看到「我的结论」
用户发现未登录也显示「推荐 & 踩雷(我的结论)」,访客没法解读「谁的我的」。
顺着把访客可见模板与 static/js 全过了一遍,同病共四处——都是**写模板时站在站长视角下笔、
而那一块又对访客公开**:

1. stats.html:标题 → {{if .IsAdmin}}我的结论{{else}}站长结论{{end}};
   副标题「只统计你自己…」→ 站长「你自己」/ 访客「站长」;两列「我推荐/我踩雷的地点」同理。
2. stats.html 访客块:「与我的结论互不影响:你标你的,访客投访客的」——对访客说不通,
   改成对两边都成立的「与上面的站长结论互不影响:各存各的表,谁也不会覆盖谁」。
3. home.html:「我的标签」→「足迹标签」(同级卡片全是中性的:足迹地图/城市足迹/天气足迹…)。
4. report.html:「这一年里,你第一次踏足的这些城市」→ 去掉人称(年报是站长的回顾)。

已经写对的照它学:place.html 的投票区早就是 {{if .IsAdmin}} 分支(站长「我的结论」、
访客「大家怎么说」),rond-map.js 的气泡同理;「含家/工作」chip 与一串「只有你自己能看到」
本来就在站长分支里。

门禁 TestVisitorPagesUseThirdPersonCopy:以**访客 ctx(无 user)**渲染 /、/stats、/report,
逐个禁用词断言,同时断言站长那份**仍旧说「我的」**(别把站长自己的视角也改掉);
前置需打开 marks_public(访客才看得到那一块),用完还原。

⚠️ 变异验证时踩了老坑:直接 `go test -run …` 因缺 ROND_TEST_CONF/ROND_SRC 会**静默 skip 并报 ok**
(0.17s 就 ok,一眼假绿)。改用 ./scripts/verify.sh 后变异被正确抓住
(visitor_copy_test.go:85 报「我的结论」),还原后转绿。

全量验收 PASS=339 FAIL=0 SKIP=0。
2026-10-01 02:15:49 +08:00

73 lines
5.6 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.
# 2026-10-01
## 防复发:把「删数据集带走自建数据」做成结构性门禁(00:30)
用户放弃继续救那批旧图:「我只想避免类似的事件再次发生」。于是把这次的教训固化成三件东西
(`internal/web/dataset_ownership_test.go` + `schema.sql` 抬头 + README 新章节):
1. **归属铁律**:判断标准只有一句——**这份记录能不能从备份重新导入?**
能(places/visits/movements/weather/activities/tags/entity_raw)⇒ 可挂 CASCADE;
不能(place_images/place_notes/place_votes/topics)⇒ 只留 dataset_id 当出处、不许挂外键。
2. **两道门禁**:运行时查 `pg_constraint`(表必须在白名单里,反向也查)+ 静态扫 `schema.sql`
(新建的库走 CREATE TABLE,只看运行时有盲点)。做变异验证时确认了静态那条**真的会响**。
3. **体检常驻后台首页**:库里 N 张 / 本地盘上 M 个 / 落单 K 个(`imageHealth`),落单 >0 直接报警。
事故的本质不是「删数据集」本身,而是**行与对象悄悄对不上、没人发现**——让它当场可见。
变异验证的收获(比测试本身更有价值):
- 运行时门禁单独看**不够**:夹具每次跑迁移,迁移自己就把坏外键摘了 ⇒ 它永远不会在不健康的库上报警。
补了 `TestMigrationDropsStaleDatasetForeignKeys`:注入事故原样的外键再跑迁移,断言被摘掉。
- 这条自愈用例又抓出缺口:`place_notes`/`place_votes` 上同类外键**迁移并不会摘**
(原先只写了 place_images 与 topics 两句 DROP)⇒ 补成四张自建数据表全覆盖。
**部署出去的库要能自愈,DROP 必须覆盖全部同类表。**
- 静态扫描必须先跳过 `--` 注释行:规矩的说明文字里就写着 `REFERENCES datasets(id)`,
不跳过会把自己写的文档当成违规。
顺带订正:后台「删除数据集」的二次确认文案在专题改完后已说过时话(说专题会一起删),改成实话。
### 补记:迁移块排序的老规矩我又踩了一次(00:55)
把「摘外键」那五句 ALTER 收成一段放在 `topics` 之后,而 `place_images` 的 CREATE 在这段**之后**
⇒ 开发库(表已存在)毫无症状,**全新库起不来**:`ALTER TABLE place_images …` 报「关系不存在」。
正是记忆里那条老规矩:「迁移块必须收敛且排在依赖表之后(插在 place_images 前:开发库无症、新库起不来)」。
被 `TestFreshDatabaseServesAppQueries` 当场抓住(这条门存在的意义)。
改成整段排在 `place_images` 建表之后(它是五张里最后一张),并把这个坑写进 schema.sql 的注释里。
教训:**凡是 ALTER 某个表的迁移块,先确认那张表在文件里已经建过了**——
只在本机库上跑一遍是测不出来的,必须跑 fresh-database 用例。
## 统计页:站长结论与访客点赞拆成两块(01:40)
用户问「数据统计处的推荐地点和踩雷地点只针对站长吗?应该分开,用户的点赞点踩单独做一块」。
他看到的没错:那张卡的**列表全是站长结论**,访客票只在副标题露了个总数。
- 新增 `votes.TopVisitorVoted`(`HAVING` 只算至少有一票的方向,否则 0 票地点塞满榜;
同票按 `visit_count DESC, p.id` 保证顺序稳定)。
- 「推荐 & 踩雷(我的结论)」只讲站长;另起一张卡「访客点赞」,列 👍/👎 票最多的地点并带票数。
- 两个 pageJob 并行加载;两块共用 `IsAdmin || MarksPublic`(与地点页投票区一致)。
- 用例按卡片标题切 HTML 断言「A 只在站长块、B 只在访客块」,比数总数更能证明没串台。
⚠️ 又踩同一个坑:票表按坐标键跨数据集读、`place_visitor_votes` 还没有 user_id ⇒
上一轮跑剩的票会被算进来。新增 `isolateVoteState` 按 place_key 清两张表(前置 + cleanup)。
顺带订正 README:那里还写着站长结论「按 src_pk 存」,其实早就是坐标键了。
## 措辞分身份:访客不该看到「我的结论」(02:05)
用户:「无论是否登陆,都显示『推荐 & 踩雷(我的结论)』,这对访客是不是会产生困扰,再检查类似的表述」。
顺着 `grep "[我你咱]"` 把访客可见模板 + `static/js` 过了一遍,共 4 处同病(都是**站在站长视角下笔、
而那一块对访客公开**):
1. `stats.html`:标题「我的结论」→ 按身份分支(站长「我的结论」/ 访客「站长结论」);
副标题「只统计你自己…」→ 站长「你自己」/ 访客「站长」;两列「我推荐/我踩雷的地点」同理。
2. `stats.html` 访客块副标题:「你标你的,访客投访客的」→ 对两边都成立的「各存各的表,谁也不会覆盖谁」。
3. `home.html`:「我的标签」→「足迹标签」(同级卡片全是中性的:足迹地图/城市足迹/天气足迹…)。
4. `report.html`:「这一年里,**你**第一次踏足…」→ 去掉人称(年报是站长的回顾)。
已写对的(照它学):`place.html` 投票区早就是 `{{if .IsAdmin}}` 分支,`rond-map.js` 气泡同理。
门禁 `TestVisitorPagesUseThirdPersonCopy`:以访客 ctx(无 user)渲染 `/`、`/stats`、`/report`,
逐个禁用词断言,同时确认站长那份仍说「我的」(别改过头)。
⚠️ 变异验证又踩老坑:**直接 `go test -run` 缺环境变量会静默 skip 并报 ok**(0.17s 就 ok,一眼假绿),
必须走 `verify.sh`。改用 verify.sh 后变异被正确抓住(`visitor_copy_test.go:85` 报「我的结论」)。