Skip to content

docs(skills,docs): 三处 hook 文档不再教「批量写的行级谓词在 ctx.input.ast」(#5670) - #5901

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-5670-bulk-ast-doc-align
Aug 6, 2026
Merged

docs(skills,docs): 三处 hook 文档不再教「批量写的行级谓词在 ctx.input.ast」(#5670)#5901
os-zhuang merged 1 commit into
mainfrom
claude/issue-5670-bulk-ast-doc-align

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Closes #5670

纯散文对齐:三处文档/技能面仍在教「批量写的行级谓词在 ctx.input.ast」,按 #5273 / PR #5668 已落地的措辞逐处改正。不动引擎、不动 spec、不动 releases。

前提核实(对 origin/main = 5c94f833c)

issue 的断言 结果
三处文件面仍在 main 上带这句 ✅ 成立(行号有漂移,按内容定位:rules/hooks.md:115-116references/data-hooks.md:61-62data-flow.mdx:313)
写路径 input 是 { id, data, options } / { id, options } engine.ts:5243 / 5705
input: { ast } 只出现在两条读路径 engine.ts:4776 / 4909,分别喂 driver.find / findOne(行号相对 issue 正文有漂移)
批量写谓词走 OperationContext.ast(#2982),不进 hookContext.input ✅ pin 测试三条断言,详见下
#5038 后批量写 after* 按行派发、input.id 绑定 ✅ pin 测试两条断言
主句(批量写触发同名事件、没有 *Many 事件)仍成立 ✅ 保留原样
content/docs/releases/v16.mdx:185 带同句但排除在外 ✅ 未动
全仓 docs/skills 只有这三处 grep -rn 'input\.ast' content/ skills/ docs/ examples/ apps/ 恰好四条命中,第四条是被排除的 releases 页

无断言被证伪。 唯一偏差是行号漂移,已按内容搜索定位。

改了什么

三处删掉「the row-scoping predicate is in ctx.input.ast」半句,替换为同一套措辞的两句实情:

  1. 批量写不向 hook 暴露行级谓词 —— 它在引擎内部 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
  2. 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 from input at all … scope the batch through options.where at the CALLER … dispatch ONCE PER MATCHED ROW」),不自行发明。

两处刻意的局部差异

  • issue 编号:skills/objectstack-data/ 两份文件本来就带编号引用(data-hooks.md 12 处、rules/hooks.md 2 处),故补 (#2982) / (#5038);content/docs/api/data-flow.mdx 全文 issue 引用,那处按其本地惯例不引编号。
  • 不写仓内测试路径:issue 建议「真值可直接引 hook-input-shape-contract.test.ts」。三份文件现有引用里没有任何一条指向仓内 packages/** 路径,且 skill 经 npx skills add 装到第三方项目后那种路径并不存在 —— 真值引用因此放在本 PR 正文,而不是写进发布给客户的文本。

验证 —— 反向验证方向说明(重要)

本单没有可 revert 的代码,所以模板里「恢复删掉的分支 → 新测试转红」那条对它不适用;照那个形状伪造一段证据比留空更糟。这里的真值验证是另一条:我写进文档的每一句,都对应 PR #5668 已在 main 上的 pin 测试的一条绿断言。全文实测:

✓ [#5273] a bulk write carries no `ast` on `input` > POSITIVE CONTROL — a read DOES carry `input.ast`
✓ [#5273] a bulk write carries no `ast` on `input` > `beforeUpdate` on a bulk write has no `ast` key
✓ [#5273] a bulk write carries no `ast` on `input` > `beforeDelete` on a bulk write has no `ast` key
✓ [#5273] `input.id` on a bulk write > `beforeUpdate` leaves `id` undefined (the key exists; nothing binds it)
✓ [#5273] `input.id` on a bulk write > `afterUpdate` fires per matched row, each naming its own `id`
✓ [#5273] `input.id` on a bulk write > `afterDelete` fires per matched row, each naming its own `id`
✓ [#5273] the single-record rows of the table > insert carries `data` — never `doc`
✓ [#5273] the single-record rows of the table > a batch insert builds ONE context per row (#2922)
✓ [#5273] the single-record rows of the table > a single-id update binds `id` and `data`
✓ [#5273] the single-record rows of the table > a single-id delete binds `id` and carries no `data`
✓ [#5273] a metadata-declared hook reads the same shape > `ctx.input.ast` is undefined on a bulk update through the flat-input proxy

Test Files  1 passed (1)
     Tests  11 passed (11)

句子 → 断言的映射:「不暴露谓词」← 第 2 / 3 / 11 条(含声明式作者那条路径,正是这句假话原本写给的读者);「after* 按行派发、input.id 绑定」← 第 5 / 6 条;第 1 条是 #4865 阳性对照(读路径确实带 ast),所以这是一次测量,不是对着一个到处都不发 ast 的引擎空过。

门禁

命令 结果
pnpm check:nul-bytes OK(5699 文件,另对三个改动文件自扫 [\x00-\x08\x0b\x0c\x0e-\x1f\x7f],零命中)
pnpm check:doc-authoring ✅ 362 files clean
pnpm check:docs-audit-scope ✅ 178 hand-written doc(s) in sync;releases 9 页 review-only
pnpm check:role-word OK(43 baselined,无新增)
pnpm check:skill-frame-sync ✅ 4 copies isomorphic(39 markdown 扫描)
pnpm check:adr-anchors OK(30 anchored)
--filter @objectstack/spec check:skill-docs ✅ Skill docs in sync
--filter @objectstack/spec check:skill-refs ✅ 9 generated files in sync
--filter @objectstack/spec check:skill-examples ✅ 205 prose examples type-check
pnpm lint(eslint) 0
--filter @objectstack/objectql test 2084 passed (127 files)

changeset:无 → 已自行加 skip-changeset 标签

实测先例,不靠猜:

同口径先例:PR #5668(#5273 的 spec 侧修复)也是 skip-changeset,无 changeset。

顺带发现(PD #10,均未在本 PR 修)


Generated by Claude Code

引擎从未在写路径的 `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
@vercel

vercel Bot commented Aug 6, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 6, 2026 11:15am

Request Review

@github-actions github-actions Bot added the size/s label Aug 6, 2026
@os-zhuang os-zhuang added skip-changeset PR has no user-facing published change; bypasses the changeset gate and removed size/s labels Aug 6, 2026 — with Claude
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Aug 6, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review August 6, 2026 11:23
@os-zhuang
os-zhuang added this pull request to the merge queue Aug 6, 2026
Merged via the queue into main with commit c15fcee Aug 6, 2026
28 of 29 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-5670-bulk-ast-doc-align branch August 6, 2026 11:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

hooks 技能与 API 文档仍在教「批量写的行级谓词在 ctx.input.ast」——与 #5273 同一句假话,只是另外三个面

2 participants