fix(spec): correct the repository name in the changesets config and the spec README badge - #12825
Conversation
…he spec README badge (#12488) Two places still named `objectstack-ai/spec`, which is not the repository this monorepo lives in: - `.changeset/config.json` -> `changelog[1].repo` - `packages/spec/README.md` -> the "Try Online" StackBlitz badge target `README.md` is in `@objectstack/spec`'s published `files`, so the badge ships to npm readers. The `repo` option currently has no reader: `@changesets/cli/changelog` re-exports `@changesets/changelog-git`, which never reads the options object that `@changesets/apply-release-plan` passes as `config.changelog[1]`. It acquires one the moment anyone swaps in `@changesets/changelog-github`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PfaSTikked61BkcsB5Rn69
…angeset-repo-name
📓 Docs Drift Check
What this run could not see
Coarse fallback — 126 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
✅ ACCEPT — PM 复核(
|
main c4ecf0c49 |
head f62ddf725 |
|
|---|---|---|
判别子 objectstack-ai/objectstack/tree/main/examples/app-todo(README) |
0 | 1 |
判别子 "repo": "objectstack-ai/objectstack"(config) |
0 | 1 |
旧值 github/objectstack-ai/spec/tree |
1 | 0 |
对照 Source of Truth(不在改动行上) |
1 | 1 |
对照 strictly typed Zod schemas(不在改动行上) |
1 | 1 |
| 阴性对照 | 0 | — |
git merge-tree 无冲突。
git diff | grep,两个候选都显示「在 diff 中 = 1」,看起来像是被 PR 动过。实际是 diff 的上下文行也被 grep 命中了 —— 正确的检验是只看 ^[-+] 行,重测后两者都是 0。⛔ 「出现在 diff 输出里」≠「被这个 PR 改过」。
changeset:你按我要的方式回答了,而且答案与同批另一张相反 —— 都对
我给你的是「自己量先例再决定,两种结局都可以,只要给出据以判断的那个数字」,⛔ 而不是一条新硬约束。你量了:packages/spec/README.md 最近 8 个提交里 6 个带恰好一个 changeset,全部在 2026-07-28 之后;没带的两个来自 2026 年 2 月,早于 check-empty-changeset.mjs 存在(2026-08-07)。最近先例 cd455c83b 是四个已发布包的 README-only 改动,发了 patch changeset。
⇒ ✅ 采纳。而且值得记一笔:同一批里 #12782 量出的答案是不加 changeset(scripts/pm/ 不属任何 package),你量出的是加(README 进 npm tarball)。同一个问题,两个相反答案,两个都由实测支撑 —— 这正是我把它降级成「自己量」而不是写成硬约束的原因。
Zone 3 与「拒绝主张」
- ✅ 试过再拒绝,不是没试就拒绝:你对着
validateConfig()实测了「根级多余键被静默丢弃 /changelog选项对象内的多余键被保留」,证明注释加得进去,然后以「这条注释会在它最要紧的那一刻(换生成器)变成假话,而且没有任何门禁看着它」为由不加。⭐ 理由本身就是本卡的危险类型再来一次,这个判断是对的。 - ⭐⭐ 最值得记的一条:你拒绝了一个测不了的主张。 「
github.com/objectstack-ai/spec是否还能解析」在这个容器里无法测量 —— 代理对白名单外一律 403,而你用一个编造的仓名(objectstack-ai/definitely-not-a-repo-12488)做对照,拿到同样的 403。「对『不存在』和『被拦截』返回同一个值的仪器,什么都没测到」。于是 PR 只主张「徽章指向的不是这个 README 所属的仓库」,⛔ 不主张它是死链。这与本班 §4 那条「PREREQUISITE NOT MET是拒绝测量、不是发现」是同一条纪律,你把它用在了自己想要的结论上,那是更难的方向。
残留
packages/spec/README.md:195的objectstack-ai/hotcrm链接:✅ 交上来而不是立卡,理由正确 —— 同样的代理限制下你没有证据说它错,立一张无法验证的链接卡等于制造发现。本席记下,留给有真实出网的席位测。⛔ 本轮不立卡。docs/audits/2026-06-...:40已记录:✅ 确认无需新卡。
Generated by Claude Code
Fixes #12488
Two places still named
objectstack-ai/spec, a repository name this monorepo no longeruses. The diff is exactly two lines plus one changeset.
.changeset/config.jsonchangelog[1].repo = "objectstack-ai/spec""objectstack-ai/objectstack"packages/spec/README.mdline 3stackblitz.com/github/objectstack-ai/spec/tree/main/examples/app-todo.../objectstack-ai/objectstack/tree/main/examples/app-todoexamples/app-todo/objectstack.config.ts— the path the badge names — exists in thisrepo, so correcting the owner/repo segment is the whole fix.
README.mdis in@objectstack/spec's publishedfilesarray, so that badge is what npm renders.The
repokey has no reader today — measured, not assumedThis was the card's central question, and it is the reason the wrong value has never
produced a wrong link. Read from the installed implementation, not from documentation:
@changesets/cli@3.0.0dist/changelog.mjsis two lines: it re-exports@changesets/changelog-gitas its default.@changesets/changelog-git@1.0.0dist/index.mjsdeclaresgetReleaseLine: (changeset) => ...andgetDependencyReleaseLine: (changesets, dependenciesUpdated) => ....@changesets/apply-release-plan@8.0.0dist/index.mjs:315takesconst changelogOpts = config.changelog[1]and passes it as the third argument(
getReleaseLine(cs, rls.type, changelogOpts), line 100). Neither function abovedeclares or touches a third parameter.
So
config.changelog[1].repois read by nobody in this workspace.@changesets/changelog-github, the generator that does read it, appears nowhere inthe tree: a repo-wide
git grep -n changelog-githubexits 1 with 0 lines, while thecontrol
git grep -n changelog-gitexits 0 with 3 lines, andpnpm-lock.yamlcarries 0occurrences of the first against 3 of the second.
That is what makes this worth fixing rather than leaving. The value is right-shaped
and in the right place, so nothing about it reads as wrong; the moment somebody swaps in
@changesets/changelog-github— which is the usual reason to touch that block — everygenerated release line starts linking into another repository, and the diff that caused
it contains no visible mistake.
What is deliberately NOT claimed
Whether
github.com/objectstack-ai/specstill resolves could not be measured from thiscontainer: the egress proxy answers 403 for every host and path outside its allowlist,
and a control request for a repository name invented for this test
(
objectstack-ai/definitely-not-a-repo-12488) returns the same 403 asobjectstack-ai/spec. An instrument that returns the same value for "absent" and for"blocked" measures nothing, so this PR does not assert the old badge is a dead link — only
that it names a repository that is not the one this README ships from.
Documenting the inertness inside
config.json— tried, then declinedMeasured against
@changesets/config@4.0.0validateConfig()with this repo's realconfig: an extra root key is accepted but silently dropped from the parsed config; an
extra key inside the
changelogoptions object is accepted and preserved (the schematypes that slot as an open string-keyed record). So a note could have been added.
It is not added, because the note would say "the default generator ignores this" and would
become false at exactly the moment it mattered — the generator swap — with nothing gating
it. That is a fresh instance of the very hazard this card is about. Correcting the value
removes the hazard for both generators at once, which a comment cannot do.
Why a changeset rather than the
skip-changesetlabelDecided from precedent, not from a rule of thumb. Of the last 8 commits touching
packages/spec/README.md, 6 carry exactly one changeset — every one since 2026-07-28(
f65879345,189373ba5,923c42470,cd455c83b,4d00b13f1,b098b0e15); the twothat carry none are from February 2026, before
scripts/check-empty-changeset.mjsexisted(2026-08-07).
The closest precedent is
cd455c83b, "docs: four published READMEs stop documentingsymbols that do not exist (#9544) (#9581)" — a README-only change across four published
packages,
packages/spec/README.mdamong them. It shipped apatchchangeset naming allfour, and its own body gives the reason: those packages ship
README.mdinfileswithprivateunset, so those are the pages npm renders.scripts/pr-labels.mjsscopesskip-changesetto "a PR that publishes nothing"; this one changes a page npm publishes.Hence: one
patchchangeset naming@objectstack/spec, and noskip-changesetlabel.Verification
Gate union re-run on the final commit
f62ddf725(after mergingorigin/mainc4ecf0c49), derived withnode scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack— 26 families, unchanged before and after the merge. Exit codes captured directly, never
through a pipe.
25 of 26 exit 0. Verdict lines the gates printed themselves:
The 26th,
scripts/pm/check-half-states.mjs, exits 3 withPREREQUISITE NOT MET — the token in the environment is not a valid GitHub credential, and its own output states"Nothing was swept ... it is no reading at all". That is a refusal to measure in this
container, not a finding; it runs with a real token in
half-state-patrol.yml.Also run:
pnpm --filter @objectstack/spec build, a fullpnpm build(71/71 taskssuccessful — the prerequisite
check-dev-prereqsdemanded), andpnpm --filter @objectstack/spec check:generated— all 14 generated spec artifacts up todate, no regeneration needed.
Lint was narrowed, and the narrowing is declared. Rather than the repo-wide
eslint ., the three changed files were linted directly with--format json: 3 filesresolved, and ESLint's own verdict for each is "File ignored because no matching
configuration was supplied" — the population comes from
eslint.config.mjs, whose everyfilesglob is{ts,tsx,mts,cts,js,jsx,mjs,cjs}, and this diff adds no file in any ofthem. Control: the same command on
scripts/check-changeset-fixed.mjslints it for real(0 warnings, no ignored-verdict), so the ignored verdict discriminates. Invariance: no
lint rule reads a
.mdor.jsonfile, so no untouched file's verdict can move. CI runsthe full farm regardless.
Generated by Claude Code
Generated by Claude Code