Skip to content

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

Open
AdityaPainuli wants to merge 2 commits into
potpie-ai:mainfrom
AdityaPainuli:fix/naive-as-of-tz-crash
Open

Fix: treat naive as_of/now datetimes as UTC in recency scoring#1009
AdityaPainuli wants to merge 2 commits 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

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

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

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 9d352d08-1626-4bb1-8a70-1bb34e0a340a

📥 Commits

Reviewing files that changed from the base of the PR and between 240dc72 and b3681d2.

📒 Files selected for processing (2)
  • potpie/context-engine/src/potpie_context_engine/domain/ranking.py
  • potpie/context-engine/tests/unit/test_ranking.py

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Improved ranking consistency when timestamps lack timezone information.
    • Naive timestamps are now interpreted as UTC, ensuring accurate recency scores across mixed timestamp formats.
  • Tests

    • Added coverage verifying consistent ranking results for naive and timezone-aware timestamps.

Walkthrough

RankingService.rank now treats naive TaskContext.now values as UTC. Candidate timestamps use the same normalization helper. Unit tests cover naive and timezone-aware timestamps and verify matching ranking results.

Changes

Timezone normalization

Layer / File(s) Summary
Ranking datetime normalization
potpie/context-engine/src/potpie_context_engine/domain/ranking.py, potpie/context-engine/tests/unit/test_ranking.py
RankingService.rank normalizes context.now with _ensure_utc. The helper preserves aware datetimes, assigns UTC to naive datetimes, and leaves None unchanged. Recency scoring uses the helper for candidate timestamps. Tests verify equivalent scores and recency breakdowns for naive and UTC-aware inputs.

Possibly related PRs

  • potpie-ai/potpie#1012: Addresses naive and timezone-aware datetime handling in _parse_as_of_iso, while this change updates RankingService normalization.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: treating naive as_of and now datetimes as UTC during recency scoring.
Description check ✅ Passed The description accurately explains the crash, fixes, behavior changes, and test coverage for naive datetime handling.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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.

@AdityaPainuli
AdityaPainuli marked this pull request as ready for review July 18, 2026 10:16
Main removed the MCP adapter (cb889ad), so drop the server.py as_of fix
and its test; the ranking.py naive-UTC guard carried over to the new
src/potpie_context_engine path via rename detection.
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

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