@@ -645,6 +645,90 @@ async def test_sync_preserves_timestamps(
645645 assert abs (entity_updated_epoch - file_stats .st_mtime ) < tolerance # Allow tolerance difference
646646
647647
648+ @pytest .mark .asyncio
649+ async def test_sync_updates_timestamps_on_file_modification (
650+ sync_service : SyncService ,
651+ project_config : ProjectConfig ,
652+ entity_service : EntityService ,
653+ ):
654+ """Test that sync updates entity timestamps when files are modified.
655+
656+ This test specifically validates that when an existing file is modified and re-synced,
657+ the updated_at timestamp in the database reflects the file's actual modification time,
658+ not the database operation time. This is critical for accurate temporal ordering in
659+ search and recent_activity queries.
660+ """
661+ import time
662+
663+ project_dir = project_config .home
664+
665+ # Create initial file
666+ initial_content = """
667+ ---
668+ type: knowledge
669+ ---
670+ # Test File
671+ Initial content for timestamp test
672+ """
673+ file_path = project_dir / "timestamp_test.md"
674+ await create_test_file (file_path , initial_content )
675+
676+ # Initial sync
677+ await sync_service .sync (project_config .home )
678+
679+ # Get initial entity and timestamps
680+ entity_before = await entity_service .get_by_permalink ("timestamp-test" )
681+ initial_updated_at = entity_before .updated_at
682+
683+ # Wait a bit to ensure filesystem timestamp changes
684+ time .sleep (0.1 )
685+
686+ # Modify the file content
687+ modified_content = """
688+ ---
689+ type: knowledge
690+ ---
691+ # Test File
692+ Modified content for timestamp test
693+
694+ ## Observations
695+ - [test] This was modified
696+ """
697+ file_path .write_text (modified_content )
698+
699+ # Wait to ensure mtime is different
700+ time .sleep (0.1 )
701+
702+ # Get the file's modification time after our changes
703+ file_stats_after_modification = file_path .stat ()
704+
705+ # Re-sync the modified file
706+ await sync_service .sync (project_config .home )
707+
708+ # Get entity after re-sync
709+ entity_after = await entity_service .get_by_permalink ("timestamp-test" )
710+
711+ # Verify that updated_at changed
712+ assert entity_after .updated_at != initial_updated_at , (
713+ "updated_at should change when file is modified"
714+ )
715+
716+ # Verify that updated_at matches the file's modification time, not db operation time
717+ entity_updated_epoch = entity_after .updated_at .timestamp ()
718+ file_mtime = file_stats_after_modification .st_mtime
719+
720+ # Allow 2s difference on Windows due to filesystem timing precision
721+ tolerance = 2 if os .name == "nt" else 1
722+ assert abs (entity_updated_epoch - file_mtime ) < tolerance , (
723+ f"Entity updated_at ({ entity_after .updated_at } ) should match file mtime "
724+ f"({ datetime .fromtimestamp (file_mtime )} ) within { tolerance } s tolerance"
725+ )
726+
727+ # Verify the content was actually updated
728+ assert len (entity_after .observations ) == 1
729+ assert entity_after .observations [0 ].content == "This was modified"
730+
731+
648732@pytest .mark .asyncio
649733async def test_file_move_updates_search_index (
650734 sync_service : SyncService ,
0 commit comments