Skip to content

docs(hook-bodies): 写集一节还在说"没有静态检查",#4305 之后已不成立(enforced ≠ declared) #4351

Description

@os-zhuang

现象

content/docs/automation/hook-bodies.mdx 的 "Not statically checked: the write set" 一节声称写面完全没有静态检查:

Not checked — write side. Nothing validates which fields your body writes. … no lint can verify they exist. This is an accepted gap with no planned closure

#4305(validateHookBodyWrites,已合入 main)起,这段话不成立:hook-body-write-unknown-field 会把 L2 hook body 里 ctx.input.x = … / Object.assign(ctx.input, {x}) / ctx.api.object('y').update({x}) 三类字面写解析出来,拿去和目标对象声明的字段比对,未知字段带 did-you-mean 告警(advisory,不 gate)。#4344 正在把同一套搬到 action 的 ctx.api 写面。

为什么值得记

这一节的下游建议全是从"没有检查"推出来的,现在读起来会把作者推离真正的工具:

  • "Check your write targets by hand." —— 已经有 lint 在报了;
  • "Prefer a flow update_record node … so they get the static checking hook bodies can't." —— 这条建议本身仍然对(flow 是 error,hook 是 advisory),但理由错了:hook body 现在静态检查,差别是严重级别和覆盖面(字面模式 vs 结构化 fields),不是有无。

"declared ≠ enforced" 的镜像:这里是 enforced ≠ declared —— 能力已经交付了,文档还在说没有。作者按文档放弃一个真实存在的护栏,和按文档相信一个不存在的护栏,代价是对称的。

需要改什么

  1. 把 "Not checked — write side" 改写成准确的覆盖面描述:检查哪三类字面模式、advisory 不 gate、哪些静态不可知(computed key、spread、aliased input、动态对象名、object:'*')因而告警的缺席不等于正确
  2. Hook body writes are not statically checkable — accept the gap or give HookSchema a structured writes declaration #3700(结构化 writes 声明,closed as not planned)仍然是准确的历史,但 "accepted gap with no planned closure" 的结论要撤回 —— 缺口是用另一条路(解析写集)关的,不是没关。
  3. 保留 flow update_record 的建议,把理由换成 error-vs-advisory + 结构化 vs 字面。
  4. feat(lint,spec): L2 action body 写不存在字段从盲区变为作者时 lint 告警 (#4271) #4344 落地后,同一节要补 action 侧的 ctx.api 写面。

边界

ctx.record 那一半不属于本 issue:那是 #4345(所有写都被丢弃,不分声没声明),已在同名 PR 里连同本文件的 sandbox-surface 表和 signature-conventions 一起处理了。本 issue 只针对"未知字段写"这一族的文档描述。

参考

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions