Description
backend/parse.py's _build_ctx_turns sorts records using a key that falls back to datetime.min when a record has no timestamp:
datetime.min is naive, while the timestamps parsed from transcripts are timezone-aware. Python refuses to order a naive datetime against an aware one, so the comparison raises TypeError: can't compare offset-naive and offset-aware datetimes.
The failure needs a single file that contains both a record with a usable timestamp and a record without one. With every record timestamped, the fallback never evaluates. With none timestamped, every key is datetime.min and the comparison is naive-to-naive. Only the mixed case reaches the crash, which is why it has not been seen — no current fixture produces it.
The blast radius is ingest rather than a request: this runs while building context turns, so the affected file fails to ingest rather than degrading.
Expected Behavior
A record with a missing timestamp sorts deterministically against timestamped records without raising — either by using an aware minimum (datetime.min.replace(tzinfo=timezone.utc)), or by partitioning undated records explicitly rather than relying on a sentinel comparing correctly.
Reproduction Steps
- Construct a transcript file containing at least two records, where one has a parseable timestamp and one has none.
- Ingest that file.
- Observe
TypeError: can't compare offset-naive and offset-aware datetimes raised from the sort in _build_ctx_turns.
Environment / Context
Pre-existing; not introduced by the issue #8 lint burn-down, which left the expression unchanged. No test fixture currently contains a mixed-timestamp file, so the suite passes with the defect present.
Discovered During
The issue #8 lint and type-check backlog burn-down, reported under PITFALLS_NOTED while working through backend/parse.py. Deliberately not fixed there — the burn-down's remit was clearing findings without altering parser semantics, and changing how undated records sort is a behaviour change.
Suggested Fix
Unverified. Replacing the sentinel with datetime.min.replace(tzinfo=timezone.utc) is the smallest change and makes the comparison well-defined, placing undated records first.
Worth deciding explicitly whether "first" is the intended ordering, rather than inheriting it from whichever sentinel is convenient — if undated records should instead sort last, or be excluded from context turns entirely, the sentinel choice is the wrong lever. Either way this alters stored output for mixed files, so it likely warrants a PARSER_VERSION bump so affected transcripts are reparsed.
Description
backend/parse.py's_build_ctx_turnssorts records using a key that falls back todatetime.minwhen a record has no timestamp:datetime.minis naive, while the timestamps parsed from transcripts are timezone-aware. Python refuses to order a naive datetime against an aware one, so the comparison raisesTypeError: can't compare offset-naive and offset-aware datetimes.The failure needs a single file that contains both a record with a usable timestamp and a record without one. With every record timestamped, the fallback never evaluates. With none timestamped, every key is
datetime.minand the comparison is naive-to-naive. Only the mixed case reaches the crash, which is why it has not been seen — no current fixture produces it.The blast radius is ingest rather than a request: this runs while building context turns, so the affected file fails to ingest rather than degrading.
Expected Behavior
A record with a missing timestamp sorts deterministically against timestamped records without raising — either by using an aware minimum (
datetime.min.replace(tzinfo=timezone.utc)), or by partitioning undated records explicitly rather than relying on a sentinel comparing correctly.Reproduction Steps
TypeError: can't compare offset-naive and offset-aware datetimesraised from the sort in_build_ctx_turns.Environment / Context
Pre-existing; not introduced by the issue #8 lint burn-down, which left the expression unchanged. No test fixture currently contains a mixed-timestamp file, so the suite passes with the defect present.
Discovered During
The issue #8 lint and type-check backlog burn-down, reported under
PITFALLS_NOTEDwhile working throughbackend/parse.py. Deliberately not fixed there — the burn-down's remit was clearing findings without altering parser semantics, and changing how undated records sort is a behaviour change.Suggested Fix
Unverified. Replacing the sentinel with
datetime.min.replace(tzinfo=timezone.utc)is the smallest change and makes the comparison well-defined, placing undated records first.Worth deciding explicitly whether "first" is the intended ordering, rather than inheriting it from whichever sentinel is convenient — if undated records should instead sort last, or be excluded from context turns entirely, the sentinel choice is the wrong lever. Either way this alters stored output for mixed files, so it likely warrants a
PARSER_VERSIONbump so affected transcripts are reparsed.