feat(formula): dateField == today() now matches — AST temporal-comparison rewrite (#3183)#3210
Merged
Conversation
…arison rewrite (#3183) A `Field.date` reads back as a "YYYY-MM-DD" string (ADR-0053 Phase 1), and cel-js's equality treats a string and a timestamp as unequal without consulting any overload, so `record.due_date == today()` silently returned false (and `!= today()` silently true) even for a same-day record. celEngine.evaluate now rewrites the parsed AST: for each `==`/`!=` whose one operand is today()/daysFromNow()/daysAgo()/now(), the field operand is wrapped in date(...) (the stdlib coercion), then serialized and evaluated — so `record.due_date == today()` runs as `date(record.due_date) == today()`. - Per-occurrence: a mixed `d == "literal" || d == today()` keeps the literal comparison intact while fixing the temporal one. - Type-blind-safe: date() degrades gracefully (already-Date passes through; non-date string / null → Invalid Date → stays false), so no field types are needed and no currently-correct result is worsened. - Cheap: reserializes only when such a comparison is present (plain-includes gate) and memoizes source → rewritten source. AST-based, no regex on input. Covers every interpreter site (formulas, defaults, validation, hooks, flow conditions) via the single evaluate chokepoint. RLS/sharing unaffected (cel-to-filter rejects function calls loudly). Supersedes the #3192 advisory lint (checkTemporalDateEquality + the temporalEqualityFields helper), now removed — with the runtime fixed it would be a false alarm. Flips the #3181 KNOWN GAP characterization test to assert the fix, and adds an objectql end-to-end test (a date formula field read via find()). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SuiM565BZ3TR1VD3prMguB
…wdtn7 # Conflicts: # packages/lint/src/validate-expressions.test.ts
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
📓 Docs Drift CheckThis PR changes 3 package(s): 17 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
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.
Conflict-resolved version of #3205 (head
claude/date-equality-runtime-hydration-3183), rebased onto the latestmainvia merge. Supersedes #3205.What this is
The runtime fix for the
date == today()silent-miss (#3183):celEngine.evaluaterewrites the parsed AST so that a==/!=againsttoday()/daysFromNow()/daysAgo()/now()wraps the field operand indate(...), comparing two Timestamps instead of aYYYY-MM-DDstring vs a timestamp. Per-occurrence, type-blind-safe, idempotent, memoized. Removes the superseded #3192 advisory lint.Conflict resolution
The only merge conflict was in
packages/lint/src/validate-expressions.test.ts, where two independent deletions overlapped:date-field equality guardrail (#3183)describe block (the feat(formula,lint): warn ondatefield == temporal-function silent-miss (#3183) #3192 advisory lint, now superseded by the runtime fix).main(via [11.0][A2] Remove dead author-facing metadata properties (ADR-0049 enforce-or-remove) #2377 / feat(spec)!: remove form-surfaced dead metadata props + correct 3 misclassified-live entries (#2377) #3199) removed theADR-0062 D7 — field.columnNamedescribe block and left a trailing explanatory comment.Resolved as the union: both describe blocks removed,
main's trailing comment kept.Verification
Built with turbo (dependency graph) and ran the affected suites — all green:
@objectstack/formula— 233 passed@objectstack/lint— 228 passed@objectstack/objectql— 946 passed🤖 Generated with Claude Code
Generated by Claude Code