Repository navigation
Description
发现于 #5673 的实施(界外发现,关键词 + 文件路径查重无命中,故新开)。
现象
/discovery 有两个生产者,#5673 的裁定只点名了其中一个:
| 生产者 | 服务方 | NODE_ENV 未设置时 environment |
|---|---|---|
HttpDispatcher.getDiscoveryInfo()(packages/runtime/src/http-dispatcher.ts) |
dispatcher-plugin.ts / packages/adapters/hono |
production(#5673 已改) |
MetadataProtocol.getDiscovery()(packages/metadata-protocol/src/protocol.ts:2900) |
packages/rest/src/rest-server.ts:3050 |
development(未改) |
第二个生产者把宿主真实的缺省值原样递给映射函数:
environment: resolveDiscoveryEnvironment(
(globalThis as { process?: { env?: Record< string, string | undefined > } })
.process?.env?.NODE_ENV,
),resolveDiscoveryEnvironment(undefined) 走 typeof raw !== 'string' 分支返回 development(packages/spec/src/api/discovery.zod.ts:341-344),所以经 @objectstack/rest 暴露的 /discovery 在「忘记设 NODE_ENV 的生产部署」上仍然自称 development —— 正是 #5673 判定为危险方向的那一个。
为什么 #5673 没有一并解决
#5673 的 maintainer 裁定(2026-08-06)把落点明确限定在 packages/runtime/src/http-dispatcher.ts,并把 packages/metadata-protocol 标为跨域文件面、要求「若必须改它就 STOP + needs_decision」。派发单进一步禁止改 packages/spec / packages/metadata-protocol。所以 #5673 的 PR 在 runtime 侧就地翻默认,并在注释里如实写明本条残留,而不是悄悄绕过。
两条可能的落点(需要裁定,不要直接猜)
- 默认收进共享映射函数 ——
resolveDiscoveryEnvironment把「缺省」判为production,两个生产者都不再各自带默认。契约优先,单点决策,两个 discovery 生产者都在线上返回 schema 未声明的顶层字段(scoping / features / endpoints),且 REST 形状永远无法通过 DiscoverySchema #4828 建这张共享表的初衷就是防两个生产者漂移;代价是动packages/spec,且要同步改NODE_ENV_TO_DISCOVERY_ENVIRONMENT上方那张表格里「unset / anything else → development」那一行(该行现在对 runtime 调用方已经过时)。 - 只在 metadata-protocol 生产者就地补默认 —— 与 NODE_ENV 未设置时 /discovery 广播 environment=development,而 os start 默认 NODE_ENV=production、CLI doctor 也按 production 解析 #5673 的做法对称,不动 spec;代价是同一个「缺省语义」在仓里有两处副本,正是共享表要防的漂移。
倾向 1(单点决策、契约优先、AI 写元数据时不给消费方留宽容分支),但落点跨域,交 maintainer 裁。
附带的文档面漂移(同一处,顺带记录)
packages/spec/src/api/discovery.zod.ts 映射表上方注释仍写:
| unset / anything else |
development| preserves the pre-existinggetEnv('NODE_ENV', 'development')default…
#5673 之后 runtime 调用方已不再传该默认,这句话对映射函数自身仍为真、对调用方已不为真。无论走上面哪条路,这行都要一起改。
参考:#5673(runtime 侧 + doctor 提示行)、#4828(枚举映射的由来)、Prime Directive #9(NODE_ENV 是第三方边界上的既有例外)。
Activity
claude commentedon Aug 6, 2026
分诊:
needs-user-decision+domain:spec(路由标签,方向未定)。packages/runtime/src/http-dispatcher.ts,并明确要求「若必须改packages/metadata-protocol就 STOP + needs_decision」;本单正是那条 STOP 的兑现 —— 两条候选(1 收进共享映射函数resolveDiscoveryEnvironment,动packages/spec;2 在 metadata-protocol 生产者就地补默认,留两份缺省语义)语义相反、代价不同,分诊不代拍。packages/spec/src/api/discovery.zod.ts:341-344(+ 其上方映射表注释「unset / anything else → development」那一行,NODE_ENV 未设置时 /discovery 广播 environment=development,而 os start 默认 NODE_ENV=production、CLI doctor 也按 production 解析 #5673 之后对 runtime 调用方已过时);方向 2 落packages/metadata-protocol/src/protocol.ts:2900(getDiscovery)。按「shared contract surfaces have one owner」先归domain:spec座位;若裁 2(零改 spec),由该座位按落点转domain:engine-core(packages/metadata*属该行)。@objectstack/rest暴露的/discovery自称 development」,正是 NODE_ENV 未设置时 /discovery 广播 environment=development,而 os start 默认 NODE_ENV=production、CLI doctor 也按 production 解析 #5673 判定为危险方向的那一个,只是换了生产者。resolveDiscoveryEnvironment/NODE_ENV/getDiscovery命中 NODE_ENV 未设置时 /discovery 广播 environment=development,而 os start 默认 NODE_ENV=production、CLI doctor 也按 production 解析 #5673(runtime 半边,cli 座位,已派发)与 「环境类别」这一个概念在 spec 里有两个枚举:DiscoverySchema.environment(3 成员)与 EnvironmentTypeSchema(7 成员) #5676(environment 两个枚举并存,spec 队列,另一族)与本单,无重复入口。git log --oneline origin/main -- packages/spec/src/api/discovery.zod.ts最近一条是 SDK 的 client.capabilities 声明为 WellKnownCapabilities,但两个 discovery 生产者填的是互不相交的键集 #5672→feat(spec,runtime,metadata-protocol,client)!: 统一能力词表 —— 封闭声明,两个 discovery 生产者全量发 (#5672) #5857(能力词表统一,两个 discovery 生产者全量发),未触缺省语义;resolveDiscoveryEnvironment(undefined) → 'development'与 metadata-protocol 侧原样递传现状均未变。前提成立。本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
claude commentedon Aug 7, 2026
Disposition (2026-08-07): returned to the queue — the semantics were already ruled on in #5673.
The maintainer decided on 2026-08-06 that a deployment with
NODE_ENVunset must not call itselfdevelopment; the runtime producer was fixed, and metadata-protocol'sgetDiscoverywas left behind only because that dispatch forbade touching it. What is left is a placement question, not a semantic one — which is engineering judgement.Direction 1: fold the default into
resolveDiscoveryEnvironment(unset → production) so both producers inherit it, drop their local defaults, and fix the now-false comment atdiscovery.zod.ts:314in the same pass. Direction 2 (patch metadata-protocol locally) would leave a second copy of the default — exactly the drift the shared table was created to prevent (#4828).Single-point default also means the next discovery producer gets the right answer without anyone remembering to copy a line.
Operator: PM session
session_01GcjbQLUQKysMU9uXB34iyv; maintainer ruling 2026-08-07 (decision-inbox round 2). Veto window open — comment or reopen to overturn.Generated by Claude Code
hotlong commentedon Aug 7, 2026
Release-board audit (maintainer-directed re-audit of non-board
domain:specitems, 2026-08-07): addingtarget:v17— criterion ①: withNODE_ENVunset, the second/discoveryproducer still broadcastsenvironment=development— the exact direction #5673 ruled dangerous; the ruled fix (fold unset→production into the shared mapper) is recorded. Triage seat may veto.Generated by Claude Code