Skip to content

Commit a7b7a57

Browse files
claude[bot]claude
andauthored
docs(skills): objectstack-formula factual sweep — every behavioral claim verified against the implementation (#13674)
Six measured falsehoods corrected, token-neutral under the skills ratchet (6002/6002, no ceiling raise). Verified against `@objectstack/formula`, `@objectstack/lint` and `@objectstack/spec` by reading plus executed probes. Claude-Session: https://claude.ai/code/session_01EXxTW8mvPBhoHxmyPZ63de Co-authored-by: Claude <noreply@anthropic.com>
1 parent 9057811 commit a7b7a57

1 file changed

Lines changed: 9 additions & 12 deletions

File tree

skills/objectstack-formula/SKILL.md

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -152,12 +152,10 @@ in `coalesce(..., '')`.
152152

153153
## ObjectStack CEL standard library
154154

155-
Registered automatically. Source:
156-
`node_modules/@objectstack/formula/src/stdlib.ts`.
157-
158-
The canonical list is `CEL_STDLIB_FUNCTIONS` in
159-
`node_modules/@objectstack/formula/src/validate.ts` — a
160-
test asserts every entry resolves at runtime, so this table stays in sync with it.
155+
Registered automatically by `@objectstack/formula`, which ships `dist` only —
156+
there is no `src/` to read in an installed app. Its exported
157+
`CEL_STDLIB_FUNCTIONS` is the canonical list, pinned by two tests: every entry
158+
resolves at runtime, and this table documents them all.
161159

162160
**Dates**
163161

@@ -172,7 +170,7 @@ test asserts every entry resolves at runtime, so this table stays in sync with i
172170
| `addMonths(d, n)` | timestamp | Shift **any** date by `n` months; clamps to month-end (`addMonths(date('2026-01-31'), 1)` → Feb 28) |
173171
| `date(s)` / `datetime(s)` | timestamp | Parse an ISO date / date-time string to a timestamp |
174172

175-
> **No date arithmetic.** Do NOT write `end - start`, `date + n`, or `today() + 30`CEL has no numeric arithmetic on dates, so these fault and the field silently nulls (the build now rejects them). Use `daysBetween(start, end)` for a span in days, and `daysFromNow(n)` / `addDays(d, n)` / `addMonths(d, n)` to shift a date. Inclusive day span: `daysBetween(record.start_date, record.end_date) + 1`. Tenure in years: `daysBetween(record.hire_date, today()) / 365`. For a genuine sub-day offset use `now() + duration("3h")` — the calendar-day helpers always land on UTC midnight.
173+
> **No date arithmetic.** Do NOT write `end - start`, `date + n`, or `today() + 30`a date mixed with a number faults and the field silently nulls (the build rejects it); `end - start` does not fault, it yields a `duration` stored as `{}`. Use `daysBetween(start, end)` for a span in days, and `daysFromNow(n)` / `addDays(d, n)` / `addMonths(d, n)` to shift a date. Inclusive day span: `daysBetween(record.start_date, record.end_date) + 1`. Tenure in years: `daysBetween(record.hire_date, today()) / 365`. For a genuine sub-day offset use `now() + duration("3h")` — the calendar-day helpers always land on UTC midnight.
176174
177175
**Numbers**
178176

@@ -418,14 +416,14 @@ to the envelope.
418416
| `Field` | `expression` (when `type: 'formula'`) | cel |
419417
| `Field` | `visibleWhen` / `readonlyWhen` / `requiredWhen` | cel |
420418
| `View` / `Page` | `visibleWhen` (form section/field, page component) | cel |
421-
| `Field` | `defaultValue` (M9.9b) | cel |
419+
| `Field` | `defaultValue` (envelope only; bare string = literal) | cel |
422420
| `ConditionalValidation` | `when` | cel |
423421
| `View` / `Page` | `visibleOn` / `visibility` (deprecated aliases of `visibleWhen`, ADR-0089) | cel |
424422
| `Action` | `disabled` | cel (or boolean) |
425423
| `Hook` | `condition` | cel |
426424
| `SharingRule` | `condition` | cel |
427425
| `Flow.decision` | `expression` / edge `condition` | cel (use `vars.<step>.<key>`) |
428-
| `Dataset.records[*]` | any value | cel (via `cel\`\``) |
426+
| `Seed.records[*]` | any value | cel (via `cel\`\``) |
429427
| `audit` / `metrics` / `tracing` | `condition` / `successCriteria` | structured \| cel |
430428

431429
View list filters are **not** a CEL surface — they are structured JSON filter
@@ -439,7 +437,7 @@ All accept bare strings (auto-wrapped to `{dialect:'cron', source}`) or the
439437
| Surface | Field |
440438
|:---|:---|
441439
| `Job.schedule.expression` | canonical |
442-
| `connector.schedule`, `etl.schedule`, `sync.schedule` | pipelines |
440+
| `connector.schedule` | scheduled connector sync |
443441
| `system/cache.schedule` | warmup |
444442
| `system/disaster-recovery.schedule` | backup + drill |
445443
| `automation/execution.cronExpression` | scheduled state |
@@ -472,9 +470,8 @@ tmpl`Deal {{ record.name }} — {{ record.amount | currency }} closes {{ record.
472470
| Surface | Field |
473471
|:---|:---|
474472
| `Object.titleFormat` | record title — **deprecated** (→ `nameField`, ADR-0079) |
475-
| `system/notification` | email subject + body, SMS message, push body + message (5 fields) |
476473
| `ai/model-registry` | `promptTemplate.system`, `promptTemplate.user` |
477-
| `integration/connector/github` | titleTemplate, bodyTemplate (PR + release) |
474+
| `system/email-template` | `subject`, `bodyHtml`, `bodyText` (plain strings, `{{ }}` rendered by the email pipeline) |
478475

479476
There is no JS expression surface: procedural JS is the L2
480477
`ScriptBody { language: 'js' }` surface (hook bodies), not an expression

0 commit comments

Comments
 (0)