Skip to content

docs(qa): 2026-W19 周报不是合法 UTF-8(已绊倒两个扫描脚本),修成可读并标出截断处 - #858

Closed
vansin wants to merge 1 commit into
mainfrom
docs/fix-w19-encoding
Closed

docs(qa): 2026-W19 周报不是合法 UTF-8(已绊倒两个扫描脚本),修成可读并标出截断处#858
vansin wants to merge 1 commit into
mainfrom
docs/fix-w19-encoding

Conversation

@vansin

@vansin vansin commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

问题

docs/qa/weekly/2026-W19.md 不是合法 UTF-8,而且从它诞生那天起就不是。

$ git log --follow -- docs/qa/weekly/2026-W19.md
be6c3dee 2026-05-12 test(qa): R22 — Plan B (CI badge + CONTRIBUTING) + Plan E (qa-status.sh 周报脚手架)

只有这一次提交,且那一版就已非法 —— 历史里没有完好版本可回。

三处坏字节,签名一致:多字节汉字被从中间切断,残留一个 _:

pos=2467  e4 b8 5f   …通过 getinbox 拿,⟪坏⟫
pos=3080  ef 5f 0a   …真 LLM 烧钱不可取⟪坏⟫
pos=3453  e7 5f 0a   …但生成/解析的形⟪坏⟫

三行分别在第 48 / 56 / 68 个字符处断掉,后半句没了。看起来是当初某个按字节
截断的写入过程干的(周报是 qa-status.sh 脚手架生成的)。

为什么值得改

