Commit 641363a
* fix(docs,lint): canonical `record.` prefixes in two formula examples + a CEL semantic gate (#5116)
#5026 activated the field-formula check in validate-expressions.ts and its
real-metadata sweep found two doc examples teaching the bare-reference form:
content/docs/data-modeling/fields.mdx:230 'quantity * price * (1 - discount / 100)'
content/blog/context-window-is-the-constraint.mdx:108 cel`amount * probability`
A bare reference in a record-scoped CEL expression does not throw — it resolves
to nothing and the expression silently evaluates to null. Both are corrected to
the canonical `record.` form, verified by loading each into a minimal
spec-valid stack and running the activated validateStackExpressions (RED before,
GREEN after). packages/spec/src/data/field.test.ts:363 demonstrated the same
wrong spelling and is corrected too; its assertion is unchanged.
Adds `@objectstack/lint`'s check:doc-formula-expressions, the semantic gate that
was missing: check:doc-authoring judges literal SHAPE and check:skill-examples
runs tsc, so a formula that compiles and is semantically wrong passed both
(`expression` is typed `string`). The verdict is validateExpression imported
from @objectstack/formula — the same call `os build` makes, not a lookalike.
The discriminator is the design: `expression:` carries three unrelated contracts
in this corpus (record-scoped CEL, flow-flattened predicate where a bare ref is
CORRECT, and a cron string), so sites are opted in only by parsed structure —
`Field.*({ expression })` or `type: 'formula'` beside `expression`. A block that
looks like it carries one but cannot be extracted is a hard error, not a skip.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018iARDqtrhQgz6fVHDeDkbQ
* fix(lint): write the dedup key's control chars as escapes, not raw bytes (#5116)
`check:nul-bytes` (#4890) caught a raw NUL at
packages/lint/scripts/check-doc-formula-expressions.mjs:258 — offset 11513,
well outside git's 8000-byte binary sniff, which is exactly the blind spot that
gate exists for. A scan for every control byte found a second one beside it
(0x01, which the NUL gate does not even look for), both in the extraction
dedup key.
Replaced by script with their `\u….` escape sequences — byte-equivalent at
runtime, so the verdict is unchanged: the gate's self-test still passes 11/11
and the corpus scan still reports the same 22 clean examples across 375 files
/ 1408 TS blocks. Added a comment saying both control chars are deliberate and
must stay escaped, since a raw one is invisible in review and a literal NUL
makes grep/ripgrep treat the whole file as binary and silently return zero
matches.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018iARDqtrhQgz6fVHDeDkbQ
---------
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 81e2744 commit 641363a
7 files changed
Lines changed: 557 additions & 4 deletions
File tree
- .changeset
- .github/workflows
- content
- blog
- docs/data-modeling
- packages
- lint
- scripts
- spec/src/data
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
588 | 588 | | |
589 | 589 | | |
590 | 590 | | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
| 598 | + | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
591 | 615 | | |
592 | 616 | | |
593 | 617 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
105 | 105 | | |
106 | 106 | | |
107 | 107 | | |
108 | | - | |
| 108 | + | |
109 | 109 | | |
110 | 110 | | |
111 | 111 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
227 | 227 | | |
228 | 228 | | |
229 | 229 | | |
230 | | - | |
| 230 | + | |
231 | 231 | | |
232 | 232 | | |
233 | 233 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
25 | | - | |
| 25 | + | |
| 26 | + | |
26 | 27 | | |
27 | 28 | | |
28 | 29 | | |
| |||
0 commit comments