Skip to content

Commit c6b8786

Browse files
linggenclaude
andcommitted
fix(facts): truncate Fact::new timestamps to microseconds
Linux's Utc::now() returns nanosecond precision; our LanceDB schema stores Timestamp(Microsecond, UTC). On Linux CI the nanosecond tail was dropped at storage time, so equality checks after roundtrip failed (facts_roundtrip_through_record_batch, get_finds_inserted_fact). macOS's Utc::now() was already microsecond-truncated in practice, so local tests didn't catch this. Fix: Fact::new() now truncates `created_at` via chrono::SubsecRound::trunc_subsecs(6). In-memory timestamps now always match what the schema can store, so roundtrip is lossless. Any caller that sets `created_at` / `occurred_at` directly with nanosecond precision is still on the hook — but Fact::new covers the common path and the extract/collect pipelines use from_timestamp-style constructors that are microsecond-based. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 290ccf0 commit c6b8786

1 file changed

Lines changed: 7 additions & 3 deletions

File tree

src/facts/types.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
//! Schema matches `doc/tech-spec.md`. Any field change here must also update
1010
//! `schema.rs` and bump the store's format version.
1111
12-
use chrono::{DateTime, Utc};
12+
use chrono::{DateTime, SubsecRound, Utc};
1313
use serde::{Deserialize, Serialize};
1414
use std::fmt;
1515
use std::str::FromStr;
@@ -80,7 +80,11 @@ pub struct Fact {
8080

8181
impl Fact {
8282
/// Minimal constructor for a fresh fact. Generates a new id and stamps
83-
/// `created_at` to `now`. All optional fields default to `None` / empty.
83+
/// `created_at` to `now`, truncated to microsecond precision so the
84+
/// value round-trips through LanceDB (which stores `Timestamp(Microsecond)`).
85+
/// Without the truncation, Linux platforms where `Utc::now()` returns
86+
/// nanosecond precision would fail equality checks after store roundtrip.
87+
/// All optional fields default to `None` / empty.
8488
pub fn new(content: impl Into<String>, r#type: FactType, origin: Origin) -> Self {
8589
Self {
8690
id: Uuid::new_v4(),
@@ -92,7 +96,7 @@ impl Fact {
9296
outcome: None,
9397
origin,
9498
cwd: None,
95-
created_at: Utc::now(),
99+
created_at: Utc::now().trunc_subsecs(6),
96100
occurred_at: None,
97101
source_session: None,
98102
}

0 commit comments

Comments
 (0)