docs(skills,docs): 三处 hook 文档不再教「批量写的行级谓词在 ctx.input.ast」(#5670) - #5901
Merged
Conversation
引擎从未在写路径的 `HookContext` 上放过 AST。`packages/objectql/src/engine.ts`
的 5 个 `HookContext` 生产点里,`input: { ast }` 只出现在两条读路径(喂
`driver.find` / `findOne`);写路径构造的是 `{ id, data, options }` 与
`{ id, options }`,批量写的行级谓词走引擎内部的 `OperationContext.ast`(#2982),
从不进 `hookContext.input`。#5273 已把 spec 侧那份契约表改成引擎真正构造的形状
(PR #5668),真值由新增的 `packages/objectql/src/hook-input-shape-contract.test.ts`
钉死 —— 其中 `beforeUpdate` / `beforeDelete` 在 `multi: true` 上都断言
`'ast' in input === false`,并以 `beforeFind` 作阳性对照证明引擎并非到处不发 `ast`。
同一句从未兑现的陈述还活在三个面上,本单按已落地措辞逐处对齐:
- `skills/objectstack-data/rules/hooks.md`
- `skills/objectstack-data/references/data-hooks.md`
- `content/docs/api/data-flow.mdx`
三处改法一致:删掉「the row-scoping predicate is in `ctx.input.ast`」半句,替换为
两句实情 —— 批量写不向 hook 暴露谓词(谓词在引擎内部 `OperationContext.ast`,
composed 的 RLS / sharing 过滤器由此绑定 driver 调用本身,handler 无法放宽;要
限定批量就在调用方用 `options.where`),以及 #5038 之后 `after*` 按匹配行派发、
每行单记录形状、`input.id` 在那里绑定。主句(批量写触发同名事件、没有 `*Many`
事件)本身成立,原样保留。
前两个文件属已发布 skill 目录,沿其既有惯例带 issue 编号;`data-flow.mdx` 全文
零 issue 引用,故那处不引编号。三处都不写仓内 `packages/**` 测试路径 —— 这三份
文件现有引用里没有一条指向仓内源码路径,而 skill 经 `npx skills add` 装到第三方
项目后那种路径也不存在。
⛔ `content/docs/releases/v16.mdx:185` 带同句但未动:发布态记录按 CLAUDE.md 不在
代码 PR 里改。`packages/spec/**` 未动(#5668 已修)。
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GX3sL71LFq8m2usg6VqTSE
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
os-zhuang
marked this pull request as ready for review
August 6, 2026 11:23
This was referenced Aug 6, 2026
This was referenced Aug 6, 2026
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.
Closes #5670
纯散文对齐:三处文档/技能面仍在教「批量写的行级谓词在
ctx.input.ast」,按 #5273 / PR #5668 已落地的措辞逐处改正。不动引擎、不动 spec、不动 releases。前提核实(对
origin/main=5c94f833c)rules/hooks.md:115-116、references/data-hooks.md:61-62、data-flow.mdx:313){ id, data, options }/{ id, options }engine.ts:5243/5705input: { ast }只出现在两条读路径engine.ts:4776/4909,分别喂driver.find/findOne(行号相对 issue 正文有漂移)OperationContext.ast(#2982),不进hookContext.inputafter*按行派发、input.id绑定*Many事件)仍成立content/docs/releases/v16.mdx:185带同句但排除在外grep -rn 'input\.ast' content/ skills/ docs/ examples/ apps/恰好四条命中,第四条是被排除的 releases 页无断言被证伪。 唯一偏差是行号漂移,已按内容搜索定位。
改了什么
三处删掉「the row-scoping predicate is in
ctx.input.ast」半句,替换为同一套措辞的两句实情:OperationContext.ast(Security: bulk (multi) update/delete skips OWD owner scoping on private objects — members can modify others' rows #2982),composed 的 RLS / sharing 过滤器由此绑定 driver 调用本身,handler 无法放宽;要限定批量,就在调用方用options.where。after*改为按匹配行派发,每行是单记录形状,input.id在那里绑定([17.x] 批量写按行语义实现:hook 按行触发 + record-change trigger 按行绑定 previous/record(#4800/#4862 拍板 A) #5038)。措辞取自 PR #5668 落在
packages/spec/src/data/hook.zod.ts:340-357的那段(「NOT reachable frominputat all … scope the batch throughoptions.whereat the CALLER … dispatch ONCE PER MATCHED ROW」),不自行发明。两处刻意的局部差异
skills/objectstack-data/两份文件本来就带编号引用(data-hooks.md12 处、rules/hooks.md2 处),故补(#2982)/(#5038);content/docs/api/data-flow.mdx全文零 issue 引用,那处按其本地惯例不引编号。hook-input-shape-contract.test.ts」。三份文件现有引用里没有任何一条指向仓内packages/**路径,且 skill 经npx skills add装到第三方项目后那种路径并不存在 —— 真值引用因此放在本 PR 正文,而不是写进发布给客户的文本。验证 —— 反向验证方向说明(重要)
本单没有可 revert 的代码,所以模板里「恢复删掉的分支 → 新测试转红」那条对它不适用;照那个形状伪造一段证据比留空更糟。这里的真值验证是另一条:我写进文档的每一句,都对应 PR #5668 已在 main 上的 pin 测试的一条绿断言。全文实测:
句子 → 断言的映射:「不暴露谓词」← 第 2 / 3 / 11 条(含声明式作者那条路径,正是这句假话原本写给的读者);「
after*按行派发、input.id绑定」← 第 5 / 6 条;第 1 条是 #4865 阳性对照(读路径确实带ast),所以这是一次测量,不是对着一个到处都不发ast的引擎空过。门禁
pnpm check:nul-bytes[\x00-\x08\x0b\x0c\x0e-\x1f\x7f],零命中)pnpm check:doc-authoringpnpm check:docs-audit-scopepnpm check:role-wordpnpm check:skill-frame-syncpnpm check:adr-anchors--filter @objectstack/spec check:skill-docs--filter @objectstack/spec check:skill-refs--filter @objectstack/spec check:skill-examplespnpm lint(eslint)--filter @objectstack/objectql testchangeset:无 → 已自行加
skip-changeset标签按实测先例,不靠猜:
metadata.version不 bump。 全仓历史里只有77adf297f(已发布 skillobjectstack-pm-dispatch仍是两轴决策框架 —— 与.claude/内部三轴(#5130)分叉,且「创业聚焦」轴是否该泛化给第三方项目未定 #5451 / PR docs(skills): 已发布 skillobjectstack-pm-dispatch的决策框架由两轴升为三轴(裁决 B:泛化内核后搬) #5799)bump 过 skill 版本,那是维护者裁决的「决策框架两轴改三轴」——改的是已安装 agent 遵循的判定程序。而skills/objectstack-data/自身的内容修改先例是72c3c8613、cbb6a5ca2、28ad90e9a三次,都没有 bump;其中cbb6a5ca2改的正是本次这个references/data-hooks.md,改的也正是同一类事情(把一个已不存在的字段从教学里去掉)。另外skills/README.md的 frontmatter 字段表根本没有收录metadata.version,本单也未触碰任何SKILL.md。skip-changeset标签。 这是changeset-check自己的处方原文(Check Changeset 的失败文案把「空 changeset」推荐为出路 —— 而那正是 #4898 静默卡死发布的输入 #5292 / 空 changeset 会静默卡死已 version 的发布:Release run 全绿,但 npm 和 Docker 什么都没发(17.0.0-rc.2 现在就卡着) #4898 之后):路线 2「releases nothing(.github/、.claude/、docs/、content/、examples、tests-only 之类)→ 加skip-changeset标签 ← PREFERRED」;空 frontmatter changeset 是显式的 last resort(它是 changesets/action 的真实输入,全空集会静默绿着卡住 release)。本单零包源码改动,故取路线 2。同口径先例:PR #5668(#5273 的 spec 侧修复)也是
skip-changeset,无 changeset。顺带发现(PD #10,均未在本 PR 修)
HookEvent的枚举注释仍在说批量写把行级谓词「carried ininput」—— 与 #5273 同一句假话,在同文件 40 行之外 #5899 —— 同一句假话在packages/spec/src/data/hook.zod.ts:135-140的HookEvent枚举注释里还剩一处(写作「carried ininput」,无.ast后缀)。PR docs(spec): HookContext.input 契约表改成引擎真正构造的形状 (#5273) #5668 改的是同文件 200 行外的契约表,这段自b49ccfdfe起未被触及,于是同一个文件目前自相矛盾。本单派发面明确排除packages/spec/**,不顺手改。multi: true批量写只触发一次、previous无从绑定」,并明令作者不要在可能批量触发的 hook 里用previous#5900 ——references/data-hooks.md的conditionCEL 绑定一节(:254-257、:274-278)仍按 [17.x] 批量写按行语义实现:hook 按行触发 + record-change trigger 按行绑定 previous/record(#4800/#4862 拍板 A) #5038 之前教:「multi: true批量写 hook 只触发一次,previous无从绑定」,并明令「never reach forpreviousin a hook that can fire on … amulti: truewrite」。这对before*成立,对after*不成立 ——bulk-write-per-row-hooks.test.ts用的常量就是record.status == "done" && previous.status != "done",按行求值通过。危害方向与本单相反:那处是禁止平台已支持并已 pin 的模式。虽在本单文件面内,但属不同断言,按 PD chore: version packages #10 单独立项。Generated by Claude Code