它已经绊倒过两个按 UTF-8 读全目录的脚本(#857 做文档 pin 盘点时一次,
#772 量 slug 暴露面时又一次)。任何

for p in pathlib.Path("docs").rglob("*.md"):
    p.read_text(encoding="utf-8")     # ← 走到这里抛 UnicodeDecodeError

都会在这里中断整次扫描,而报错信息是「position 2467 的字节非法」这种
和业务毫无关系的东西 —— 第一次撞上时很难联想到是某份周报坏了。
errors="ignore" 绕过则会在写回时损坏文件,不是解法。

这次做了什么

  1. 三处坏字节换成显式标记 〔原文在此处被截断,内容已丢失〕;
  2. 顶部加一段编者注,说明来龙去脉。

🔴 没有做什么

没有猜写任何丢失的内容。 三处截断的后半句无从恢复,与其编一个读起来通顺的
句子填上(那会让一份 QA 记录变成半真半假的东西),不如把「这里丢了」如实写出来。

验证

改后按 UTF-8 读完 docs/ 下全部 168 个 md 文件      无异常
.github/scripts/check-no-memory-slugs.py 全树      scanned 1186 file(s)  OK

这个文件从 be6c3de(2026-05-12)提交那天起就不是合法 UTF-8:三行在写入时被按字节
截断,把汉字切成半个(残留字节 e4 b8 5f / ef 5f 0a / e7 5f 0a)。

它已经绊倒过两个按 UTF-8 读全目录的脚本(见 #857#772 的记录)——
任何 Path.read_text() 走到这里都会抛 UnicodeDecodeError,中断整次扫描,
而且报错指向的是"位置 2467 的字节"这种与业务无关的信息,很难联想到是某份周报坏了。

处理:

- 三处坏字节换成显式标记〔原文在此处被截断,内容已丢失〕;
- 顶部加编者注说明来龙去脉。

🔴 **没有猜写任何丢失的内容。** 该文件只有一次提交,历史里没有完好版本
(git log --follow 只有 be6c3de 一条,且那一版就已非法),被截掉的后半句
无从恢复 —— 与其编一个读起来通顺的句子,不如把"这里丢了"如实写出来。

验证:改后按 UTF-8 读完 docs/ 下全部 md 文件无异常;
check-no-memory-slugs.py 在全树上仍报 OK。

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 54973e18d5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

_派生 token 是否随母 token 失效,是 fleet-management 类工具的核心契约。_
- `qa-hub-07-sse-reconnect` — [tests/qa-hub-07-sse-reconnect/](../../tests/qa-hub-07-sse-reconnect/)
_这个测试 pin 关键契约:「断开期间的任务不能丢」—— 通过 getinbox 拿,_
_这个测试 pin 关键契约:「断开期间的任务不能丢」—— 通过 getinbox 拿,〔原文在此处被截断,内容已丢失〕_

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restore the summaries from their existing sources

These contents are not permanently lost: scripts/qa-status.sh generated each summary from the next line of the linked test README and merely split UTF-8 with head -c 100. In the reviewed parent tree, the three READMEs still contain the exact text, including 不是通过重放 SSE, the complete 真 LLM 烧钱不可取, sentence, and 生成/解析的形状边界没有快速断言. Replacing the bytes with loss markers therefore makes the QA record and the new editor's note factually incorrect; recover the summaries from those repository sources or describe them as generator truncation instead.

Useful? React with 👍 / 👎.

@vansin

vansin commented Aug 13, 2026

Copy link
Copy Markdown
Contributor Author

把这个 PR 的必要性说准一点(核过之后,比我原来写的更窄、也更具体)

我在正文里说它「绊倒过两个按 UTF-8 读全目录的脚本」。核实一下影响面,免得这条被高估或低估:

今天没有任何在仓脚本会被它绊倒

我扫了 scripts/ / .github/ / tests/ 下所有以 UTF-8 读文件、且提到 docs 的脚本,逐个看它们怎么读:

tests/qa-core-docs/run.mjs            读指定文件(docs-site/docs/guide/introduction.md 等)
tests/qa-frontdoor-docs/run.mjs       读指定文件
tests/dashboard-chat-doc-path.test.mjs 读指定文件

全是按路径读具名文件,没有一个递归遍历 docs/ —— 所以它们碰不到 docs/qa/weekly/2026-W19.md
绊倒的只有临时分析脚本(我在 #857#772 各撞一次)。

🔴 但有一个将来一定会撞上的,而且撞法比崩溃更糟

scripts/check-doc-source-pins.py(#843)是递归遍历的,而它这样读:

try:
    text = (REPO / rel).read_text(encoding="utf-8")
except (OSError, UnicodeDecodeError):
    continue          # ← 静默跳过

不会崩,会静默跳过这个文件。

#852 建议把它的 DOC_ROOTdocs-site 扩到 docs/ —— 一旦扩了:

  • 2026-W19.md 会被静默跳过;
  • 该文件里若有失效的行号 pin,永远不会被检查到;
  • 而门照报绿。

这正是本仓反复出现的那个形态(见 #861 / #860 / feedback_checker_scope_bug_vacuous_pass):
不是门报错,是门看不见。一个编码坏掉的文件,在递归扫描器眼里等于不存在。

所以这个 PR 的准确定位

不是「修复 CI 崩溃」(今天没有 CI 因它崩),而是:

  1. 让临时分析不再需要每次绕过它;
  2. docs/ 下的源码行号引用没有任何门覆盖:扩 DOC_ROOT 只解决 2/11,剩下 9 条要符号级校验 #852 扩大扫描范围之前,把这个「会被静默跳过的洞」堵上 ——
    否则扩范围之后它就是一个看不见的盲区。

顺序上,这个 PR 应当排在 #852 的扩范围动作之前

@vansin

vansin commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

这个 PR 要修的东西已经不存在了,建议关闭。

标题是「2026-W19 周报不是合法 UTF-8(已绊倒两个扫描脚本)」。我在 origin/main 上核了:

open('docs/qa/weekly/2026-W19.md','rb').read().decode('utf-8')   # 无异常抛出

W19 现在是合法 UTF-8,由 #899(9db6dcf1 — "修 W19 编码与死链…")修掉了。

本 PR 当前是 dirty,但那个冲突不是"需要重新解决一下",而是它和一份已经被修好的文件在同一处打架

顺带:这个文件今晚又动了两次,你可能想知道

如果你这个 PR 里还有 #899 没覆盖的改动,说一声,我们单独摘出来;否则关掉

@vansin

vansin commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

关掉 —— 它要修的东西已经在 main 上修好了,而现在合它会把另一件事改坏。

① 它的前提在写的时候是真的

在这个 PR 的父提交上验:

$ git show <858 的父提交>:docs/qa/weekly/2026-W19.md | python3 -c "..."
valid UTF-8: NO  —— 'utf-8' codec can't decode bytes in position 2467-2468: invalid continuation byte

编码问题当时确实存在。这个 PR 没有说错话。

② 但 main 上已经不是那样了

$ git log --oneline origin/main -- docs/qa/weekly/2026-W19.md
abb31c53  fix(ci,docs): docs-integrity 看不见「裸文件名」相对链接…… (#911)
9db6dcf1  fix(docs,ci): 修 W19 编码与死链、给矛盾耗时标条件…… (#899)   ← 编码在这里修的
be6c3dee  test(qa): R22 ……

当前 main 上那份:5642 字节,合法 UTF-8,三处截断也已经标出来了(标记文本不同,但作用一样)。

③ 🔴 现在合它,会把 #911 修好的相对链接改回去

两版的差别不止编码 —— 链接层级也不一样:

main(#911 之后) 本 PR
指向仓根 ../../../tests/… ../../tests/…

文件在 docs/qa/weekly/,到仓根是三层../../ 只到 docs/,于是 ../../tests/… 解析成 docs/tests/… —— 不存在

不是推断,我把本 PR 的文件放到 main 的树上跑了一次 main 现在的门:

$ python3 .github/scripts/check-docs-integrity.py
::error file=docs/qa/weekly/2026-W19.md::relative link '../../tests/qa-hub-05-roundtrip/'
        resolves to 'docs/tests/qa-hub-05-roundtrip', which does not exist
…(共 26 条)
26 problem(s).

26 条,全在这一个文件里。

⚠️ 顺带说明这里为什么之前看不出来:本 PR 现在的 check 列表里根本没有 docs-integrity(只有 5 个 check,都是这道门存在之前的)。门存在、也接线了,但这个 head 上不会被触发 —— 要 rebase 到 main 才会红。所以「它 CI 是绿的」在这里不构成任何证据。

④ 有一样东西值得留下,我抄在这里免得丢

本 PR 加的那段编者注,main 上没有对应的说明:

编者注(2026-08-14):本文件自 be6c3dee(2026-05-12) 提交时起就不是合法 UTF-8 —— 有三行在写入时被按字节截断,把一个汉字切成了半个。文件只有这一次提交,历史里没有完好版本,被截掉的后半句已永久丢失

这次只做两件事:把三处坏字节换成显式标记,使文件成为合法 UTF-8。没有猜写任何丢失的内容。

「历史里没有完好版本、内容永久丢失」这句是有用的 —— main 的行内标记只说了「被截断」,没说为什么找不回来。谁想补的话,单独提一个只加这段注的 PR 即可,别带链接改动


结论:关闭。原因不是这个 PR 做错了,是 main 在它之后走了两步(#899 修编码、#911 修链接),而它还停在两步之前。 今晚第 5 个这种形状 —— 陈旧 PR 的危险不在于它没用,在于它会把后来修好的东西一起带回去。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant