Skip to content

文档/博客里的公式样例写裸引用 —— #5026 激活字段公式校验后,照抄这两处的元数据会被 os build 判红 #5116

Description

@xuyushun441-sys

#5026 把 validate-expressions.ts 的字段公式校验从 f.formula(spec 按名拒绝的别名)收敛到 f.expression,激活了一条从未跑过的检查。在做"全部真实元数据零新红"验证时顺带扫了 skills/ 和 content/ 里的公式样例 —— 三个 example app、platform-objects、default-permission-sets、skills/ 全绿,但文档和博客里有两处样例写的是裸引用,按 Prime Directive #10 单独记账,不在 #5026 的 PR 范围内(那个 PR 限于 packages/lint)。

事实

把每条样例喂给激活后的 validateExpression('value', src, { scope: 'record' }):

位置 源 判决
content/docs/data-modeling/fields.mdx:230 'quantity * price * (1 - discount / 100)' RED
content/blog/context-window-is-the-constraint.mdx:108 cel`amount * probability` RED

两条的错误文本一样:

bare reference `quantity` — a formula/validation expression binds the record as
the `record` namespace, not at top level, so `quantity` resolves to nothing and
the expression silently evaluates to null. Write `record.quantity`.

同一批扫描里判绿的(即 canonical、无需改动)包括 content/docs/data-modeling/formulas.mdx 的全部样例、field-types.mdx:408、getting-started/common-patterns.mdx:143、skills/objectstack-data/rules/field-types.md:300、skills/objectstack-data/rules/relationships.md:285、skills/objectstack-ui/SKILL.md:120。所以这是两处孤立的漏网,不是文档整体的惯例问题。

为什么值得修

fields.mdx 是 data-modeling 章节里讲 Field.formula() 的入口页之一,而裸引用在 CEL 里静默求值为 null——这正是 #1928 建这条检查的原因。#5026 之后,照着这一行写出来的元数据会在 os build / os lint / os validate 上判红,文档教的写法和平台的门直接矛盾。博客那篇的调性是"AI 照着 spec 写元数据",样例本身写错更尴尬。

顺带记一处不算缺陷但形状相同的:packages/spec/src/data/field.test.ts:363 的 expression: 'first_name + " " + last_name'。那个测试的被测对象是 FieldSchema.parse 能不能过,裸引用不影响它的断言,但它同样示范了错误拼法;改成 record. 前缀零成本。

修法

三处都是一行的事:

  • fields.mdx:230 → 'record.quantity * record.price * (1 - record.discount / 100)'
  • context-window-is-the-constraint.mdx:108 → cel`record.amount * record.probability`
  • (可选)field.test.ts:363 → 'record.first_name + " " + record.last_name'

content/docs/ 是手写目录(非 auto-gen),按 AGENTS.md 的 Documentation Guardrails 可以直接改;注意不要碰 content/docs/releases/。

值得一并考虑的更长期问题:check:skill-examples 只对标了 <!-- os:check --> 的块跑 tsc --noEmit,不跑任何表达式语义校验 —— 所以这类"能编译但 CEL 是错的"样例目前没有任何门。把文档/skills 里的公式样例喂给 validateExpression 做一道门,是比逐条修更根本的处置,但那是另一个单子的体量。

参考

Activity

  1. xuyushun441-sys commented on Aug 4, 2026

    @xuyushun441-sys
    CollaboratorAuthor

    认领(PM 分派)

    • session:session_018iARDqtrhQgz6fVHDeDkbQ
    • 分支:claude/issue-5116-formula-example-drift
    • 车道:domain:devx(落点:两处文档样例 + 视成本决定是否含样例语义门)

    范围分两半:① 修正点名的裸引用样例(必做);② 评估"样例过 CEL 语义校验"的门的成本 —— 便宜(能复用 #5026 激活的检查 + check:skill-examples 的既有基建)就一并落,不便宜就写明方案由 PM 另立。样例是语料,教错的成本按 AI 作者的复制次数放大 —— 这条与 #4913/#4929 把语料纳入 doc-authoring 的理由同源。


    Generated by Claude Code

  2. xuyushun441-sys commented on Aug 4, 2026

    @xuyushun441-sys
    CollaboratorAuthor

    审核通过 — PR #5140 已取消草稿并挂上 auto-merge(SQUASH);按维护者指示,这是本会话最后一单派发

    三处样例修正 + 一道判据扎实的新门,外加一次门禁自证。

    样例修正的红/绿在 #5026 分支的 detached worktree 上验证(#5118 未合时 main 的检查 inert —— 变通正确且如实说明);新门不依赖它:直接调 @objectstack/formula 的 validateExpression,与 os build 同一调用,零重实现(PD#12)。

    门的准入判据是测量出来的,不是设计出来的:语料里同一个 expression: 键承载三种互斥契约 —— record CEL、flow 扁平谓词(裸引用在那里是对的,7 处)、cron 串(4 处)。按键匹配会 11 处全误伤;按解析结构准入(Field.*({expression}) 或 type:'formula' 毗邻),实测 22 处真公式全收、零误伤。另两处硬功夫:两条原始缺陷都在无标记块且 blog 目录不在既有 marker 扫描根 —— 沿用现成基建两处都抓不到,这个测量决定了独立扫描;TS 把行首 { 解析成块语句造成的静默假阴性,被"提取不到即硬错"接住(第一版启发式就栽在这上面,被自己的硬错抓到)。self-test 用逐字原缺陷源做红例 —— 门不可能悄悄不再抓它为之而生的东西。

    返工一轮:门禁闭环的实证。 首推的脚本里有一个裸 NUL(offset 11513,在 git 8000 字节嗅探盲区外)—— 被昨天 #4890 建的门禁当场抓住,报错文案自带处方。这是"写关于字节的代码时落下那个字节"的第三次同型事故,而这次防线是机械的,不再靠人肉扫描。修复时 agent 还发现 14 字节外第二个裸控制字节(0x01)—— check:nul-bytes 目前不扫它,NUL-only 修复会放它过去;已一并转义并留注释。这暴露 #4890 门禁的一个覆盖缺口(0x01-0x08 等控制字节不在扫描面,而 #4890 议题里 dev 当年的手工扫描恰恰是全控制字符的)—— 已立 finding 单记录,遵守停派令不派发,归下一波。

    修复后全绿:NUL 门禁 5222 文件 OK、门 11/11+22、lint 1177、spec 7720、双 typecheck、ESLint。verdict 数字与修复前逐字相同 —— 换编码没换行为的直接证据。


    Generated by Claude Code

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

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions