@@ -208,26 +208,46 @@ export async function capsule({
208208 // Stabilize for storage: sort object keys only (preserves array order in snapshots)
209209 const stabilizeForStorage = ( obj : any ) : any => JSON . parse ( stringify ( obj ) || 'null' )
210210
211+ // Detect hash-like strings (32+ hex chars)
212+ const isHashLike = ( s : string ) : boolean => / ^ [ 0 - 9 a - f ] { 32 , } $ / i. test ( s )
213+
211214 // Deep sort for comparison: sort both object keys AND array elements recursively
215+ // Also normalizes hash-like keys/values that differ between machines
212216 const deepSortForComparison = ( obj : any ) : any => {
213217 if ( obj === null || obj === undefined ) return obj
214218 if ( Array . isArray ( obj ) ) {
215- // Recursively sort array elements, then sort the array itself
216219 const sorted = obj . map ( deepSortForComparison )
217- // Sort arrays by their JSON representation for deterministic ordering
218220 return sorted . sort ( ( a , b ) => {
219221 const aStr = JSON . stringify ( a ) ?? ''
220222 const bStr = JSON . stringify ( b ) ?? ''
221223 return aStr . localeCompare ( bStr )
222224 } )
223225 }
224226 if ( typeof obj === 'object' ) {
227+ const keys = Object . keys ( obj )
228+ const hasHashKeys = keys . some ( isHashLike )
229+
230+ if ( hasHashKeys ) {
231+ // For objects with hash-like keys, convert to a sorted array of values
232+ // so that different hash keys with same values still match
233+ const entries = keys . map ( k => deepSortForComparison ( obj [ k ] ) )
234+ return entries . sort ( ( a , b ) => {
235+ const aStr = JSON . stringify ( a ) ?? ''
236+ const bStr = JSON . stringify ( b ) ?? ''
237+ return aStr . localeCompare ( bStr )
238+ } )
239+ }
240+
225241 const sorted : Record < string , any > = { }
226- for ( const key of Object . keys ( obj ) . sort ( ) ) {
242+ for ( const key of keys . sort ( ) ) {
227243 sorted [ key ] = deepSortForComparison ( obj [ key ] )
228244 }
229245 return sorted
230246 }
247+ // Normalize hash-like string values to a placeholder
248+ if ( typeof obj === 'string' && isHashLike ( obj ) ) {
249+ return '<HASH>'
250+ }
231251 return obj
232252 }
233253
0 commit comments