Skip to content

Commit d47f76d

Browse files
hyperpolymathclaude
andcommitted
fix(orbital-sync): replace broken length+first+last hash with FNV-1a
simpleHash collided on any two strings differing only in middle chars (e.g. "abc" === "axc" → both "3-a-c"), causing OrbitalSync to silently miss real content changes across the 106 panels. FNV-1a via %raw JS, consistent with ProvenanceEngine.computeRegionHash pattern already established in this codebase. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 2d3ff7f commit d47f76d

1 file changed

Lines changed: 13 additions & 8 deletions

File tree

src/core/OrbitalSync.res

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,22 @@
1010
type syncEvent = Model.syncEvent
1111
type syncState = Model.syncState
1212

13-
/// Simple hash function for change detection
13+
/// FNV-1a change-detection hash — consistent with ProvenanceEngine pattern.
14+
/// Replaces the broken length+first+last approach that collided on any two
15+
/// strings differing only in middle characters (e.g. "abc" ≡ "axc").
1416
let simpleHash = (content: string): string => {
15-
// Simple hash based on content length and first/last chars
16-
// In production, use a proper hash function
17-
let len = String.length(content)
18-
if len === 0 {
17+
if String.length(content) === 0 {
1918
"empty"
2019
} else {
21-
let first = String.charAt(content, 0)
22-
let last = String.charAt(content, len - 1)
23-
`${Int.toString(len)}-${first}-${last}`
20+
%raw(`
21+
(function(s) {
22+
var h = 0x811c9dc5;
23+
for (var i = 0; i < s.length; i++) {
24+
h = ((h ^ s.charCodeAt(i)) * 0x01000193) >>> 0;
25+
}
26+
return h.toString(16);
27+
})(content)
28+
`)
2429
}
2530
}
2631

0 commit comments

Comments
 (0)