范围外发现,记录于 #5873 的重锚复验过程中(该单前提已被证伪 —— 其正文指认的 authorable-surface.json 无保护 JSON.parse 已随 #5837 分片重做整体消失,详见其评论)。观察类:不构成绕过,门禁照样红、--check 照样不写盘,只是这一条错误分支的诊断质量掉回了「裸 JS 报错」。
事实
packages/spec/scripts/lib/sharded-artifacts.ts:95-104 的 categoryOfDefKey(key: string) 直接调 key.indexOf('/')。参数类型写的是 string,但它读的是磁盘上的 JSON 数组条目 —— 一个被手编成非字符串的条目(数字、null、对象)在运行时就会让它抛裸 TypeError。
它自己对「字符串但没有 category 段」这一类是会说话的:
cannot shard "foo": every ratcheted key is "category/Def[:prop]" and this one has no category segment (#5837)
缺的只是「根本不是字符串」这一格。
实测(本轮,worktree @ origin/main 252f71bd6,build-schemas.ts @ 747d2e451)
往 packages/spec/authorable-surface/ui.json 的 keys[0] 注入数字 12345,跑 pnpm --filter @objectstack/spec check:authorable-surface:
EXIT=1
❌ Failed to read authorable-surface/: key.indexOf is not a function
退出码对、无栈,但这条消息不报是哪个分片文件、不报是哪个条目、无 issue 锚点、无处方。读者拿到的信息量约等于零 —— 14 个分片,他得自己挨个找。
对照:同一文件同一轮,其它缺陷类都说话
同一 worktree、同一 gate,另外三种破坏方式的实测输出:
| 破坏方式 |
实测输出 |
删掉 ui.json 末尾 } |
❌ Failed to read authorable-surface/: authorable-surface/ui.json is not valid JSON (#5837): SyntaxError: ... |
keys 改成非数组 |
❌ Failed to read authorable-surface/: authorable-surface/ui.json has no "keys" array (#5837). |
破坏姊妹 authorable-surface.base.json |
❌ authorable-surface.base.json is not valid JSON (#5235): SyntaxError: ... |
keys 内注入非字符串条目 |
❌ Failed to read authorable-surface/: key.indexOf is not a function |
前三行都报了文件名 + issue 锚点;只有第四行退化。
影响面
categoryOfDefKey 是三个分片产物的共用路径 —— authorable-surface/、schema-manifest/、authorable-defaults/ 的读取都经 aggregateCategoryShards 走到它(build-schemas.ts 的三个 try/catch 分别在 :503 / :733 / :2324),所以同一条哑消息会以三种前缀出现。落点是 lib 一处,不是三处。
为什么归为观察类
建议修法(窄)
两个落点二选一,都不新增语义:
- A(更靠近根因):
categoryOfDefKey 在 indexOf 之前加一格 typeof key !== 'string',复用它已有的那句 message 形状。缺点是它拿不到分片文件名。
- B(信息更全):
aggregateCategoryShards 遍历 list 时顺手判类型 —— 它手里正好有 shard.name,能报出「哪个文件的哪个条目」,与相邻那句 has no "keys" array (#5837) 同族。
倾向 B:这个 reader 的既有惯例就是「报文件名 + 报条目 + 带 issue 锚点」,B 能把这一格补齐到同一水平,A 只能补到「不是裸报错」。
关联:#5873(本发现的来源单,其自身前提已被证伪)、#5837(分片重做)、#5235(姊妹 reader,对照实现)。
范围外发现,记录于 #5873 的重锚复验过程中(该单前提已被证伪 —— 其正文指认的
authorable-surface.json无保护JSON.parse已随 #5837 分片重做整体消失,详见其评论)。观察类:不构成绕过,门禁照样红、--check照样不写盘,只是这一条错误分支的诊断质量掉回了「裸 JS 报错」。事实
packages/spec/scripts/lib/sharded-artifacts.ts:95-104的categoryOfDefKey(key: string)直接调key.indexOf('/')。参数类型写的是string,但它读的是磁盘上的 JSON 数组条目 —— 一个被手编成非字符串的条目(数字、null、对象)在运行时就会让它抛裸TypeError。它自己对「字符串但没有 category 段」这一类是会说话的:
缺的只是「根本不是字符串」这一格。
实测(本轮,worktree @ origin/main
252f71bd6,build-schemas.ts@747d2e451)往
packages/spec/authorable-surface/ui.json的keys[0]注入数字12345,跑pnpm --filter @objectstack/spec check:authorable-surface:退出码对、无栈,但这条消息不报是哪个分片文件、不报是哪个条目、无 issue 锚点、无处方。读者拿到的信息量约等于零 —— 14 个分片,他得自己挨个找。
对照:同一文件同一轮,其它缺陷类都说话
同一 worktree、同一 gate,另外三种破坏方式的实测输出:
ui.json末尾}❌ Failed to read authorable-surface/: authorable-surface/ui.json is not valid JSON (#5837): SyntaxError: ...keys改成非数组❌ Failed to read authorable-surface/: authorable-surface/ui.json has no "keys" array (#5837).authorable-surface.base.json❌ authorable-surface.base.json is not valid JSON (#5235): SyntaxError: ...keys内注入非字符串条目❌ Failed to read authorable-surface/: key.indexOf is not a function前三行都报了文件名 + issue 锚点;只有第四行退化。
影响面
categoryOfDefKey是三个分片产物的共用路径 ——authorable-surface/、schema-manifest/、authorable-defaults/的读取都经aggregateCategoryShards走到它(build-schemas.ts的三个 try/catch 分别在 :503 / :733 / :2324),所以同一条哑消息会以三种前缀出现。落点是 lib 一处,不是三处。为什么归为观察类
console.error+process.exit(1),退出码正确;--check在读之前不写任何文件(check:authorable-surface在 --check 模式下仍会写json-schema.manifest.json—— 一个「检查」在改工作区 #4711 纪律未退步)。建议修法(窄)
两个落点二选一,都不新增语义:
categoryOfDefKey在indexOf之前加一格typeof key !== 'string',复用它已有的那句 message 形状。缺点是它拿不到分片文件名。aggregateCategoryShards遍历list时顺手判类型 —— 它手里正好有shard.name,能报出「哪个文件的哪个条目」,与相邻那句has no "keys" array (#5837)同族。倾向 B:这个 reader 的既有惯例就是「报文件名 + 报条目 + 带 issue 锚点」,B 能把这一格补齐到同一水平,A 只能补到「不是裸报错」。
关联:#5873(本发现的来源单,其自身前提已被证伪)、#5837(分片重做)、#5235(姊妹 reader,对照实现)。