Skip to content

Fix: treat naive as_of/now datetimes as UTC in recency scoring#1009

Draft
AdityaPainuli wants to merge 1 commit into
potpie-ai:mainfrom
AdityaPainuli:fix/naive-as-of-tz-crash
Draft

Fix: treat naive as_of/now datetimes as UTC in recency scoring#1009
AdityaPainuli wants to merge 1 commit into
potpie-ai:mainfrom
AdityaPainuli:fix/naive-as-of-tz-crash

Conversation

@AdityaPainuli

Copy link
Copy Markdown

Closes #1008

Problem

MCP context_resolve / context_search with a date-only or naive ISO as_of (e.g. "2024-06-01") crashes the whole read: _parse_as_of_iso returns a naive datetime, readers pass it to the ranker as its clock (TaskContext(now=req.as_of)), and _recency_score normalizes valid_at to tz-aware but never normalizes now — so now - valid_at raises TypeError: can't subtract offset-naive and offset-aware datetimes for any claim carrying a valid_at. "2024-06-01" and "2024-06-01T00:00:00Z" are the same instant; one worked, the other crashed.

What changed

Two small, layered fixes:

  • domain/ranking.py: added a module-private _ensure_utc() helper. rank() now normalizes a caller-supplied now, and _recency_score reuses the same helper for valid_at (replacing the previous inline normalization). Naive and aware datetimes can no longer mix inside the ranker, regardless of entry point.
  • adapters/inbound/mcp/server.py: _parse_as_of_iso interprets naive timestamps as UTC and always returns a tz-aware datetime — consistent with how naive valid_at values were already treated. Explicit offsets and the Z suffix are preserved as before.

The boundary fix makes MCP input semantics explicit (naive = UTC); the domain fix hardens the ranker for any other caller.

Behavior

Input Before After
as_of="2024-06-01" TypeError, whole read fails normal envelope, interpreted as UTC
as_of="2024-06-01T10:30:00" TypeError normal envelope, interpreted as UTC
as_of="2024-06-01T00:00:00Z" worked unchanged
as_of="2024-06-01T10:30:00+05:30" worked unchanged, offset preserved

Testing

  • 3 new ranking tests: naive now against aware and naive valid_at no longer crashes, and a naive now scores identically to its aware-UTC equivalent (same recency breakdown).
  • New test_mcp_as_of_parsing.py: every accepted as_of form parses tz-aware; naive input maps to UTC; explicit offset and Z handling preserved; blank/None returns None.
  • Full unit suite: 2049 passed, 1 skipped, 0 failures.
  • ruff check and ruff format clean (repo pre-commit config, v0.14.3).

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: f545d20e-861d-4266-89fd-e776c866c52f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@AdityaPainuli

Copy link
Copy Markdown
Author

Putting this as a draft as waiting for confirmation on the issue itself.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] MCP: date-only or naive as_of crashes context_resolve/context_search with TypeError in recency scoring

1 participant