test(client): discovery 替身改成真实 /discovery 形状,并本地钉死两处退役拼法 - #6112
Merged
Conversation
…y, pin both retired spellings
`packages/client/src/client.test.ts`'s `connect()` double spelled two shapes no
discovery producer has ever emitted:
capabilities: ['metadata', 'data', 'ui'],
endpoints: {}
`endpoints` was the dispatcher-only verbatim copy of `routes`, retired by #4828
under ADR-0049; the real producer emits `routes` (`ApiRoutesSchema`, required by
`DiscoverySchema`). `capabilities` is a closed object over the one vocabulary,
one `CapabilityDescriptor` per key (#5672 ruling A) — never a string array, and
the three names it listed are `routes` keys, not capability keys.
Both were inert (the test asserts only that the fetch happened), which is why
they survived two retirements. This is the sibling of #5674 one package over,
found by re-reading the rule's consumption radius rather than the edited package.
The double is now shaped on the measured producer output, with the capability
map BUILT from `WELL_KNOWN_CAPABILITY_KEYS` rather than hand-listed, so it
cannot fall behind the vocabulary.
Adds `packages/client/src/discovery-double-retired-key.test.ts`, a LOCAL pin
mirroring `packages/rest/src/discovery-double-retired-key.test.ts` (#5674) —
per-package, not promoted to a repo-level gate, because the two packages write
their doubles in different forms. It reads both forms `packages/client` actually
uses (a fetch mock's `json` body and a direct `discoveryInfo` assignment), finds
5 discovery doubles across 2 files, and asserts the two negatives.
Tests-only; no changeset.
Fixes #5787
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wbxm29qPKnLf44AbSxizqW
|
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). ✅ |
qq9340100
marked this pull request as ready for review
August 7, 2026 02:22
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 #5787
问题
packages/client/src/client.test.ts里connect()的 discovery 替身拼了两个任何 producer 都没发过的形状:endpoints—— 真实 producer(ObjectStackProtocolImplementation.getDiscovery(),packages/metadata-protocol/src/protocol.ts)发的是routes(ApiRoutesSchema,DiscoverySchema里必填)。endpoints只在 dispatcher 那条路径上作为routes的逐字副本存在过,两个 discovery 生产者都在线上返回 schema 未声明的顶层字段(scoping / features / endpoints),且 REST 形状永远无法通过 DiscoverySchema #4828 已按 ADR-0049 删除。capabilities是数组 ——DiscoverySchema.capabilities是对WellKnownCapabilitiesSchema的闭合对象,每个词汇键一条CapabilityDescriptor({ enabled, features?, description? }),SDK 的 client.capabilities 声明为 WellKnownCapabilities,但两个 discovery 生产者填的是互不相交的键集 #5672 ruling A。它从来不是字符串数组;而且它列的三个名字(metadata/data/ui)根本不是 capability 键,是routes键。两处都是惰性的 —— 该用例只断言
expect(fetchMock).toHaveBeenCalled(),不读 body 的任何键 —— 这正是它们连着躲过两轮退役的原因。这是 #5674 在另一个包里的同族兄弟,按「规则的消费半径」而不是按被改的包复查时发现的。改法
1. 替身按实测的 producer 输出重塑(
client.test.ts)capability map 用
WELL_KNOWN_CAPABILITY_KEYS构造而不是手写键表 —— 该常量的 schema 注释明确说了它存在的意义就是防止「手列键」这种漂移,手写一份在词汇增长的当天就会悄悄落后。2. 新增本地 pin
packages/client/src/discovery-double-retired-key.test.ts对齐
packages/rest/src/discovery-double-retired-key.test.ts(#5674)的形状,保持按包,没有提成跨包 repo 级 gate —— issue 正文明确要求不要默认扩大,而且两个包写替身的方式本来就不同:restmock 的是协议对象(getDiscovery: vi.fn().mockResolvedValue(…)),clientmock 的是线(fetch到json())。单一跨包扫描器无论如何都得同时带两种捕获形态,失败信息还会指向读者当下并不在的那个包。两条本地 pin,各读各包真实使用的形态,是更小也更好读的安排。要不要合并成 repo 级 gate 是维护者的决定,不该作为本次修复的副作用发生。pin 的诚实边界(写进了 docblock):
json: async () =箭头体,以及对私有discoveryInfo字段的直接赋值。第三种写法读不到。capabilities或routes键才算 discovery 替身 —— 本包其它响应体(/meta、/data等)会被捕获然后正确忽略。实测:共捕获 9 个字面量,判定 5 个为 discovery 替身,横跨 2 个文件。routes或完整词汇:隔壁 capability getter 的用例是刻意用残缺和遗留载荷驱动 getter 的(capabilities-vocabulary.test.ts就是原样重放 SDK 的 client.capabilities 声明为 WellKnownCapabilities,但两个 discovery 生产者填的是互不相交的键集 #5672 之前的 dispatcher map),要求每个替身都合规会把那份覆盖删掉。验证
pnpm --filter @objectstack/client test—— 20 个测试文件 / 240 个用例全绿(pin 新增 3 条)。pnpm --filter @objectstack/client typecheck——tsc --noEmit加check:test-typecheck均通过;新 pin 与client.test.ts都不在test-typecheck-debt.json里,按该 ledger 的规矩必须零错误,实测零错误(ledger 仍是原来的 3 文件 / 6 错误,未动)。反向验证(方向为事先预测的「红」,即常规方向): 把退役拼法原样放回
client.test.ts的替身,pin 的两条否定断言双双转红并点名client.test.ts,而反空转那条保持绿(证明扫描器仍然匹配到了整个替身population,红不是因为扫了空集):随后已还原修复,重跑全绿。
范围
Tests-only,无 changeset(需要
skip-changeset标签)。没有碰packages/rest、packages/spec或任何生产代码;apiName保持原样 —— 它不是缺陷,是GetDiscoveryResponse上已声明的弃用别名,真实 producer 至今与name同值双发(protocol 18 移除)。同文件里 meta 面的 mock 未动(#5895 / #5946 刚刚有意重塑过)。🤖 Generated with Claude Code
https://claude.ai/code/session_01Wbxm29qPKnLf44AbSxizqW
Generated by Claude Code