fix(local-files): floor mtimeMs to integer for BIGINT compatibility#79
Merged
MAnders333 merged 1 commit intoMay 26, 2026
Merged
Conversation
fs.Stats.mtimeMs is documented as a float that preserves sub-millisecond
precision when the underlying filesystem supports it (APFS, ext4, btrfs,
etc.). The local-files reader propagated this float through:
statSync().mtimeMs (float)
→ episode.maxMessageTime / timeCreated
→ consolidate.ts chunkSessionTimestamp
→ reconsolidate.ts entryTime
→ KnowledgeEntry.{createdAt,updatedAt,lastAccessedAt}
→ INSERT INTO knowledge_entry (… BIGINT cols)
SQLite tolerates the float via type-affinity coercion, but Postgres
rejects it strictly:
PostgresError: invalid input syntax for type bigint: "1779275328228.197"
Every novel-entry insert from a local-files-sourced session fails on a
Postgres-backed deployment, while updates (which use Date.now()) succeed —
producing a confusing partial-success failure mode where extraction works
but no rows reach the store.
Fix: Math.floor(stat.mtimeMs) at both statSync call sites in the reader,
so all downstream uses inherit a guaranteed-integer value. No schema or
API change. Existing 27 local-files tests still pass.
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.
Summary
fs.Stats.mtimeMsis documented as a float that preserves sub-millisecond precision when the underlying filesystem supports it (APFS on macOS, ext4 / btrfs / xfs on Linux, etc.). The local-files reader propagates that float through the consolidation pipeline into the PostgresBIGINTcolumns ofknowledge_entry, which Postgres rejects strictly.Reproduction
A Postgres-backed deployment ingesting a
.mdfile via the local-files reader fails on every novel-entry insert with:Example from a real run (17 extracted entries from a single Markdown source, all 17 inserts failed):
Critically,
UPDATEs of existing entries succeed in the same run because they useDate.now()(integer) for the newupdated_at, notentryTime. This produces a confusing partial-success failure mode: extraction + the synthesis pass run normally, but no rows from local-files reach the store.SQLite users would never see this because SQLite coerces floats to integers via type affinity on
INTEGERcolumns. The bug only surfaces against Postgres.Cause
Tracing the float from source to sink:
Other readers (
opencode,claude-code,codex,cursor,vscode) source theirmaxMessageTimefrom already-integer values stored in upstream session DBs/JSONL, so they aren't affected.local-filesis the only reader that pulls directly from a Nodefs.Statsfloat.Fix
Math.floor(statSync(...).mtimeMs)at bothstatSynccall sites insrc/daemon/readers/local-files.ts. All downstream consumers inherit the integer.No schema or API change. No behavioural change beyond removing sub-ms precision (which can never be persisted into a
BIGINTms column anyway).Verification
bun test tests/episodes-local-files.test.ts— all 27 tests passbun test(full suite) — no new failures introduced (one unrelated config-loading test was already failing onmainbefore this branch)bunx biome check src/daemon/readers/local-files.ts— no new lint findings (the existing import-order warning on this file is pre-existing onmain)Notes for reviewers
I considered a defence-in-depth
Math.floorinconsolidate.tswherechunkSessionTimestampis computed, but kept the patch minimal to the actual source. Happy to add it if you'd prefer the consolidator to never trust reader-supplied timestamps.