fix(formula): hydrate ISO date/datetime strings on CEL overload fault (#1530)#1560
Merged
Conversation
…#1530) Date-typed formula fields (and any predicate comparing a date field to a temporal builtin) always evaluated to null. `Field.date` serializes to "YYYY-MM-DD" and `Field.datetime` to a full ISO string; cel-js compares that raw string against the `google.protobuf.Timestamp` returned by today() / now() / daysFromNow() and raises `no such overload`, which surfaced as a silent null (ADR-0032 §1c). This is the date analogue of the numeric-string fix (#1534), so it reuses the exact same fault-retry path in cel-engine: on a `no such overload`, hydrate the offending scope and retry ONCE. Extend that hydration to also coerce strict ISO-8601 date / date-time strings to `Date`, alongside the existing numeric-string → number coercion. Renamed `hydrateNumericStrings` → `hydrateOverloadStrings` to reflect both. Fixing it in the engine (not in objectql's applyFormulaPlan as the issue hypothesized) repairs every caller — formula fields, flow conditions, validation/workflow predicates — not just formula projection. Hydration runs only after a fault, so expressions that already type-check are never re-interpreted, and a genuine non-temporal string still faults loudly. Tests: 8 new cases in cel-engine.test.ts (is_expiring_soon date-only window, unmet compare → false, is_overdue, full ISO datetime vs now(), timestamp arithmetic today() - hire_date, mixed date+numeric record, non-temporal string still faults, no spurious coercion on string==string). Full formula suite green (90/90). Closes #1530. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
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.
Problem
Date-typed formula fields — and any predicate comparing a date field to a temporal builtin — always evaluate to
null(#1530).Field.dateserializes to"YYYY-MM-DD"andField.datetimeto a full ISO string; cel-js compares that raw string against thegoogle.protobuf.Timestampreturned bytoday()/now()/daysFromNow()and raisesno such overload, which is swallowed tonull(contrary to ADR-0032 §1c "no silent failure").Repro (templates
allaggregate, 7.7.0):contracts_contract.is_expiring_soon,todo_task.is_overdue,hr_employee.tenure_yearsall returnnulleven with clean date-only values.Fix
This is the date analogue of the numeric-string fix (#1534), so it reuses the exact same fault-retry path in
cel-engine.ts: on ano such overload, hydrate the offending scope and retry once. I extended that hydration to also coerce strict ISO-8601 date / date-time strings →Date, alongside the existing numeric-string → number coercion (hydrateNumericStrings→hydrateOverloadStrings).Fixing it in the engine (rather than in objectql's
applyFormulaPlan, as the issue hypothesized) repairs every caller — formula fields, flow conditions, validation/workflow predicates — not just formula projection.Safety, matching the #1534 precedent:
"soon") still faults loudly.string == stringalready type-checks → retry never runs → no spurious coercion of date-looking strings.Tests
8 new cases in
cel-engine.test.ts: date-onlyis_expiring_soonwindow, unmet compare →false(not fault),is_overdue, full ISO datetime vsnow(), timestamp arithmetictoday() - hire_date, mixed date+numeric record, non-temporal string still faults, no spurious coercion onstring == string.Full
@objectstack/formulasuite green: 90/90.Closes #1530.
🤖 Generated with Claude Code