Repository navigation
文档/博客里的公式样例写裸引用 —— #5026 激活字段公式校验后,照抄这两处的元数据会被 os build 判红 #5116
Description
Activity
- addedbugSomething isn't workingSomething isn't workingdocumentationImprovements or additions to documentationImprovements or additions to documentation
on Aug 4, 2026 xuyushun441-sys commented
on Aug 4, 2026 CollaboratorAuthorMore actions认领(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
- session:
- added a commit that references this issue
on Aug 4, 2026 xuyushun441-sys commented
on Aug 4, 2026 CollaboratorAuthorMore actions审核通过 — 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
#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)'content/blog/context-window-is-the-constraint.mdx:108cel`amount * probability`两条的错误文本一样:
同一批扫描里判绿的(即 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做一道门,是比逐条修更根本的处置,但那是另一个单子的体量。参考
f.formula—— spec 声明的是expression,这段从未对任何 spec 合法 stack 跑过 #5026(激活字段公式校验;发现于其真实元数据扫描)、Formula guardrail: cel-js arithmetic silently returns null (double × int + bare identifiers) #1928(裸引用/类型健全性)、validate-expressions / validate-security-posture 也有同形的 spec 不声明键的??别名读法(#5009 建议 3 的核对结果) #5017(同族的别名收敛)