feat(lint,spec): L2 hook body 写不存在字段从 accepted gap 变为作者时 lint 告警 (#4271) - #4305
Merged
Conversation
…hor time (#4271) An L2 (language:'js') hook body writing a field the target object never declares runs clean in the sandbox, reports success, and the unknown column never lands — the #4001 silent-no-op failure mode at the runtime-expression layer. New advisory rule `hook-body-write-unknown-field` parses the body (never executes it), resolves the literal writes declared in the HOOK_BODY_WRITE_PATTERNS ledger against the target object's declared + system fields, and warns with a did-you-mean. Wired via REFERENCE_INTEGRITY_RULES (validate/lint/compile at once); TypeScript parser loads lazily off the kernel boot path; every ledger entry is reconciliation-tested against the extractor. Statically unknowable writes bail silently — zero false positives over completeness. The hook-body.zod.ts "accepted gap" note now points at the lint. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…int-warning-4e1787
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 2 package(s): 107 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
…not a raw NUL byte The raw byte trips check:nul-bytes (a NUL makes grep treat the file as binary, dropping it out of every grep-based lint); the escape sequence is byte-identical at runtime. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…int-warning-4e1787
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 #4271。
做了什么
新增
@objectstack/lint规则hook-body-write-unknown-field(validate-hook-body-writes.ts):解析 L2(language:'js')hook body 的source(TypeScript parser,只 parse、不执行、不 type-check),把字面量写集对照目标对象「声明字段 + 系统字段」,未知字段发 advisory warning 并带findClosestMatches的 did-you-mean。挂进REFERENCE_INTEGRITY_RULES,os validate/os lint/os compile一次全覆盖,CLI 零改动;不进defineStack运行时。hook-body.zod.ts:134的「Write-set opacity — accepted static-analysis gap」段落改写为指向本 lint,并明确列出仍然不查的形态,避免「没告警=没问题」的误读。关键设计(按 issue 方案落地,两处按实况修正)
HOOK_BODY_WRITE_PATTERNS每条带 canonical example,测试用真提取器 round-trip,断言产出与声明逐条完全一致且都带该条 pattern id —— 「声明了模式但没人验证」(Console: screen-flow Submit never calls the resume endpoint — every screen flow is un-completable from the UI #3528 的死法)在此结构性不可能。ctx.api写面按ObjectRepository真签名编:insert(data)/create(data)/update(data, options)载荷在第 0 位,updateById(id, data)在第 1 位 —— issue 里的.update(id, { x })形状实际不存在;.create是insert的真实 alias,一并支持。installFlatInput)的信封键id/options/ast/data是 envelope 写不是记录字段写,永不判为字段。object:'*'通配 hook 的ctx.input写、跨包对象、一层 const 别名(记为 v1 known miss)。多目标 hook 只在字段在所有已知目标上都缺时才告警 —— body 可用ctx.object === '…'按对象分支,partial miss 静态上不可判错。HookBodyWriteSeverity = 'warning'类型层面固定「永不阻断」,与lintUnknownAuthoringKeys(排查「手抄 spec 清单 + "keep in sync" 注释」模式:一天内确认三例,全部曾静默漂移 #3786)姿态一致。validate-react-page-props同款 createRequire 惰性加载,另加ctx/Object标识符预筛 —— 没有 JS body、或 body 根本不含这些标识符时零解析零加载。lazy-deps.test.ts三层守卫(结构扫描 / dist 探针 / in-process)全部扩到本规则。验证
packages/lint:38 文件 565 测试全过(含 27 个新测试、两个 dist 探针);eslint 干净。check:generated8 个生成物门禁全绿(注释改动不落生成 docs)。origin/main后按 AGENTS.md §9 刷新构建,全仓pnpm build+pnpm testexit 0。os validate打出 ⚠ + did-you-mean 且继续后续检查;examples 三个自带 JS hook 均写声明字段,零自触发。@objectstack/lintminor +@objectstack/specpatch。🤖 Generated with Claude Code