Skip to content

fix(runtime): 无 setFallbackHandler 的适配器改以 warn 宣告声明式端点不可达 (#5400) - #5409

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-5400-dispatcher-fallback-warn
Aug 5, 2026
Merged

fix(runtime): 无 setFallbackHandler 的适配器改以 warn 宣告声明式端点不可达 (#5400)#5409
baozhoutao merged 1 commit into
mainfrom
claude/issue-5400-dispatcher-fallback-warn

Conversation

@baozhoutao

Copy link
Copy Markdown
Contributor

Fixes#5400

前提核对(先于实现)

issue 引用的是 f417863fc,已过时 —— 今晨 #5404(#5399)刚改写过这处注释。以 origin/main(4b61cf3)为准逐条核对,前提全部成立:

即:声明能发布、能被声明的端点在无接缝的适配器上永久不可服务、而唯一信号不打印 —— 三段齐备。

改了什么

setFallbackHandler 是 metadata 声明的 apis: 端点抵达 handler 的唯一接缝,且在 IHttpServer 上是可选成员(契约明写消费者用 typeof === 'function' 探测)。适配器不暴露它时没有第二条路:所有声明的端点永久不可服务,调用方只拿到传输层的裸 404 —— 与拼错路径毫无区别。

一行级别改动,并按 AGENTS.md「Absence must be loud」(Route & surface ownership §3)的要求让这条日志同时带上两半:

  • 后果 —— 该传输上任何 metadata 声明的 apis: 端点都不会被服务,只会回裸 404;
  • 补救 —— 换用实现了 setFallbackHandler 的 HTTP 适配器(如 @objectstack/plugin-hono-server)。

附带 { mount, declarativeEndpoints: 'unreachable' } 结构化 meta,便于机读。

原处注释一并改写为翻转后的真话(不留 #5404 那版「当前仍是 debug」的过期叙事),并记下级别选择的理由。

为什么是 warn 而不是 error

按「Degradation log levels」那个唯一判据 —— 降级后系统对外看着正常,而它声称已持久化的东西其实没落盘吗? —— 答案是否:这里没有任何持久化承诺。属功能性降级(某能力没挂上,下一个调用它的人自然会发现),与该节参考文案「scheduled flows will not run until a job service is registered」同形。故 warn,不升 error

钉级别的测试

新增 packages/runtime/src/dispatcher-plugin.fallback-absence-warn.test.ts(5 例,均显式 }, 60_000)),参照 #5226「级别由门禁焊住」姿态:

  1. 缺接缝时发一条、且级别为 warn —— 退回 debug 或误升 error 都红;
  2. 文案含后果(metadata-declared / `apis:` / UNREACHABLE / bare 404);
  3. 文案含补救(setFallbackHandler / @objectstack/plugin-hono-server);
  4. meta 带受影响挂载前缀;
  5. 反向用例 —— 适配器暴露接缝时这条完全不出声(保证 warn 是信号而非启动噪音,改发的是 Declarative endpoint dispatch step armed)。

反向验证(方向先于执行预判)

预判为常规 Red 方向,理由写在测试文件头:断言读的是发出级别这一谓词,而非可能「因为什么都没产出而通过」的计数。实测两个方向都焊住:

  • 改回 ctx.logger.debug4 failed | 1 passed,AssertionError: expected 'debug' to be 'warn',5 号(合规适配器静默)仍绿 —— 符合预判;
  • 升到 ctx.logger.error → 同样 4 failed | 1 passed,AssertionError: expected 'error' to be 'warn'

随后已还原为 warn 并复跑全绿。

消费半径巡检

按「按规则的消费半径扫 fixture」逐一核过所有装载 dispatcher 的用例:走真实 Hono 适配器的(接缝存在,不进该分支)与用假 server 的(logger 为 no-op,无 warn 断言)均不受影响;全仓无第二处引用旧文案。

验证

  • npx vitest run --maxWorkers=2 src/dispatcher-plugin.fallback-absence-warn.test.tsTest Files 1 passed (1) / Tests 5 passed (5)
  • runtime 全量 npx vitest run --maxWorkers=2Test Files 93 passed (93) / Tests 1346 passed (1346)(92 → 93 即本 PR 新增文件)
  • pnpm --filter '@objectstack/runtime' typecheck → exit 0
  • 门禁:check:durability-log-level / check:nul-bytes / check:startup-registry-verdict / check:wildcard-fallthrough / check:route-envelope 全 PASS

范围

packages/runtime/src/dispatcher-plugin.ts + 新增测试 + changeset。⛔ 未触碰 #5122HttpServer 包装器本体(相邻但独立,另单处理)。无 API / schema / 路由变更;已在合规适配器上的部署看不到任何新增输出。

🤖 Generated with Claude Code

https://claude.ai/code/session_016FNvXhtSdnEGEfLEsMmvxh


Generated by Claude Code

`setFallbackHandler` 是 metadata 声明的 `apis:` 端点抵达 handler 的**唯一**接缝,
且在 `IHttpServer` 上是可选成员。适配器不暴露它时,所有声明的端点永久不可服务,
调用方只拿到传输层的裸 404 —— 与拼错路径毫无区别。
此前这条只记 `debug`。该级别曾经是对的:在非空 `apis:` 于发布期被整体拒绝(#4936)
的年代,没有任何部署可能"缺"什么,因为没有任何部署能声明什么。#5040 E7 发布翻转
终结了这个前提 —— 声明现在能发布,stack 也确实在发。而默认 `level: 'info'` 根本
不打印 `debug`(`packages/core/src/logger.ts` 的 `isEnabled`),运维侧等于零信号,
正是 AGENTS.md「Absence must be loud」(Route & surface ownership §3)点名要避免的
「留一个裸 404 让人去诊断」。
因此升为 `warn`,并按该节要求让这一行同时带上两半:
- **后果** —— 该传输上任何 metadata 声明的 `apis:` 端点都不会被服务,只会回裸 404;
- **补救** —— 换用实现了 `setFallbackHandler` 的 HTTP 适配器
(如 `@objectstack/plugin-hono-server`)。
刻意是 `warn` 而非 `error`:按「Degradation log levels」那个唯一判据 —— 降级后系统
对外看着正常,而它声称已持久化的东西其实没落盘吗? —— 答案是否,这里没有任何持久化
承诺。属功能性降级(某能力没挂上,下一个调用它的人自然会发现),与参考文案
「scheduled flows will not run until a job service is registered」同形。
新增 `dispatcher-plugin.fallback-absence-warn.test.ts` 把级别焊死(参照 #5226
「级别由门禁焊住」姿态):级别退回 `debug` 或误升 `error` 都会红,并另钉一条反向
用例 —— 合规适配器上这条完全不出声,保证 warn 是信号而非启动噪音。
反向验证(方向先于执行预判,属常规 Red 方向,因断言读的是发出级别这一**谓词**,
而非可能"因为什么都没产出而通过"的计数):
- 改回 `debug` → 1-4 号用例红(`expected 'debug' to be 'warn'`),5 号仍绿;
- 升到 `error` → 同样 1-4 号红(`expected 'error' to be 'warn'`)。
仅运维可见:无 API / schema / 路由变更,已在合规适配器(默认
`@objectstack/plugin-hono-server`)上的部署看不到任何新增输出。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016FNvXhtSdnEGEfLEsMmvxh
@vercel

vercelBot commented Aug 5, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectstackIgnoredIgnoredAug 5, 2026 9:03am

Request Review

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tests tooling labels Aug 5, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/runtime.

21 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/api/client-sdk.mdx(via packages/runtime)
  • content/docs/api/index.mdx(via @objectstack/runtime)
  • content/docs/api/wire-format.mdx(via @objectstack/runtime)
  • content/docs/automation/hook-bodies.mdx(via @objectstack/runtime)
  • content/docs/concepts/metadata-lifecycle.mdx(via @objectstack/runtime)
  • content/docs/concepts/north-star.mdx(via packages/runtime)
  • content/docs/data-modeling/drivers.mdx(via @objectstack/runtime)
  • content/docs/deployment/index.mdx(via @objectstack/runtime)
  • content/docs/deployment/production-readiness.mdx(via @objectstack/runtime)
  • content/docs/deployment/single-project-mode.mdx(via @objectstack/runtime)
  • content/docs/deployment/vercel.mdx(via @objectstack/runtime)
  • content/docs/getting-started/your-first-project.mdx(via @objectstack/runtime)
  • content/docs/kernel/cluster.mdx(via @objectstack/runtime)
  • content/docs/permissions/authentication.mdx(via @objectstack/runtime)
  • content/docs/permissions/authorization.mdx(via packages/runtime)
  • content/docs/plugins/packages.mdx(via @objectstack/runtime)
  • content/docs/protocol/kernel/http-protocol.mdx(via @objectstack/runtime)
  • content/docs/protocol/kernel/index.mdx(via @objectstack/runtime)
  • content/docs/protocol/kernel/lifecycle.mdx(via @objectstack/runtime)
  • content/docs/releases/implementation-status.mdx(via @objectstack/runtime)
  • content/docs/releases/v17.mdx(via @objectstack/runtime)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/mteststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

E7 翻转后,「适配器无 setFallbackHandler」仍只记 debug —— 声明式端点静默不可达,而代码注释自己写明此时应转 warn

2 participants

@baozhoutao@claude