@@ -18,6 +18,10 @@ interface CacheEntry<T> {
1818
1919 timestamp : number ;
2020 version : number ; // Cache schema version
21+ // Optional file-state fingerprint (e.g., `${mtimeMs}-${size}`).
22+ // When present on both set() and get(), a mismatch invalidates the entry —
23+ // a safety net for FileWatcher events dropped by macOS FSEvents.
24+ fingerprint ?: string ;
2125}
2226
2327// Union type for cached values
@@ -64,9 +68,11 @@ export class DataCache {
6468 /**
6569 * Gets a cached session detail.
6670 * @param key - Cache key in format "projectId/sessionId"
67- * @returns The cached SessionDetail, or undefined if not found or expired
71+ * @param fingerprint - Optional file-state fingerprint. If the cached entry
72+ * has a fingerprint that differs from this one, it's treated as stale.
73+ * @returns The cached SessionDetail, or undefined if not found, expired, or stale
6874 */
69- get ( key : string ) : SessionDetail | undefined {
75+ get ( key : string , fingerprint ?: string ) : SessionDetail | undefined {
7076 if ( ! this . enabled ) {
7177 return undefined ;
7278 }
@@ -91,6 +97,12 @@ export class DataCache {
9197 return undefined ;
9298 }
9399
100+ // Check fingerprint mismatch (file changed since cached)
101+ if ( fingerprint !== undefined && entry . fingerprint !== fingerprint ) {
102+ this . cache . delete ( key ) ;
103+ return undefined ;
104+ }
105+
94106 // Move to end (mark as recently used)
95107 this . cache . delete ( key ) ;
96108 this . cache . set ( key , entry ) ;
@@ -141,7 +153,7 @@ export class DataCache {
141153 * Internal method to set a value in the cache.
142154 * Handles LRU eviction and cache entry creation.
143155 */
144- private setInternal ( key : string , value : CachedValue ) : void {
156+ private setInternal ( key : string , value : CachedValue , fingerprint ?: string ) : void {
145157 if ( ! this . enabled ) {
146158 return ;
147159 }
@@ -158,16 +170,19 @@ export class DataCache {
158170 value,
159171 timestamp : Date . now ( ) ,
160172 version : DataCache . CURRENT_VERSION ,
173+ fingerprint,
161174 } ) ;
162175 }
163176
164177 /**
165178 * Sets a value in the cache.
166179 * @param key - Cache key in format "projectId/sessionId"
167180 * @param value - The SessionDetail to cache
181+ * @param fingerprint - Optional file-state fingerprint paired with this entry.
182+ * When provided here AND on a future get(), a mismatch will invalidate.
168183 */
169- set ( key : string , value : SessionDetail ) : void {
170- this . setInternal ( key , value ) ;
184+ set ( key : string , value : SessionDetail , fingerprint ?: string ) : void {
185+ this . setInternal ( key , value , fingerprint ) ;
171186 }
172187
173188 /**
0 commit comments