fix(spec): the shard reader names the file, entry and anchor for a non-string entry (#6751) - #7075
Merged
os-project-manager merged 1 commit intoAug 9, 2026
Conversation
…n-string entry (#6751) `aggregateCategoryShards` cast each shard's array to `string[]` and handed the entries straight to `categoryOfDefKey`, whose parameter is declared `string`. A hand-edited non-string entry therefore died inside the helper on a bare `key.indexOf is not a function`. All three call sites in `build-schemas.ts` print `error.message` and nothing else, so that text was the whole diagnostic: no shard file among 14, no entry, no issue anchor — while the reader's other three defect classes all name the file and carry one. The check lands at the reader, not in `categoryOfDefKey`: the helper's contract already says `string`, and only its caller knows the file name. The `as string[]` cast is replaced by a real `typeof` check that narrows, so the entry type is now verified where untyped JSON enters rather than asserted. Gate behaviour is unchanged — same exit 1, same verdicts. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AZgRyPVwi1jLb1mNNuUQ9o
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckNo hand-written docs reference the 0 changed package(s). ✅ |
Collaborator
Author
|
座位验收( 复核(在报告到达前已独立做完,与报告零出入):
本单最值钱的产出是反向验证挖出的第三类,单据没写:数组条目根本不抛 TypeError—— 预测失手也记得干净:首轮 26/26 绿的预测被自己的新夹具打红,抓的是新代码的冠词缺陷( 范围守住了:姊妹读取器( 摘草稿入队。 Generated by Claude Code |
os-project-manager
marked this pull request as ready for review
August 9, 2026 13:56
os-project-manager
enabled auto-merge
August 9, 2026 13:56
os-project-manager
deleted the
claude/issue-6751-shard-reader-named-error
branch
August 9, 2026 14:26
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #6751
分片读取器四类缺陷里,只有「条目不是字符串」这一类不说话。本 PR 把它补齐到与另外三类同一水平:报文件名 + 报条目 + 带 issue 锚点 + 带处方。门禁行为一格未动。
落点选择:B(读取处),不是 A(
categoryOfDefKey内)单子给了两个候选,选 B ——
aggregateCategoryShards的遍历处,理由是契约方向:categoryOfDefKey(key: string)的签名已经声明了string。真正的违约方是调用者:它把磁盘上的无类型 JSON 数组as string[]一转就喂了进去。在 helper 里加typeof容错,等于让一个声明只收string的函数去迁就它自己声明不接受的类型 —— 修的是消费者,不是生产者。shard.name。A 最多补到「不是裸报错」,补不出文件名 —— 而 14 个分片里到底是哪一个,恰恰是作者唯一真正需要的信息。declares category …/has no "keys" array/carries "…")全部由这一层产出,同族同形。顺带的结构收益:
as string[]这个断言消失了,换成一次真实的typeof窄化 —— 条目类型现在是在无类型 JSON 入场处被验证,而不是被断言。锚点沿用
#5837(分片重做),与相邻三句一致:锚点指向「这个文件为什么长这样」的设计决策,不指向写下这行的 PR。实测:同一破坏,修前 / 修后
往
packages/spec/authorable-surface/ui.json的keys[0]注入数字12345,跑pnpm --filter @objectstack/spec check:authorable-surface:修前(
origin/main@2c7e62d5f),EXIT=1:修后,
EXIT=1(退出码未变):干净树上门禁照常
EXIT=0,且该次运行把三个分片产物全读了一遍(1598 schemas / 1311 defaults / manifest),验证均无变化 —— 三个消费者都走的是被改动的这段循环。反向验证发现:数组条目根本不抛 TypeError,而是报错报错了
把新加的分支删掉重跑新夹具,预测「3 红 / 23 绿」,实测
Tests 3 failed | 23 passed (26),与预测一致。三条红各自暴露的真实旧行为:12345key.indexOf is not a functionnullCannot read properties of null (reading 'indexOf')["ui/View"]cannot shard "ui/View": … has no category segment (#5837)第三行是本轮最值得记的一笔,单子里没有:数组条目压根不会抛 TypeError。
['ui/View'].indexOf('/')是一次完全合法的Array.prototype.indexOf调用,返回-1,于是slash <= 0成立,代码一路落进「没有 category 段」那条消息 —— 报出一个文件里并不存在的 key,和一个不是真正病因的病因。一个自信的错误诊断比一个裸报错更贵,这也是类型检查必须排在路由之前的原因。该事实已写进夹具注释。夹具:为什么不能用
toThrow()这三条用例断言的是消息内容,逐项 pin 文件名 / 条目 / 锚点,不是
expect(...).toThrow()—— 修前的读取器照样抛(只是抛裸TypeError),所以 throw-only 断言在它本该 pin 的缺陷上是永远绿的。这里消息即契约(#5240),按此口径写。null与object单独一条:typeof null === 'object',把「你写了null」说成「object」会把作者引去找花括号。诚实记一笔预测失手:首轮我预测 26/26 全绿,实测
1 failed—— 夹具抓出的是我自己新代码的语法缺陷(a object,冠词没跟类型名走),不是读取器的。已修为按首字母定冠词(object/undefined都取an)。验证
pnpm --filter @objectstack/spec test→Test Files 354 passed (354)/Tests 9238 passed (9238)pnpm --filter @objectstack/spec typecheck→ 全绿,含check:scripts-typecheck(strict 程序,真正读到本次改动的那个)npx eslint两个改动文件 →EXIT=0;node scripts/check-nul-bytes.mjs→ OKcheck:authorable-surface:干净树EXIT=0,注入非字符串EXIT=1changeset
无 ——
packages/spec的files数组为dist / json-schema / liveness / prompts / llms.txt / README.md / src/**/*.zod.ts / CHANGELOG.md / api-surface / spec-changes.json,不含scripts/(本轮自行复验)。本 PR 只动packages/spec/scripts/**,发布物零变化,故打skip-changeset标签。🤖 Generated with Claude Code
Generated by Claude Code