wip: benchmarks for testing different p2p sync strategies using a pds as a relay
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fixed merge bench

notplants 2c0a3ace 64d0dee6

+4671 -47
+17
bench-results/20260314-174700/quick-local/report.md
··· 1 + # Merge Strategy Benchmark Results 2 + 3 + Generated: 2026-03-14T17:47:00.288045108+00:00 4 + 5 + | Files | Collabs | Conflict | 1-git (ms) | 1-conflicts | 2-diff (ms) | 3-sidecar (ms) | 4-yrs (ms) | 2-ok | 3-ok | 4-ok | 6 + |-------|---------|----------|-----------|-------------|-------------|----------------|------------|------|------|------| 7 + | 10 | 2 | low | 26 | 0 | 39 | 78 | 1 | Y | Y | Y | 8 + | 10 | 2 | high | 36 | 2 | 102 | 106 | 2 | Y | Y | Y | 9 + 10 + ### Legend 11 + 12 + - **1-git**: Plain git 3-way merge 13 + - **2-diff**: git-yrs-merge in diff-only mode 14 + - **3-sidecar**: git-yrs-merge with .yrs/ sidecars 15 + - **4-yrs**: Yrs CRDT merge (simulated, no network) 16 + - **ok**: merge completed successfully (Y/N) 17 + - **conflicts**: number of files with conflict markers (strategy 1 only)
+9
bench-results/20260314-174700/quick-local/results.csv
··· 1 + files,conflict_rate,collaborators,edits,strategy,time_ms,conflicts,success 2 + 10,low,2,3,1-plain-git,26,0,true 3 + 10,low,2,3,2-yrs-diff,39,0,true 4 + 10,low,2,3,3-yrs-sidecar,78,0,true 5 + 10,low,2,3,4-yrs-on-pds,1,0,true 6 + 10,high,2,3,1-plain-git,36,2,false 7 + 10,high,2,3,2-yrs-diff,102,0,true 8 + 10,high,2,3,3-yrs-sidecar,106,0,true 9 + 10,high,2,3,4-yrs-on-pds,2,0,true
+84
bench-results/20260314-174700/quick-local/results.json
··· 1 + [ 2 + { 3 + "file_count": 10, 4 + "avg_file_size": 500, 5 + "collaborators": 2, 6 + "edits_per_branch": 3, 7 + "conflict_rate": "low", 8 + "results": [ 9 + { 10 + "strategy": "1-plain-git", 11 + "merge_time_ms": 26, 12 + "conflicts_reported": 0, 13 + "files_processed": 10, 14 + "success": true, 15 + "error": null 16 + }, 17 + { 18 + "strategy": "2-yrs-diff", 19 + "merge_time_ms": 39, 20 + "conflicts_reported": 0, 21 + "files_processed": 36, 22 + "success": true, 23 + "error": null 24 + }, 25 + { 26 + "strategy": "3-yrs-sidecar", 27 + "merge_time_ms": 78, 28 + "conflicts_reported": 0, 29 + "files_processed": 36, 30 + "success": true, 31 + "error": null 32 + }, 33 + { 34 + "strategy": "4-yrs-on-pds", 35 + "merge_time_ms": 1, 36 + "conflicts_reported": 0, 37 + "files_processed": 0, 38 + "success": true, 39 + "error": null 40 + } 41 + ] 42 + }, 43 + { 44 + "file_count": 10, 45 + "avg_file_size": 500, 46 + "collaborators": 2, 47 + "edits_per_branch": 3, 48 + "conflict_rate": "high", 49 + "results": [ 50 + { 51 + "strategy": "1-plain-git", 52 + "merge_time_ms": 36, 53 + "conflicts_reported": 2, 54 + "files_processed": 14, 55 + "success": false, 56 + "error": "" 57 + }, 58 + { 59 + "strategy": "2-yrs-diff", 60 + "merge_time_ms": 102, 61 + "conflicts_reported": 0, 62 + "files_processed": 36, 63 + "success": true, 64 + "error": null 65 + }, 66 + { 67 + "strategy": "3-yrs-sidecar", 68 + "merge_time_ms": 106, 69 + "conflicts_reported": 0, 70 + "files_processed": 36, 71 + "success": true, 72 + "error": null 73 + }, 74 + { 75 + "strategy": "4-yrs-on-pds", 76 + "merge_time_ms": 2, 77 + "conflicts_reported": 0, 78 + "files_processed": 0, 79 + "success": true, 80 + "error": null 81 + } 82 + ] 83 + } 84 + ]
+24
bench-results/20260314-174722/default-local/report.md
··· 1 + # Merge Strategy Benchmark Results 2 + 3 + Generated: 2026-03-14T17:47:22.185684781+00:00 4 + 5 + | Files | Collabs | Conflict | 1-git (ms) | 1-conflicts | 2-diff (ms) | 3-sidecar (ms) | 4-yrs (ms) | 2-ok | 3-ok | 4-ok | 6 + |-------|---------|----------|-----------|-------------|-------------|----------------|------------|------|------|------| 7 + | 10 | 2 | low | 25 | 0 | 42 | 74 | 1 | Y | Y | Y | 8 + | 10 | 2 | medium | 29 | 1 | 67 | 110 | 1 | Y | Y | Y | 9 + | 10 | 2 | high | 36 | 3 | 120 | 151 | 1 | Y | Y | Y | 10 + | 50 | 2 | low | 39 | 0 | 66 | 81 | 6 | Y | Y | Y | 11 + | 50 | 2 | medium | 43 | 2 | 109 | 164 | 5 | Y | Y | Y | 12 + | 50 | 2 | high | 51 | 7 | 213 | 258 | 7 | Y | Y | Y | 13 + | 200 | 2 | low | 71 | 1 | 108 | 157 | 26 | Y | Y | Y | 14 + | 200 | 2 | medium | 52 | 5 | 256 | 321 | 32 | Y | Y | Y | 15 + | 200 | 2 | high | 59 | 15 | 497 | 517 | 25 | Y | Y | Y | 16 + 17 + ### Legend 18 + 19 + - **1-git**: Plain git 3-way merge 20 + - **2-diff**: git-yrs-merge in diff-only mode 21 + - **3-sidecar**: git-yrs-merge with .yrs/ sidecars 22 + - **4-yrs**: Yrs CRDT merge (simulated, no network) 23 + - **ok**: merge completed successfully (Y/N) 24 + - **conflicts**: number of files with conflict markers (strategy 1 only)
+37
bench-results/20260314-174722/default-local/results.csv
··· 1 + files,conflict_rate,collaborators,edits,strategy,time_ms,conflicts,success 2 + 10,low,2,5,1-plain-git,25,0,true 3 + 10,low,2,5,2-yrs-diff,42,0,true 4 + 10,low,2,5,3-yrs-sidecar,74,0,true 5 + 10,low,2,5,4-yrs-on-pds,1,0,true 6 + 10,medium,2,5,1-plain-git,29,1,false 7 + 10,medium,2,5,2-yrs-diff,67,0,true 8 + 10,medium,2,5,3-yrs-sidecar,110,0,true 9 + 10,medium,2,5,4-yrs-on-pds,1,0,true 10 + 10,high,2,5,1-plain-git,36,3,false 11 + 10,high,2,5,2-yrs-diff,120,0,true 12 + 10,high,2,5,3-yrs-sidecar,151,0,true 13 + 10,high,2,5,4-yrs-on-pds,1,0,true 14 + 50,low,2,10,1-plain-git,39,0,true 15 + 50,low,2,10,2-yrs-diff,66,0,true 16 + 50,low,2,10,3-yrs-sidecar,81,0,true 17 + 50,low,2,10,4-yrs-on-pds,6,0,true 18 + 50,medium,2,10,1-plain-git,43,2,false 19 + 50,medium,2,10,2-yrs-diff,109,0,true 20 + 50,medium,2,10,3-yrs-sidecar,164,0,true 21 + 50,medium,2,10,4-yrs-on-pds,5,0,true 22 + 50,high,2,10,1-plain-git,51,7,false 23 + 50,high,2,10,2-yrs-diff,213,0,true 24 + 50,high,2,10,3-yrs-sidecar,258,0,true 25 + 50,high,2,10,4-yrs-on-pds,7,0,true 26 + 200,low,2,20,1-plain-git,71,1,false 27 + 200,low,2,20,2-yrs-diff,108,0,true 28 + 200,low,2,20,3-yrs-sidecar,157,0,true 29 + 200,low,2,20,4-yrs-on-pds,26,0,true 30 + 200,medium,2,20,1-plain-git,52,5,false 31 + 200,medium,2,20,2-yrs-diff,256,0,true 32 + 200,medium,2,20,3-yrs-sidecar,321,0,true 33 + 200,medium,2,20,4-yrs-on-pds,32,0,true 34 + 200,high,2,20,1-plain-git,59,15,false 35 + 200,high,2,20,2-yrs-diff,497,0,true 36 + 200,high,2,20,3-yrs-sidecar,517,0,true 37 + 200,high,2,20,4-yrs-on-pds,25,0,true
+371
bench-results/20260314-174722/default-local/results.json
··· 1 + [ 2 + { 3 + "file_count": 10, 4 + "avg_file_size": 1000, 5 + "collaborators": 2, 6 + "edits_per_branch": 5, 7 + "conflict_rate": "low", 8 + "results": [ 9 + { 10 + "strategy": "1-plain-git", 11 + "merge_time_ms": 25, 12 + "conflicts_reported": 0, 13 + "files_processed": 10, 14 + "success": true, 15 + "error": null 16 + }, 17 + { 18 + "strategy": "2-yrs-diff", 19 + "merge_time_ms": 42, 20 + "conflicts_reported": 0, 21 + "files_processed": 38, 22 + "success": true, 23 + "error": null 24 + }, 25 + { 26 + "strategy": "3-yrs-sidecar", 27 + "merge_time_ms": 74, 28 + "conflicts_reported": 0, 29 + "files_processed": 39, 30 + "success": true, 31 + "error": null 32 + }, 33 + { 34 + "strategy": "4-yrs-on-pds", 35 + "merge_time_ms": 1, 36 + "conflicts_reported": 0, 37 + "files_processed": 0, 38 + "success": true, 39 + "error": null 40 + } 41 + ] 42 + }, 43 + { 44 + "file_count": 10, 45 + "avg_file_size": 1000, 46 + "collaborators": 2, 47 + "edits_per_branch": 5, 48 + "conflict_rate": "medium", 49 + "results": [ 50 + { 51 + "strategy": "1-plain-git", 52 + "merge_time_ms": 29, 53 + "conflicts_reported": 1, 54 + "files_processed": 12, 55 + "success": false, 56 + "error": "" 57 + }, 58 + { 59 + "strategy": "2-yrs-diff", 60 + "merge_time_ms": 67, 61 + "conflicts_reported": 0, 62 + "files_processed": 38, 63 + "success": true, 64 + "error": null 65 + }, 66 + { 67 + "strategy": "3-yrs-sidecar", 68 + "merge_time_ms": 110, 69 + "conflicts_reported": 0, 70 + "files_processed": 40, 71 + "success": true, 72 + "error": null 73 + }, 74 + { 75 + "strategy": "4-yrs-on-pds", 76 + "merge_time_ms": 1, 77 + "conflicts_reported": 0, 78 + "files_processed": 0, 79 + "success": true, 80 + "error": null 81 + } 82 + ] 83 + }, 84 + { 85 + "file_count": 10, 86 + "avg_file_size": 1000, 87 + "collaborators": 2, 88 + "edits_per_branch": 5, 89 + "conflict_rate": "high", 90 + "results": [ 91 + { 92 + "strategy": "1-plain-git", 93 + "merge_time_ms": 36, 94 + "conflicts_reported": 3, 95 + "files_processed": 16, 96 + "success": false, 97 + "error": "" 98 + }, 99 + { 100 + "strategy": "2-yrs-diff", 101 + "merge_time_ms": 120, 102 + "conflicts_reported": 0, 103 + "files_processed": 40, 104 + "success": true, 105 + "error": null 106 + }, 107 + { 108 + "strategy": "3-yrs-sidecar", 109 + "merge_time_ms": 151, 110 + "conflicts_reported": 0, 111 + "files_processed": 38, 112 + "success": true, 113 + "error": null 114 + }, 115 + { 116 + "strategy": "4-yrs-on-pds", 117 + "merge_time_ms": 1, 118 + "conflicts_reported": 0, 119 + "files_processed": 0, 120 + "success": true, 121 + "error": null 122 + } 123 + ] 124 + }, 125 + { 126 + "file_count": 50, 127 + "avg_file_size": 1000, 128 + "collaborators": 2, 129 + "edits_per_branch": 10, 130 + "conflict_rate": "low", 131 + "results": [ 132 + { 133 + "strategy": "1-plain-git", 134 + "merge_time_ms": 39, 135 + "conflicts_reported": 0, 136 + "files_processed": 50, 137 + "success": true, 138 + "error": null 139 + }, 140 + { 141 + "strategy": "2-yrs-diff", 142 + "merge_time_ms": 66, 143 + "conflicts_reported": 0, 144 + "files_processed": 168, 145 + "success": true, 146 + "error": null 147 + }, 148 + { 149 + "strategy": "3-yrs-sidecar", 150 + "merge_time_ms": 81, 151 + "conflicts_reported": 0, 152 + "files_processed": 169, 153 + "success": true, 154 + "error": null 155 + }, 156 + { 157 + "strategy": "4-yrs-on-pds", 158 + "merge_time_ms": 6, 159 + "conflicts_reported": 0, 160 + "files_processed": 0, 161 + "success": true, 162 + "error": null 163 + } 164 + ] 165 + }, 166 + { 167 + "file_count": 50, 168 + "avg_file_size": 1000, 169 + "collaborators": 2, 170 + "edits_per_branch": 10, 171 + "conflict_rate": "medium", 172 + "results": [ 173 + { 174 + "strategy": "1-plain-git", 175 + "merge_time_ms": 43, 176 + "conflicts_reported": 2, 177 + "files_processed": 54, 178 + "success": false, 179 + "error": "" 180 + }, 181 + { 182 + "strategy": "2-yrs-diff", 183 + "merge_time_ms": 109, 184 + "conflicts_reported": 0, 185 + "files_processed": 170, 186 + "success": true, 187 + "error": null 188 + }, 189 + { 190 + "strategy": "3-yrs-sidecar", 191 + "merge_time_ms": 164, 192 + "conflicts_reported": 0, 193 + "files_processed": 168, 194 + "success": true, 195 + "error": null 196 + }, 197 + { 198 + "strategy": "4-yrs-on-pds", 199 + "merge_time_ms": 5, 200 + "conflicts_reported": 0, 201 + "files_processed": 0, 202 + "success": true, 203 + "error": null 204 + } 205 + ] 206 + }, 207 + { 208 + "file_count": 50, 209 + "avg_file_size": 1000, 210 + "collaborators": 2, 211 + "edits_per_branch": 10, 212 + "conflict_rate": "high", 213 + "results": [ 214 + { 215 + "strategy": "1-plain-git", 216 + "merge_time_ms": 51, 217 + "conflicts_reported": 7, 218 + "files_processed": 64, 219 + "success": false, 220 + "error": "" 221 + }, 222 + { 223 + "strategy": "2-yrs-diff", 224 + "merge_time_ms": 213, 225 + "conflicts_reported": 0, 226 + "files_processed": 171, 227 + "success": true, 228 + "error": null 229 + }, 230 + { 231 + "strategy": "3-yrs-sidecar", 232 + "merge_time_ms": 258, 233 + "conflicts_reported": 0, 234 + "files_processed": 170, 235 + "success": true, 236 + "error": null 237 + }, 238 + { 239 + "strategy": "4-yrs-on-pds", 240 + "merge_time_ms": 7, 241 + "conflicts_reported": 0, 242 + "files_processed": 0, 243 + "success": true, 244 + "error": null 245 + } 246 + ] 247 + }, 248 + { 249 + "file_count": 200, 250 + "avg_file_size": 1000, 251 + "collaborators": 2, 252 + "edits_per_branch": 20, 253 + "conflict_rate": "low", 254 + "results": [ 255 + { 256 + "strategy": "1-plain-git", 257 + "merge_time_ms": 71, 258 + "conflicts_reported": 1, 259 + "files_processed": 202, 260 + "success": false, 261 + "error": "" 262 + }, 263 + { 264 + "strategy": "2-yrs-diff", 265 + "merge_time_ms": 108, 266 + "conflicts_reported": 0, 267 + "files_processed": 638, 268 + "success": true, 269 + "error": null 270 + }, 271 + { 272 + "strategy": "3-yrs-sidecar", 273 + "merge_time_ms": 157, 274 + "conflicts_reported": 0, 275 + "files_processed": 636, 276 + "success": true, 277 + "error": null 278 + }, 279 + { 280 + "strategy": "4-yrs-on-pds", 281 + "merge_time_ms": 26, 282 + "conflicts_reported": 0, 283 + "files_processed": 0, 284 + "success": true, 285 + "error": null 286 + } 287 + ] 288 + }, 289 + { 290 + "file_count": 200, 291 + "avg_file_size": 1000, 292 + "collaborators": 2, 293 + "edits_per_branch": 20, 294 + "conflict_rate": "medium", 295 + "results": [ 296 + { 297 + "strategy": "1-plain-git", 298 + "merge_time_ms": 52, 299 + "conflicts_reported": 5, 300 + "files_processed": 210, 301 + "success": false, 302 + "error": "" 303 + }, 304 + { 305 + "strategy": "2-yrs-diff", 306 + "merge_time_ms": 256, 307 + "conflicts_reported": 0, 308 + "files_processed": 638, 309 + "success": true, 310 + "error": null 311 + }, 312 + { 313 + "strategy": "3-yrs-sidecar", 314 + "merge_time_ms": 321, 315 + "conflicts_reported": 0, 316 + "files_processed": 636, 317 + "success": true, 318 + "error": null 319 + }, 320 + { 321 + "strategy": "4-yrs-on-pds", 322 + "merge_time_ms": 32, 323 + "conflicts_reported": 0, 324 + "files_processed": 0, 325 + "success": true, 326 + "error": null 327 + } 328 + ] 329 + }, 330 + { 331 + "file_count": 200, 332 + "avg_file_size": 1000, 333 + "collaborators": 2, 334 + "edits_per_branch": 20, 335 + "conflict_rate": "high", 336 + "results": [ 337 + { 338 + "strategy": "1-plain-git", 339 + "merge_time_ms": 59, 340 + "conflicts_reported": 15, 341 + "files_processed": 230, 342 + "success": false, 343 + "error": "" 344 + }, 345 + { 346 + "strategy": "2-yrs-diff", 347 + "merge_time_ms": 497, 348 + "conflicts_reported": 0, 349 + "files_processed": 640, 350 + "success": true, 351 + "error": null 352 + }, 353 + { 354 + "strategy": "3-yrs-sidecar", 355 + "merge_time_ms": 517, 356 + "conflicts_reported": 0, 357 + "files_processed": 640, 358 + "success": true, 359 + "error": null 360 + }, 361 + { 362 + "strategy": "4-yrs-on-pds", 363 + "merge_time_ms": 25, 364 + "conflicts_reported": 0, 365 + "files_processed": 0, 366 + "success": true, 367 + "error": null 368 + } 369 + ] 370 + } 371 + ]
+18
bench-results/v4-ymap-clean/conflict-pds/report.md
··· 1 + # Merge Strategy Benchmark Results 2 + 3 + Generated: 2026-03-14T05:10:34.344164209+00:00 4 + 5 + | Files | Collabs | Conflict | 1-git (ms) | 1-conflicts | 2-diff (ms) | 3-sidecar (ms) | 4-yrs (ms) | 2-ok | 3-ok | 4-ok | 6 + |-------|---------|----------|-----------|-------------|-------------|----------------|------------|------|------|------| 7 + | 10 | 2 | guaranteed | 8235 | 10 | 9087 | 8487 | 1586 | Y | Y | Y | 8 + | 50 | 2 | guaranteed | 8364 | 20 | 9285 | 10161 | 1796 | Y | Y | Y | 9 + | 200 | 2 | guaranteed | 8965 | 20 | 12713 | 10805 | 4854 | Y | Y | Y | 10 + 11 + ### Legend 12 + 13 + - **1-git**: Plain git 3-way merge 14 + - **2-diff**: git-yrs-merge in diff-only mode 15 + - **3-sidecar**: git-yrs-merge with .yrs/ sidecars 16 + - **4-yrs**: Yrs CRDT merge (simulated, no network) 17 + - **ok**: merge completed successfully (Y/N) 18 + - **conflicts**: number of files with conflict markers (strategy 1 only)
+13
bench-results/v4-ymap-clean/conflict-pds/results.csv
··· 1 + files,conflict_rate,collaborators,edits,strategy,time_ms,conflicts,success 2 + 10,guaranteed,2,10,1-plain-git,8235,10,false 3 + 10,guaranteed,2,10,2-yrs-diff,9087,0,true 4 + 10,guaranteed,2,10,3-yrs-sidecar,8487,0,true 5 + 10,guaranteed,2,10,4-yrs-on-pds,1586,0,true 6 + 50,guaranteed,2,20,1-plain-git,8364,20,false 7 + 50,guaranteed,2,20,2-yrs-diff,9285,0,true 8 + 50,guaranteed,2,20,3-yrs-sidecar,10161,0,true 9 + 50,guaranteed,2,20,4-yrs-on-pds,1796,0,true 10 + 200,guaranteed,2,20,1-plain-git,8965,20,false 11 + 200,guaranteed,2,20,2-yrs-diff,12713,0,true 12 + 200,guaranteed,2,20,3-yrs-sidecar,10805,0,true 13 + 200,guaranteed,2,20,4-yrs-on-pds,4854,0,true
+125
bench-results/v4-ymap-clean/conflict-pds/results.json
··· 1 + [ 2 + { 3 + "file_count": 10, 4 + "avg_file_size": 1000, 5 + "collaborators": 2, 6 + "edits_per_branch": 10, 7 + "conflict_rate": "guaranteed", 8 + "results": [ 9 + { 10 + "strategy": "1-plain-git", 11 + "merge_time_ms": 8235, 12 + "conflicts_reported": 10, 13 + "files_processed": 30, 14 + "success": false, 15 + "error": "" 16 + }, 17 + { 18 + "strategy": "2-yrs-diff", 19 + "merge_time_ms": 9087, 20 + "conflicts_reported": 0, 21 + "files_processed": 51, 22 + "success": true, 23 + "error": null 24 + }, 25 + { 26 + "strategy": "3-yrs-sidecar", 27 + "merge_time_ms": 8487, 28 + "conflicts_reported": 0, 29 + "files_processed": 51, 30 + "success": true, 31 + "error": null 32 + }, 33 + { 34 + "strategy": "4-yrs-on-pds", 35 + "merge_time_ms": 1586, 36 + "conflicts_reported": 0, 37 + "files_processed": 10, 38 + "success": true, 39 + "error": null 40 + } 41 + ] 42 + }, 43 + { 44 + "file_count": 50, 45 + "avg_file_size": 1000, 46 + "collaborators": 2, 47 + "edits_per_branch": 20, 48 + "conflict_rate": "guaranteed", 49 + "results": [ 50 + { 51 + "strategy": "1-plain-git", 52 + "merge_time_ms": 8364, 53 + "conflicts_reported": 20, 54 + "files_processed": 90, 55 + "success": false, 56 + "error": "" 57 + }, 58 + { 59 + "strategy": "2-yrs-diff", 60 + "merge_time_ms": 9285, 61 + "conflicts_reported": 0, 62 + "files_processed": 191, 63 + "success": true, 64 + "error": null 65 + }, 66 + { 67 + "strategy": "3-yrs-sidecar", 68 + "merge_time_ms": 10161, 69 + "conflicts_reported": 0, 70 + "files_processed": 191, 71 + "success": true, 72 + "error": null 73 + }, 74 + { 75 + "strategy": "4-yrs-on-pds", 76 + "merge_time_ms": 1796, 77 + "conflicts_reported": 0, 78 + "files_processed": 50, 79 + "success": true, 80 + "error": null 81 + } 82 + ] 83 + }, 84 + { 85 + "file_count": 200, 86 + "avg_file_size": 1000, 87 + "collaborators": 2, 88 + "edits_per_branch": 20, 89 + "conflict_rate": "guaranteed", 90 + "results": [ 91 + { 92 + "strategy": "1-plain-git", 93 + "merge_time_ms": 8965, 94 + "conflicts_reported": 20, 95 + "files_processed": 240, 96 + "success": false, 97 + "error": "" 98 + }, 99 + { 100 + "strategy": "2-yrs-diff", 101 + "merge_time_ms": 12713, 102 + "conflicts_reported": 0, 103 + "files_processed": 641, 104 + "success": true, 105 + "error": null 106 + }, 107 + { 108 + "strategy": "3-yrs-sidecar", 109 + "merge_time_ms": 10805, 110 + "conflicts_reported": 0, 111 + "files_processed": 641, 112 + "success": true, 113 + "error": null 114 + }, 115 + { 116 + "strategy": "4-yrs-on-pds", 117 + "merge_time_ms": 4854, 118 + "conflicts_reported": 0, 119 + "files_processed": 200, 120 + "success": true, 121 + "error": null 122 + } 123 + ] 124 + } 125 + ]
+24
bench-results/v4-ymap-clean/default-pds/report.md
··· 1 + # Merge Strategy Benchmark Results 2 + 3 + Generated: 2026-03-14T05:00:58.748253660+00:00 4 + 5 + | Files | Collabs | Conflict | 1-git (ms) | 1-conflicts | 2-diff (ms) | 3-sidecar (ms) | 4-yrs (ms) | 2-ok | 3-ok | 4-ok | 6 + |-------|---------|----------|-----------|-------------|-------------|----------------|------------|------|------|------| 7 + | 10 | 2 | low | 7296 | 0 | 8563 | 8689 | 1766 | Y | Y | Y | 8 + | 10 | 2 | medium | 7388 | 0 | 7491 | 8840 | 1761 | Y | Y | Y | 9 + | 10 | 2 | high | 7647 | 1 | 7772 | 8475 | 1825 | Y | Y | Y | 10 + | 50 | 2 | low | 8168 | 0 | 9168 | 8739 | 2175 | Y | Y | Y | 11 + | 50 | 2 | medium | 7838 | 0 | 9118 | 8849 | 2073 | Y | Y | Y | 12 + | 50 | 2 | high | 8198 | 0 | 9827 | 8189 | 1964 | Y | Y | Y | 13 + | 200 | 2 | low | 8354 | 0 | 10168 | 10844 | 6277 | Y | Y | Y | 14 + | 200 | 2 | medium | 8197 | 0 | 11216 | 8838 | 5703 | Y | Y | Y | 15 + | 200 | 2 | high | 8442 | 1 | 10340 | 9615 | 6323 | Y | Y | Y | 16 + 17 + ### Legend 18 + 19 + - **1-git**: Plain git 3-way merge 20 + - **2-diff**: git-yrs-merge in diff-only mode 21 + - **3-sidecar**: git-yrs-merge with .yrs/ sidecars 22 + - **4-yrs**: Yrs CRDT merge (simulated, no network) 23 + - **ok**: merge completed successfully (Y/N) 24 + - **conflicts**: number of files with conflict markers (strategy 1 only)
+37
bench-results/v4-ymap-clean/default-pds/results.csv
··· 1 + files,conflict_rate,collaborators,edits,strategy,time_ms,conflicts,success 2 + 10,low,2,5,1-plain-git,7296,0,true 3 + 10,low,2,5,2-yrs-diff,8563,0,true 4 + 10,low,2,5,3-yrs-sidecar,8689,0,true 5 + 10,low,2,5,4-yrs-on-pds,1766,0,true 6 + 10,medium,2,5,1-plain-git,7388,0,true 7 + 10,medium,2,5,2-yrs-diff,7491,0,true 8 + 10,medium,2,5,3-yrs-sidecar,8840,0,true 9 + 10,medium,2,5,4-yrs-on-pds,1761,0,true 10 + 10,high,2,5,1-plain-git,7647,1,false 11 + 10,high,2,5,2-yrs-diff,7772,0,true 12 + 10,high,2,5,3-yrs-sidecar,8475,0,true 13 + 10,high,2,5,4-yrs-on-pds,1825,0,true 14 + 50,low,2,10,1-plain-git,8168,0,true 15 + 50,low,2,10,2-yrs-diff,9168,0,true 16 + 50,low,2,10,3-yrs-sidecar,8739,0,true 17 + 50,low,2,10,4-yrs-on-pds,2175,0,true 18 + 50,medium,2,10,1-plain-git,7838,0,true 19 + 50,medium,2,10,2-yrs-diff,9118,0,true 20 + 50,medium,2,10,3-yrs-sidecar,8849,0,true 21 + 50,medium,2,10,4-yrs-on-pds,2073,0,true 22 + 50,high,2,10,1-plain-git,8198,0,true 23 + 50,high,2,10,2-yrs-diff,9827,0,true 24 + 50,high,2,10,3-yrs-sidecar,8189,0,true 25 + 50,high,2,10,4-yrs-on-pds,1964,0,true 26 + 200,low,2,20,1-plain-git,8354,0,true 27 + 200,low,2,20,2-yrs-diff,10168,0,true 28 + 200,low,2,20,3-yrs-sidecar,10844,0,true 29 + 200,low,2,20,4-yrs-on-pds,6277,0,true 30 + 200,medium,2,20,1-plain-git,8197,0,true 31 + 200,medium,2,20,2-yrs-diff,11216,0,true 32 + 200,medium,2,20,3-yrs-sidecar,8838,0,true 33 + 200,medium,2,20,4-yrs-on-pds,5703,0,true 34 + 200,high,2,20,1-plain-git,8442,1,false 35 + 200,high,2,20,2-yrs-diff,10340,0,true 36 + 200,high,2,20,3-yrs-sidecar,9615,0,true 37 + 200,high,2,20,4-yrs-on-pds,6323,0,true
+371
bench-results/v4-ymap-clean/default-pds/results.json
··· 1 + [ 2 + { 3 + "file_count": 10, 4 + "avg_file_size": 1000, 5 + "collaborators": 2, 6 + "edits_per_branch": 5, 7 + "conflict_rate": "low", 8 + "results": [ 9 + { 10 + "strategy": "1-plain-git", 11 + "merge_time_ms": 7296, 12 + "conflicts_reported": 0, 13 + "files_processed": 10, 14 + "success": true, 15 + "error": null 16 + }, 17 + { 18 + "strategy": "2-yrs-diff", 19 + "merge_time_ms": 8563, 20 + "conflicts_reported": 0, 21 + "files_processed": 38, 22 + "success": true, 23 + "error": null 24 + }, 25 + { 26 + "strategy": "3-yrs-sidecar", 27 + "merge_time_ms": 8689, 28 + "conflicts_reported": 0, 29 + "files_processed": 36, 30 + "success": true, 31 + "error": null 32 + }, 33 + { 34 + "strategy": "4-yrs-on-pds", 35 + "merge_time_ms": 1766, 36 + "conflicts_reported": 0, 37 + "files_processed": 10, 38 + "success": true, 39 + "error": null 40 + } 41 + ] 42 + }, 43 + { 44 + "file_count": 10, 45 + "avg_file_size": 1000, 46 + "collaborators": 2, 47 + "edits_per_branch": 5, 48 + "conflict_rate": "medium", 49 + "results": [ 50 + { 51 + "strategy": "1-plain-git", 52 + "merge_time_ms": 7388, 53 + "conflicts_reported": 0, 54 + "files_processed": 10, 55 + "success": true, 56 + "error": null 57 + }, 58 + { 59 + "strategy": "2-yrs-diff", 60 + "merge_time_ms": 7491, 61 + "conflicts_reported": 0, 62 + "files_processed": 37, 63 + "success": true, 64 + "error": null 65 + }, 66 + { 67 + "strategy": "3-yrs-sidecar", 68 + "merge_time_ms": 8840, 69 + "conflicts_reported": 0, 70 + "files_processed": 37, 71 + "success": true, 72 + "error": null 73 + }, 74 + { 75 + "strategy": "4-yrs-on-pds", 76 + "merge_time_ms": 1761, 77 + "conflicts_reported": 0, 78 + "files_processed": 10, 79 + "success": true, 80 + "error": null 81 + } 82 + ] 83 + }, 84 + { 85 + "file_count": 10, 86 + "avg_file_size": 1000, 87 + "collaborators": 2, 88 + "edits_per_branch": 5, 89 + "conflict_rate": "high", 90 + "results": [ 91 + { 92 + "strategy": "1-plain-git", 93 + "merge_time_ms": 7647, 94 + "conflicts_reported": 1, 95 + "files_processed": 12, 96 + "success": false, 97 + "error": "" 98 + }, 99 + { 100 + "strategy": "2-yrs-diff", 101 + "merge_time_ms": 7772, 102 + "conflicts_reported": 0, 103 + "files_processed": 36, 104 + "success": true, 105 + "error": null 106 + }, 107 + { 108 + "strategy": "3-yrs-sidecar", 109 + "merge_time_ms": 8475, 110 + "conflicts_reported": 0, 111 + "files_processed": 38, 112 + "success": true, 113 + "error": null 114 + }, 115 + { 116 + "strategy": "4-yrs-on-pds", 117 + "merge_time_ms": 1825, 118 + "conflicts_reported": 0, 119 + "files_processed": 10, 120 + "success": true, 121 + "error": null 122 + } 123 + ] 124 + }, 125 + { 126 + "file_count": 50, 127 + "avg_file_size": 1000, 128 + "collaborators": 2, 129 + "edits_per_branch": 10, 130 + "conflict_rate": "low", 131 + "results": [ 132 + { 133 + "strategy": "1-plain-git", 134 + "merge_time_ms": 8168, 135 + "conflicts_reported": 0, 136 + "files_processed": 50, 137 + "success": true, 138 + "error": null 139 + }, 140 + { 141 + "strategy": "2-yrs-diff", 142 + "merge_time_ms": 9168, 143 + "conflicts_reported": 0, 144 + "files_processed": 166, 145 + "success": true, 146 + "error": null 147 + }, 148 + { 149 + "strategy": "3-yrs-sidecar", 150 + "merge_time_ms": 8739, 151 + "conflicts_reported": 0, 152 + "files_processed": 167, 153 + "success": true, 154 + "error": null 155 + }, 156 + { 157 + "strategy": "4-yrs-on-pds", 158 + "merge_time_ms": 2175, 159 + "conflicts_reported": 0, 160 + "files_processed": 50, 161 + "success": true, 162 + "error": null 163 + } 164 + ] 165 + }, 166 + { 167 + "file_count": 50, 168 + "avg_file_size": 1000, 169 + "collaborators": 2, 170 + "edits_per_branch": 10, 171 + "conflict_rate": "medium", 172 + "results": [ 173 + { 174 + "strategy": "1-plain-git", 175 + "merge_time_ms": 7838, 176 + "conflicts_reported": 0, 177 + "files_processed": 50, 178 + "success": true, 179 + "error": null 180 + }, 181 + { 182 + "strategy": "2-yrs-diff", 183 + "merge_time_ms": 9118, 184 + "conflicts_reported": 0, 185 + "files_processed": 168, 186 + "success": true, 187 + "error": null 188 + }, 189 + { 190 + "strategy": "3-yrs-sidecar", 191 + "merge_time_ms": 8849, 192 + "conflicts_reported": 0, 193 + "files_processed": 169, 194 + "success": true, 195 + "error": null 196 + }, 197 + { 198 + "strategy": "4-yrs-on-pds", 199 + "merge_time_ms": 2073, 200 + "conflicts_reported": 0, 201 + "files_processed": 50, 202 + "success": true, 203 + "error": null 204 + } 205 + ] 206 + }, 207 + { 208 + "file_count": 50, 209 + "avg_file_size": 1000, 210 + "collaborators": 2, 211 + "edits_per_branch": 10, 212 + "conflict_rate": "high", 213 + "results": [ 214 + { 215 + "strategy": "1-plain-git", 216 + "merge_time_ms": 8198, 217 + "conflicts_reported": 0, 218 + "files_processed": 50, 219 + "success": true, 220 + "error": null 221 + }, 222 + { 223 + "strategy": "2-yrs-diff", 224 + "merge_time_ms": 9827, 225 + "conflicts_reported": 0, 226 + "files_processed": 168, 227 + "success": true, 228 + "error": null 229 + }, 230 + { 231 + "strategy": "3-yrs-sidecar", 232 + "merge_time_ms": 8189, 233 + "conflicts_reported": 0, 234 + "files_processed": 167, 235 + "success": true, 236 + "error": null 237 + }, 238 + { 239 + "strategy": "4-yrs-on-pds", 240 + "merge_time_ms": 1964, 241 + "conflicts_reported": 0, 242 + "files_processed": 50, 243 + "success": true, 244 + "error": null 245 + } 246 + ] 247 + }, 248 + { 249 + "file_count": 200, 250 + "avg_file_size": 1000, 251 + "collaborators": 2, 252 + "edits_per_branch": 20, 253 + "conflict_rate": "low", 254 + "results": [ 255 + { 256 + "strategy": "1-plain-git", 257 + "merge_time_ms": 8354, 258 + "conflicts_reported": 0, 259 + "files_processed": 200, 260 + "success": true, 261 + "error": null 262 + }, 263 + { 264 + "strategy": "2-yrs-diff", 265 + "merge_time_ms": 10168, 266 + "conflicts_reported": 0, 267 + "files_processed": 637, 268 + "success": true, 269 + "error": null 270 + }, 271 + { 272 + "strategy": "3-yrs-sidecar", 273 + "merge_time_ms": 10844, 274 + "conflicts_reported": 0, 275 + "files_processed": 638, 276 + "success": true, 277 + "error": null 278 + }, 279 + { 280 + "strategy": "4-yrs-on-pds", 281 + "merge_time_ms": 6277, 282 + "conflicts_reported": 0, 283 + "files_processed": 200, 284 + "success": true, 285 + "error": null 286 + } 287 + ] 288 + }, 289 + { 290 + "file_count": 200, 291 + "avg_file_size": 1000, 292 + "collaborators": 2, 293 + "edits_per_branch": 20, 294 + "conflict_rate": "medium", 295 + "results": [ 296 + { 297 + "strategy": "1-plain-git", 298 + "merge_time_ms": 8197, 299 + "conflicts_reported": 0, 300 + "files_processed": 200, 301 + "success": true, 302 + "error": null 303 + }, 304 + { 305 + "strategy": "2-yrs-diff", 306 + "merge_time_ms": 11216, 307 + "conflicts_reported": 0, 308 + "files_processed": 637, 309 + "success": true, 310 + "error": null 311 + }, 312 + { 313 + "strategy": "3-yrs-sidecar", 314 + "merge_time_ms": 8838, 315 + "conflicts_reported": 0, 316 + "files_processed": 639, 317 + "success": true, 318 + "error": null 319 + }, 320 + { 321 + "strategy": "4-yrs-on-pds", 322 + "merge_time_ms": 5703, 323 + "conflicts_reported": 0, 324 + "files_processed": 200, 325 + "success": true, 326 + "error": null 327 + } 328 + ] 329 + }, 330 + { 331 + "file_count": 200, 332 + "avg_file_size": 1000, 333 + "collaborators": 2, 334 + "edits_per_branch": 20, 335 + "conflict_rate": "high", 336 + "results": [ 337 + { 338 + "strategy": "1-plain-git", 339 + "merge_time_ms": 8442, 340 + "conflicts_reported": 1, 341 + "files_processed": 202, 342 + "success": false, 343 + "error": "" 344 + }, 345 + { 346 + "strategy": "2-yrs-diff", 347 + "merge_time_ms": 10340, 348 + "conflicts_reported": 0, 349 + "files_processed": 636, 350 + "success": true, 351 + "error": null 352 + }, 353 + { 354 + "strategy": "3-yrs-sidecar", 355 + "merge_time_ms": 9615, 356 + "conflicts_reported": 0, 357 + "files_processed": 638, 358 + "success": true, 359 + "error": null 360 + }, 361 + { 362 + "strategy": "4-yrs-on-pds", 363 + "merge_time_ms": 6323, 364 + "conflicts_reported": 0, 365 + "files_processed": 200, 366 + "success": true, 367 + "error": null 368 + } 369 + ] 370 + } 371 + ]
+18
bench-results/v4-ymap-clean/filesize-pds/report.md
··· 1 + # Merge Strategy Benchmark Results 2 + 3 + Generated: 2026-03-14T05:03:52.188155274+00:00 4 + 5 + | Files | Collabs | Conflict | 1-git (ms) | 1-conflicts | 2-diff (ms) | 3-sidecar (ms) | 4-yrs (ms) | 2-ok | 3-ok | 4-ok | 6 + |-------|---------|----------|-----------|-------------|-------------|----------------|------------|------|------|------| 7 + | 50 | 2 | medium | 9101 | 0 | 9460 | 8342 | 2185 | Y | Y | Y | 8 + | 50 | 2 | medium | 9099 | 0 | 8366 | 9090 | 3048 | Y | Y | Y | 9 + | 50 | 2 | medium | 11159 | 0 | 10340 | 11066 | 7797 | Y | Y | Y | 10 + 11 + ### Legend 12 + 13 + - **1-git**: Plain git 3-way merge 14 + - **2-diff**: git-yrs-merge in diff-only mode 15 + - **3-sidecar**: git-yrs-merge with .yrs/ sidecars 16 + - **4-yrs**: Yrs CRDT merge (simulated, no network) 17 + - **ok**: merge completed successfully (Y/N) 18 + - **conflicts**: number of files with conflict markers (strategy 1 only)
+13
bench-results/v4-ymap-clean/filesize-pds/results.csv
··· 1 + files,conflict_rate,collaborators,edits,strategy,time_ms,conflicts,success 2 + 50,medium,2,10,1-plain-git,9101,0,true 3 + 50,medium,2,10,2-yrs-diff,9460,0,true 4 + 50,medium,2,10,3-yrs-sidecar,8342,0,true 5 + 50,medium,2,10,4-yrs-on-pds,2185,0,true 6 + 50,medium,2,10,1-plain-git,9099,0,true 7 + 50,medium,2,10,2-yrs-diff,8366,0,true 8 + 50,medium,2,10,3-yrs-sidecar,9090,0,true 9 + 50,medium,2,10,4-yrs-on-pds,3048,0,true 10 + 50,medium,2,10,1-plain-git,11159,0,true 11 + 50,medium,2,10,2-yrs-diff,10340,0,true 12 + 50,medium,2,10,3-yrs-sidecar,11066,0,true 13 + 50,medium,2,10,4-yrs-on-pds,7797,0,true
+125
bench-results/v4-ymap-clean/filesize-pds/results.json
··· 1 + [ 2 + { 3 + "file_count": 50, 4 + "avg_file_size": 1000, 5 + "collaborators": 2, 6 + "edits_per_branch": 10, 7 + "conflict_rate": "medium", 8 + "results": [ 9 + { 10 + "strategy": "1-plain-git", 11 + "merge_time_ms": 9101, 12 + "conflicts_reported": 0, 13 + "files_processed": 50, 14 + "success": true, 15 + "error": null 16 + }, 17 + { 18 + "strategy": "2-yrs-diff", 19 + "merge_time_ms": 9460, 20 + "conflicts_reported": 0, 21 + "files_processed": 165, 22 + "success": true, 23 + "error": null 24 + }, 25 + { 26 + "strategy": "3-yrs-sidecar", 27 + "merge_time_ms": 8342, 28 + "conflicts_reported": 0, 29 + "files_processed": 168, 30 + "success": true, 31 + "error": null 32 + }, 33 + { 34 + "strategy": "4-yrs-on-pds", 35 + "merge_time_ms": 2185, 36 + "conflicts_reported": 0, 37 + "files_processed": 50, 38 + "success": true, 39 + "error": null 40 + } 41 + ] 42 + }, 43 + { 44 + "file_count": 50, 45 + "avg_file_size": 10000, 46 + "collaborators": 2, 47 + "edits_per_branch": 10, 48 + "conflict_rate": "medium", 49 + "results": [ 50 + { 51 + "strategy": "1-plain-git", 52 + "merge_time_ms": 9099, 53 + "conflicts_reported": 0, 54 + "files_processed": 50, 55 + "success": true, 56 + "error": null 57 + }, 58 + { 59 + "strategy": "2-yrs-diff", 60 + "merge_time_ms": 8366, 61 + "conflicts_reported": 0, 62 + "files_processed": 169, 63 + "success": true, 64 + "error": null 65 + }, 66 + { 67 + "strategy": "3-yrs-sidecar", 68 + "merge_time_ms": 9090, 69 + "conflicts_reported": 0, 70 + "files_processed": 168, 71 + "success": true, 72 + "error": null 73 + }, 74 + { 75 + "strategy": "4-yrs-on-pds", 76 + "merge_time_ms": 3048, 77 + "conflicts_reported": 0, 78 + "files_processed": 50, 79 + "success": true, 80 + "error": null 81 + } 82 + ] 83 + }, 84 + { 85 + "file_count": 50, 86 + "avg_file_size": 50000, 87 + "collaborators": 2, 88 + "edits_per_branch": 10, 89 + "conflict_rate": "medium", 90 + "results": [ 91 + { 92 + "strategy": "1-plain-git", 93 + "merge_time_ms": 11159, 94 + "conflicts_reported": 0, 95 + "files_processed": 50, 96 + "success": true, 97 + "error": null 98 + }, 99 + { 100 + "strategy": "2-yrs-diff", 101 + "merge_time_ms": 10340, 102 + "conflicts_reported": 0, 103 + "files_processed": 168, 104 + "success": true, 105 + "error": null 106 + }, 107 + { 108 + "strategy": "3-yrs-sidecar", 109 + "merge_time_ms": 11066, 110 + "conflicts_reported": 0, 111 + "files_processed": 168, 112 + "success": true, 113 + "error": null 114 + }, 115 + { 116 + "strategy": "4-yrs-on-pds", 117 + "merge_time_ms": 7797, 118 + "conflicts_reported": 0, 119 + "files_processed": 50, 120 + "success": true, 121 + "error": null 122 + } 123 + ] 124 + } 125 + ]
+143
bench-results/v4-ymap-clean/report.md
··· 1 + # v4-ymap-clean Benchmark Report 2 + 3 + **Date**: 2026-03-14 4 + **Code version**: v4 index-blob (FileIndex serialized as JSON blob in pack) 5 + **PDS**: bluesky-pds.t1cc.commoninternet.net 6 + **Run mode**: Sequential (no parallel benchmark contamination) 7 + 8 + ## Test Results 9 + 10 + | Suite | Result | 11 + |-------|--------| 12 + | Unit/correctness tests | **78/78 passed** | 13 + | E2E tests (real PDS) | **6/6 passed** | 14 + 15 + ## Strategy Legend 16 + 17 + | # | Strategy | Description | Conflicts? | 18 + |---|----------|-------------|-----------| 19 + | 1 | plain-git | Standard `git merge` 3-way via PDS | Yes (git conflicts) | 20 + | 2 | yrs-diff | git merge + git-yrs-merge driver (diff-only) | No (CRDT resolved) | 21 + | 3 | yrs-sidecar | git merge + git-yrs-merge driver + .yrs/ sidecars | No (CRDT resolved) | 22 + | 4 | yrs-on-pds | Yrs CRDT merge via pds-yrs (no git) | No (CRDT resolved) | 23 + 24 + --- 25 + 26 + ## Default PDS Benchmark (3x3 matrix: 10/50/200 files x low/med/high conflict) 27 + 28 + | Files | Conflict | 1-git (ms) | 1-conflicts | 2-diff (ms) | 3-sidecar (ms) | 4-yrs (ms) | Speedup vs git | 29 + |-------|----------|-----------|-------------|-------------|----------------|------------|----------------| 30 + | 10 | low | 7296 | 0 | 8563 | 8689 | **1766** | 4.1x | 31 + | 10 | medium | 7388 | 0 | 7491 | 8840 | **1761** | 4.2x | 32 + | 10 | high | 7647 | 1 | 7772 | 8475 | **1825** | 4.2x | 33 + | 50 | low | 8168 | 0 | 9168 | 8739 | **2175** | 3.8x | 34 + | 50 | medium | 7838 | 0 | 9118 | 8849 | **2073** | 3.8x | 35 + | 50 | high | 8198 | 0 | 9827 | 8189 | **1964** | 4.2x | 36 + | 200 | low | 8354 | 0 | 10168 | 10844 | **6277** | 1.3x | 37 + | 200 | medium | 8197 | 0 | 11216 | 8838 | **5703** | 1.4x | 38 + | 200 | high | 8442 | 1 | 10340 | 9615 | **6323** | 1.3x | 39 + 40 + ### Observations — Default 41 + 42 + - **Strategy 4 (yrs-on-pds) is fastest across the board** at 10 and 50 files (3.8-4.2x faster than git). 43 + - At 200 files, strategy 4 is still faster but the gap narrows (1.3-1.4x) due to O(N) blob round-trips. 44 + - Strategies 1-3 all involve git push/clone to PDS which has a fixed ~7s baseline overhead. 45 + - Strategy 1 (plain git) produced merge conflicts in 2/9 scenarios (high conflict at 10 and 200 files). All CRDT strategies (2, 3, 4) resolved conflicts automatically. 46 + - Strategy 2 (yrs-diff) is slightly slower than plain git due to merge driver overhead. 47 + - Strategy 3 (yrs-sidecar) is the slowest git-based strategy due to .yrs/ sidecar file overhead. 48 + 49 + --- 50 + 51 + ## Stress Benchmark (1000 files) 52 + 53 + | Files | Conflict | 1-git (ms) | 1-conflicts | 2-diff (ms) | 3-sidecar (ms) | 4-yrs (ms) | Ratio 4/1 | 54 + |-------|----------|-----------|-------------|-------------|----------------|------------|-----------| 55 + | 1000 | low | 10129 | 0 | 15258 | 13256 | **73127** | 7.2x slower | 56 + | 1000 | medium | 11122 | 0 | 13438 | 14001 | **68667** | 6.2x slower | 57 + | 1000 | high | 10210 | 0 | 12365 | 13129 | **69197** | 6.8x slower | 58 + 59 + ### Observations — Stress 60 + 61 + - At 1000 files, **git strategies are significantly faster** (~10-15s vs ~70s for pds-yrs). 62 + - Git benefits from O(1) packfile push/clone — all files in one transfer. pds-yrs does O(N) blob round-trips for merge (each file's snapshot + updates must be fetched individually from each repo). 63 + - **No 413 Payload Too Large errors** — the index-blob approach keeps the ATProto record small regardless of file count. 64 + - All 1000-file scenarios succeed for all strategies. 65 + - Strategy 4 times are consistent (~69-73s) regardless of conflict rate, since CRDT merge cost is negligible compared to network I/O. 66 + 67 + --- 68 + 69 + ## Filesize Benchmark (50 files, varying avg file size) 70 + 71 + | File Size | 1-git (ms) | 2-diff (ms) | 3-sidecar (ms) | 4-yrs (ms) | Ratio 4/1 | 72 + |-----------|-----------|-------------|----------------|------------|-----------| 73 + | 1 KB | 9101 | 9460 | 8342 | **2185** | 4.2x faster | 74 + | 10 KB | 9099 | 8366 | 9090 | **3048** | 3.0x faster | 75 + | 50 KB | 11159 | 10340 | 11066 | **7797** | 1.4x faster | 76 + 77 + ### Observations — Filesize 78 + 79 + - Strategy 4 remains faster at all file sizes for 50 files. 80 + - Git strategies are relatively insensitive to file size (pack compression handles it well). 81 + - Strategy 4 scales linearly with data volume: 1KB=2.2s, 10KB=3.0s, 50KB=7.8s. 82 + 83 + --- 84 + 85 + ## Guaranteed Conflict Benchmark (deterministic same-line edits) 86 + 87 + This benchmark uses `ConflictRate::Guaranteed` — both collaborators deterministically 88 + edit the **same line** in the same files, guaranteeing git 3-way merge conflicts. 89 + `edits_per_branch` is capped at `min(file_count, 20)`. 90 + 91 + | Files | 1-git (ms) | 1-conflicts | 2-diff (ms) | 3-sidecar (ms) | 4-yrs (ms) | Speedup vs git | 92 + |-------|-----------|-------------|-------------|----------------|------------|----------------| 93 + | 10 | 8235 | **10** | 9087 | 8487 | **1586** | 5.2x | 94 + | 50 | 8364 | **20** | 9285 | 10161 | **1796** | 4.7x | 95 + | 200 | 8965 | **20** | 12713 | 10805 | **4854** | 1.8x | 96 + 97 + ### Observations — Guaranteed Conflicts 98 + 99 + - Plain git **fails every scenario** — 10-20 conflict files per run (matching `edits_per_branch` cap). 100 + - All three CRDT strategies (2, 3, 4) resolve every conflict cleanly with **zero** conflict markers. 101 + - Strategy 4 remains fastest (1.8-5.2x vs git), and is the only strategy that avoids git entirely. 102 + - This validates the core value proposition: CRDT merge eliminates conflicts that would block plain git workflows. 103 + 104 + ### Why default "high" conflict shows few git conflicts 105 + 106 + The default matrix uses `ConflictRate::High` (75% overlap) with `apply_random_edit`, which picks 107 + random edit types (append, insert, rewrite, delete) at random positions. Even when two collaborators 108 + target the same file, they usually edit different lines — so git's 3-way merge succeeds. 109 + Only `--conflict` with `apply_conflicting_edit` deterministically rewrites the same line, 110 + guaranteeing actual merge conflicts. 111 + 112 + --- 113 + 114 + ## Cross-Strategy Summary 115 + 116 + ### Where pds-yrs (Strategy 4) wins 117 + - **Small-to-medium repos (10-50 files)**: 3-4x faster than any git strategy 118 + - **Zero conflicts**: CRDT merge is always clean, while git had conflicts in 2/9 default scenarios 119 + - **No git dependency**: Works purely over ATProto HTTP API 120 + - **Record size**: Index-blob approach keeps records small at any file count 121 + 122 + ### Where git strategies win 123 + - **Large repos (200+ files)**: git's O(1) packfile transfer beats O(N) blob fetches 124 + - **1000 files**: git is 6-7x faster than pds-yrs 125 + - **File size scaling**: git's pack compression handles large files efficiently 126 + 127 + ### Strategy rankings by file count 128 + 129 + | File Count | Fastest | 2nd | 3rd | 4th | 130 + |------------|---------|-----|-----|-----| 131 + | 10 | 4-yrs | 1-git | 2-diff | 3-sidecar | 132 + | 50 | 4-yrs | 1-git | 3-sidecar | 2-diff | 133 + | 200 | 4-yrs (barely) | 1-git | 3-sidecar | 2-diff | 134 + | 1000 | 1-git | 2-diff | 3-sidecar | 4-yrs | 135 + 136 + ### Conflict resolution 137 + 138 + | Strategy | Auto-resolves conflicts? | Default (high) | Guaranteed | 139 + |----------|--------------------------|----------------|------------| 140 + | 1-git | No | 1 conflict in 9 runs | **10-20 conflicts per run** (100% failure) | 141 + | 2-diff | Yes (CRDT) | 0 | 0 | 142 + | 3-sidecar | Yes (CRDT) | 0 | 0 | 143 + | 4-yrs | Yes (CRDT) | 0 | 0 |
+18
bench-results/v4-ymap-clean/stress-pds/report.md
··· 1 + # Merge Strategy Benchmark Results 2 + 3 + Generated: 2026-03-14T04:54:15.994429871+00:00 4 + 5 + | Files | Collabs | Conflict | 1-git (ms) | 1-conflicts | 2-diff (ms) | 3-sidecar (ms) | 4-yrs (ms) | 2-ok | 3-ok | 4-ok | 6 + |-------|---------|----------|-----------|-------------|-------------|----------------|------------|------|------|------| 7 + | 1000 | 2 | low | 10129 | 0 | 15258 | 13256 | 73127 | Y | Y | Y | 8 + | 1000 | 2 | medium | 11122 | 0 | 13438 | 14001 | 68667 | Y | Y | Y | 9 + | 1000 | 2 | high | 10210 | 0 | 12365 | 13129 | 69197 | Y | Y | Y | 10 + 11 + ### Legend 12 + 13 + - **1-git**: Plain git 3-way merge 14 + - **2-diff**: git-yrs-merge in diff-only mode 15 + - **3-sidecar**: git-yrs-merge with .yrs/ sidecars 16 + - **4-yrs**: Yrs CRDT merge (simulated, no network) 17 + - **ok**: merge completed successfully (Y/N) 18 + - **conflicts**: number of files with conflict markers (strategy 1 only)
+13
bench-results/v4-ymap-clean/stress-pds/results.csv
··· 1 + files,conflict_rate,collaborators,edits,strategy,time_ms,conflicts,success 2 + 1000,low,2,50,1-plain-git,10129,0,true 3 + 1000,low,2,50,2-yrs-diff,15258,0,true 4 + 1000,low,2,50,3-yrs-sidecar,13256,0,true 5 + 1000,low,2,50,4-yrs-on-pds,73127,0,true 6 + 1000,medium,2,50,1-plain-git,11122,0,true 7 + 1000,medium,2,50,2-yrs-diff,13438,0,true 8 + 1000,medium,2,50,3-yrs-sidecar,14001,0,true 9 + 1000,medium,2,50,4-yrs-on-pds,68667,0,true 10 + 1000,high,2,50,1-plain-git,10210,0,true 11 + 1000,high,2,50,2-yrs-diff,12365,0,true 12 + 1000,high,2,50,3-yrs-sidecar,13129,0,true 13 + 1000,high,2,50,4-yrs-on-pds,69197,0,true
+125
bench-results/v4-ymap-clean/stress-pds/results.json
··· 1 + [ 2 + { 3 + "file_count": 1000, 4 + "avg_file_size": 1000, 5 + "collaborators": 2, 6 + "edits_per_branch": 50, 7 + "conflict_rate": "low", 8 + "results": [ 9 + { 10 + "strategy": "1-plain-git", 11 + "merge_time_ms": 10129, 12 + "conflicts_reported": 0, 13 + "files_processed": 1000, 14 + "success": true, 15 + "error": null 16 + }, 17 + { 18 + "strategy": "2-yrs-diff", 19 + "merge_time_ms": 15258, 20 + "conflicts_reported": 0, 21 + "files_processed": 3099, 22 + "success": true, 23 + "error": null 24 + }, 25 + { 26 + "strategy": "3-yrs-sidecar", 27 + "merge_time_ms": 13256, 28 + "conflicts_reported": 0, 29 + "files_processed": 3093, 30 + "success": true, 31 + "error": null 32 + }, 33 + { 34 + "strategy": "4-yrs-on-pds", 35 + "merge_time_ms": 73127, 36 + "conflicts_reported": 0, 37 + "files_processed": 1000, 38 + "success": true, 39 + "error": null 40 + } 41 + ] 42 + }, 43 + { 44 + "file_count": 1000, 45 + "avg_file_size": 1000, 46 + "collaborators": 2, 47 + "edits_per_branch": 50, 48 + "conflict_rate": "medium", 49 + "results": [ 50 + { 51 + "strategy": "1-plain-git", 52 + "merge_time_ms": 11122, 53 + "conflicts_reported": 0, 54 + "files_processed": 1000, 55 + "success": true, 56 + "error": null 57 + }, 58 + { 59 + "strategy": "2-yrs-diff", 60 + "merge_time_ms": 13438, 61 + "conflicts_reported": 0, 62 + "files_processed": 3097, 63 + "success": true, 64 + "error": null 65 + }, 66 + { 67 + "strategy": "3-yrs-sidecar", 68 + "merge_time_ms": 14001, 69 + "conflicts_reported": 0, 70 + "files_processed": 3096, 71 + "success": true, 72 + "error": null 73 + }, 74 + { 75 + "strategy": "4-yrs-on-pds", 76 + "merge_time_ms": 68667, 77 + "conflicts_reported": 0, 78 + "files_processed": 1000, 79 + "success": true, 80 + "error": null 81 + } 82 + ] 83 + }, 84 + { 85 + "file_count": 1000, 86 + "avg_file_size": 1000, 87 + "collaborators": 2, 88 + "edits_per_branch": 50, 89 + "conflict_rate": "high", 90 + "results": [ 91 + { 92 + "strategy": "1-plain-git", 93 + "merge_time_ms": 10210, 94 + "conflicts_reported": 0, 95 + "files_processed": 1000, 96 + "success": true, 97 + "error": null 98 + }, 99 + { 100 + "strategy": "2-yrs-diff", 101 + "merge_time_ms": 12365, 102 + "conflicts_reported": 0, 103 + "files_processed": 3093, 104 + "success": true, 105 + "error": null 106 + }, 107 + { 108 + "strategy": "3-yrs-sidecar", 109 + "merge_time_ms": 13129, 110 + "conflicts_reported": 0, 111 + "files_processed": 3094, 112 + "success": true, 113 + "error": null 114 + }, 115 + { 116 + "strategy": "4-yrs-on-pds", 117 + "merge_time_ms": 69197, 118 + "conflicts_reported": 0, 119 + "files_processed": 1000, 120 + "success": true, 121 + "error": null 122 + } 123 + ] 124 + } 125 + ]
+24
bench-results/v4-ymap-full/default-pds/report.md
··· 1 + # Merge Strategy Benchmark Results 2 + 3 + Generated: 2026-03-14T04:47:07.151699641+00:00 4 + 5 + | Files | Collabs | Conflict | 1-git (ms) | 1-conflicts | 2-diff (ms) | 3-sidecar (ms) | 4-yrs (ms) | 2-ok | 3-ok | 4-ok | 6 + |-------|---------|----------|-----------|-------------|-------------|----------------|------------|------|------|------| 7 + | 10 | 2 | low | 7787 | 0 | 7290 | 9054 | 1251 | Y | Y | Y | 8 + | 10 | 2 | medium | 8046 | 0 | 7569 | 8275 | 1483 | Y | Y | Y | 9 + | 10 | 2 | high | 8028 | 0 | 8090 | 8315 | 2600 | Y | Y | Y | 10 + | 50 | 2 | low | 8789 | 0 | 13323 | 8249 | 2187 | Y | Y | Y | 11 + | 50 | 2 | medium | 8973 | 1 | 8183 | 10361 | 2159 | Y | Y | Y | 12 + | 50 | 2 | high | 8702 | 0 | 8506 | 10109 | 2089 | Y | Y | Y | 13 + | 200 | 2 | low | 9593 | 0 | 11155 | 11431 | 5686 | Y | Y | Y | 14 + | 200 | 2 | medium | 7712 | 0 | 9159 | 9944 | 5061 | Y | Y | Y | 15 + | 200 | 2 | high | 8540 | 0 | 8922 | 10676 | 5156 | Y | Y | Y | 16 + 17 + ### Legend 18 + 19 + - **1-git**: Plain git 3-way merge 20 + - **2-diff**: git-yrs-merge in diff-only mode 21 + - **3-sidecar**: git-yrs-merge with .yrs/ sidecars 22 + - **4-yrs**: Yrs CRDT merge (simulated, no network) 23 + - **ok**: merge completed successfully (Y/N) 24 + - **conflicts**: number of files with conflict markers (strategy 1 only)
+37
bench-results/v4-ymap-full/default-pds/results.csv
··· 1 + files,conflict_rate,collaborators,edits,strategy,time_ms,conflicts,success 2 + 10,low,2,5,1-plain-git,7787,0,true 3 + 10,low,2,5,2-yrs-diff,7290,0,true 4 + 10,low,2,5,3-yrs-sidecar,9054,0,true 5 + 10,low,2,5,4-yrs-on-pds,1251,0,true 6 + 10,medium,2,5,1-plain-git,8046,0,true 7 + 10,medium,2,5,2-yrs-diff,7569,0,true 8 + 10,medium,2,5,3-yrs-sidecar,8275,0,true 9 + 10,medium,2,5,4-yrs-on-pds,1483,0,true 10 + 10,high,2,5,1-plain-git,8028,0,true 11 + 10,high,2,5,2-yrs-diff,8090,0,true 12 + 10,high,2,5,3-yrs-sidecar,8315,0,true 13 + 10,high,2,5,4-yrs-on-pds,2600,0,true 14 + 50,low,2,10,1-plain-git,8789,0,true 15 + 50,low,2,10,2-yrs-diff,13323,0,true 16 + 50,low,2,10,3-yrs-sidecar,8249,0,true 17 + 50,low,2,10,4-yrs-on-pds,2187,0,true 18 + 50,medium,2,10,1-plain-git,8973,1,false 19 + 50,medium,2,10,2-yrs-diff,8183,0,true 20 + 50,medium,2,10,3-yrs-sidecar,10361,0,true 21 + 50,medium,2,10,4-yrs-on-pds,2159,0,true 22 + 50,high,2,10,1-plain-git,8702,0,true 23 + 50,high,2,10,2-yrs-diff,8506,0,true 24 + 50,high,2,10,3-yrs-sidecar,10109,0,true 25 + 50,high,2,10,4-yrs-on-pds,2089,0,true 26 + 200,low,2,20,1-plain-git,9593,0,true 27 + 200,low,2,20,2-yrs-diff,11155,0,true 28 + 200,low,2,20,3-yrs-sidecar,11431,0,true 29 + 200,low,2,20,4-yrs-on-pds,5686,0,true 30 + 200,medium,2,20,1-plain-git,7712,0,true 31 + 200,medium,2,20,2-yrs-diff,9159,0,true 32 + 200,medium,2,20,3-yrs-sidecar,9944,0,true 33 + 200,medium,2,20,4-yrs-on-pds,5061,0,true 34 + 200,high,2,20,1-plain-git,8540,0,true 35 + 200,high,2,20,2-yrs-diff,8922,0,true 36 + 200,high,2,20,3-yrs-sidecar,10676,0,true 37 + 200,high,2,20,4-yrs-on-pds,5156,0,true
+371
bench-results/v4-ymap-full/default-pds/results.json
··· 1 + [ 2 + { 3 + "file_count": 10, 4 + "avg_file_size": 1000, 5 + "collaborators": 2, 6 + "edits_per_branch": 5, 7 + "conflict_rate": "low", 8 + "results": [ 9 + { 10 + "strategy": "1-plain-git", 11 + "merge_time_ms": 7787, 12 + "conflicts_reported": 0, 13 + "files_processed": 10, 14 + "success": true, 15 + "error": null 16 + }, 17 + { 18 + "strategy": "2-yrs-diff", 19 + "merge_time_ms": 7290, 20 + "conflicts_reported": 0, 21 + "files_processed": 39, 22 + "success": true, 23 + "error": null 24 + }, 25 + { 26 + "strategy": "3-yrs-sidecar", 27 + "merge_time_ms": 9054, 28 + "conflicts_reported": 0, 29 + "files_processed": 38, 30 + "success": true, 31 + "error": null 32 + }, 33 + { 34 + "strategy": "4-yrs-on-pds", 35 + "merge_time_ms": 1251, 36 + "conflicts_reported": 0, 37 + "files_processed": 10, 38 + "success": true, 39 + "error": null 40 + } 41 + ] 42 + }, 43 + { 44 + "file_count": 10, 45 + "avg_file_size": 1000, 46 + "collaborators": 2, 47 + "edits_per_branch": 5, 48 + "conflict_rate": "medium", 49 + "results": [ 50 + { 51 + "strategy": "1-plain-git", 52 + "merge_time_ms": 8046, 53 + "conflicts_reported": 0, 54 + "files_processed": 10, 55 + "success": true, 56 + "error": null 57 + }, 58 + { 59 + "strategy": "2-yrs-diff", 60 + "merge_time_ms": 7569, 61 + "conflicts_reported": 0, 62 + "files_processed": 40, 63 + "success": true, 64 + "error": null 65 + }, 66 + { 67 + "strategy": "3-yrs-sidecar", 68 + "merge_time_ms": 8275, 69 + "conflicts_reported": 0, 70 + "files_processed": 37, 71 + "success": true, 72 + "error": null 73 + }, 74 + { 75 + "strategy": "4-yrs-on-pds", 76 + "merge_time_ms": 1483, 77 + "conflicts_reported": 0, 78 + "files_processed": 10, 79 + "success": true, 80 + "error": null 81 + } 82 + ] 83 + }, 84 + { 85 + "file_count": 10, 86 + "avg_file_size": 1000, 87 + "collaborators": 2, 88 + "edits_per_branch": 5, 89 + "conflict_rate": "high", 90 + "results": [ 91 + { 92 + "strategy": "1-plain-git", 93 + "merge_time_ms": 8028, 94 + "conflicts_reported": 0, 95 + "files_processed": 10, 96 + "success": true, 97 + "error": null 98 + }, 99 + { 100 + "strategy": "2-yrs-diff", 101 + "merge_time_ms": 8090, 102 + "conflicts_reported": 0, 103 + "files_processed": 35, 104 + "success": true, 105 + "error": null 106 + }, 107 + { 108 + "strategy": "3-yrs-sidecar", 109 + "merge_time_ms": 8315, 110 + "conflicts_reported": 0, 111 + "files_processed": 38, 112 + "success": true, 113 + "error": null 114 + }, 115 + { 116 + "strategy": "4-yrs-on-pds", 117 + "merge_time_ms": 2600, 118 + "conflicts_reported": 0, 119 + "files_processed": 10, 120 + "success": true, 121 + "error": null 122 + } 123 + ] 124 + }, 125 + { 126 + "file_count": 50, 127 + "avg_file_size": 1000, 128 + "collaborators": 2, 129 + "edits_per_branch": 10, 130 + "conflict_rate": "low", 131 + "results": [ 132 + { 133 + "strategy": "1-plain-git", 134 + "merge_time_ms": 8789, 135 + "conflicts_reported": 0, 136 + "files_processed": 50, 137 + "success": true, 138 + "error": null 139 + }, 140 + { 141 + "strategy": "2-yrs-diff", 142 + "merge_time_ms": 13323, 143 + "conflicts_reported": 0, 144 + "files_processed": 167, 145 + "success": true, 146 + "error": null 147 + }, 148 + { 149 + "strategy": "3-yrs-sidecar", 150 + "merge_time_ms": 8249, 151 + "conflicts_reported": 0, 152 + "files_processed": 167, 153 + "success": true, 154 + "error": null 155 + }, 156 + { 157 + "strategy": "4-yrs-on-pds", 158 + "merge_time_ms": 2187, 159 + "conflicts_reported": 0, 160 + "files_processed": 50, 161 + "success": true, 162 + "error": null 163 + } 164 + ] 165 + }, 166 + { 167 + "file_count": 50, 168 + "avg_file_size": 1000, 169 + "collaborators": 2, 170 + "edits_per_branch": 10, 171 + "conflict_rate": "medium", 172 + "results": [ 173 + { 174 + "strategy": "1-plain-git", 175 + "merge_time_ms": 8973, 176 + "conflicts_reported": 1, 177 + "files_processed": 52, 178 + "success": false, 179 + "error": "" 180 + }, 181 + { 182 + "strategy": "2-yrs-diff", 183 + "merge_time_ms": 8183, 184 + "conflicts_reported": 0, 185 + "files_processed": 169, 186 + "success": true, 187 + "error": null 188 + }, 189 + { 190 + "strategy": "3-yrs-sidecar", 191 + "merge_time_ms": 10361, 192 + "conflicts_reported": 0, 193 + "files_processed": 169, 194 + "success": true, 195 + "error": null 196 + }, 197 + { 198 + "strategy": "4-yrs-on-pds", 199 + "merge_time_ms": 2159, 200 + "conflicts_reported": 0, 201 + "files_processed": 50, 202 + "success": true, 203 + "error": null 204 + } 205 + ] 206 + }, 207 + { 208 + "file_count": 50, 209 + "avg_file_size": 1000, 210 + "collaborators": 2, 211 + "edits_per_branch": 10, 212 + "conflict_rate": "high", 213 + "results": [ 214 + { 215 + "strategy": "1-plain-git", 216 + "merge_time_ms": 8702, 217 + "conflicts_reported": 0, 218 + "files_processed": 50, 219 + "success": true, 220 + "error": null 221 + }, 222 + { 223 + "strategy": "2-yrs-diff", 224 + "merge_time_ms": 8506, 225 + "conflicts_reported": 0, 226 + "files_processed": 167, 227 + "success": true, 228 + "error": null 229 + }, 230 + { 231 + "strategy": "3-yrs-sidecar", 232 + "merge_time_ms": 10109, 233 + "conflicts_reported": 0, 234 + "files_processed": 167, 235 + "success": true, 236 + "error": null 237 + }, 238 + { 239 + "strategy": "4-yrs-on-pds", 240 + "merge_time_ms": 2089, 241 + "conflicts_reported": 0, 242 + "files_processed": 50, 243 + "success": true, 244 + "error": null 245 + } 246 + ] 247 + }, 248 + { 249 + "file_count": 200, 250 + "avg_file_size": 1000, 251 + "collaborators": 2, 252 + "edits_per_branch": 20, 253 + "conflict_rate": "low", 254 + "results": [ 255 + { 256 + "strategy": "1-plain-git", 257 + "merge_time_ms": 9593, 258 + "conflicts_reported": 0, 259 + "files_processed": 200, 260 + "success": true, 261 + "error": null 262 + }, 263 + { 264 + "strategy": "2-yrs-diff", 265 + "merge_time_ms": 11155, 266 + "conflicts_reported": 0, 267 + "files_processed": 637, 268 + "success": true, 269 + "error": null 270 + }, 271 + { 272 + "strategy": "3-yrs-sidecar", 273 + "merge_time_ms": 11431, 274 + "conflicts_reported": 0, 275 + "files_processed": 635, 276 + "success": true, 277 + "error": null 278 + }, 279 + { 280 + "strategy": "4-yrs-on-pds", 281 + "merge_time_ms": 5686, 282 + "conflicts_reported": 0, 283 + "files_processed": 200, 284 + "success": true, 285 + "error": null 286 + } 287 + ] 288 + }, 289 + { 290 + "file_count": 200, 291 + "avg_file_size": 1000, 292 + "collaborators": 2, 293 + "edits_per_branch": 20, 294 + "conflict_rate": "medium", 295 + "results": [ 296 + { 297 + "strategy": "1-plain-git", 298 + "merge_time_ms": 7712, 299 + "conflicts_reported": 0, 300 + "files_processed": 200, 301 + "success": true, 302 + "error": null 303 + }, 304 + { 305 + "strategy": "2-yrs-diff", 306 + "merge_time_ms": 9159, 307 + "conflicts_reported": 0, 308 + "files_processed": 639, 309 + "success": true, 310 + "error": null 311 + }, 312 + { 313 + "strategy": "3-yrs-sidecar", 314 + "merge_time_ms": 9944, 315 + "conflicts_reported": 0, 316 + "files_processed": 638, 317 + "success": true, 318 + "error": null 319 + }, 320 + { 321 + "strategy": "4-yrs-on-pds", 322 + "merge_time_ms": 5061, 323 + "conflicts_reported": 0, 324 + "files_processed": 200, 325 + "success": true, 326 + "error": null 327 + } 328 + ] 329 + }, 330 + { 331 + "file_count": 200, 332 + "avg_file_size": 1000, 333 + "collaborators": 2, 334 + "edits_per_branch": 20, 335 + "conflict_rate": "high", 336 + "results": [ 337 + { 338 + "strategy": "1-plain-git", 339 + "merge_time_ms": 8540, 340 + "conflicts_reported": 0, 341 + "files_processed": 200, 342 + "success": true, 343 + "error": null 344 + }, 345 + { 346 + "strategy": "2-yrs-diff", 347 + "merge_time_ms": 8922, 348 + "conflicts_reported": 0, 349 + "files_processed": 635, 350 + "success": true, 351 + "error": null 352 + }, 353 + { 354 + "strategy": "3-yrs-sidecar", 355 + "merge_time_ms": 10676, 356 + "conflicts_reported": 0, 357 + "files_processed": 636, 358 + "success": true, 359 + "error": null 360 + }, 361 + { 362 + "strategy": "4-yrs-on-pds", 363 + "merge_time_ms": 5156, 364 + "conflicts_reported": 0, 365 + "files_processed": 200, 366 + "success": true, 367 + "error": null 368 + } 369 + ] 370 + } 371 + ]
+18
bench-results/v4-ymap-full/filesize-pds/report.md
··· 1 + # Merge Strategy Benchmark Results 2 + 3 + Generated: 2026-03-14T04:43:23.926838909+00:00 4 + 5 + | Files | Collabs | Conflict | 1-git (ms) | 1-conflicts | 2-diff (ms) | 3-sidecar (ms) | 4-yrs (ms) | 2-ok | 3-ok | 4-ok | 6 + |-------|---------|----------|-----------|-------------|-------------|----------------|------------|------|------|------| 7 + | 50 | 2 | medium | 7921 | 0 | 7817 | 9085 | 2066 | Y | Y | Y | 8 + | 50 | 2 | medium | 8640 | 0 | 8501 | 10198 | 3210 | Y | Y | Y | 9 + | 50 | 2 | medium | 8987 | 0 | 13013 | 11794 | 8870 | Y | Y | Y | 10 + 11 + ### Legend 12 + 13 + - **1-git**: Plain git 3-way merge 14 + - **2-diff**: git-yrs-merge in diff-only mode 15 + - **3-sidecar**: git-yrs-merge with .yrs/ sidecars 16 + - **4-yrs**: Yrs CRDT merge (simulated, no network) 17 + - **ok**: merge completed successfully (Y/N) 18 + - **conflicts**: number of files with conflict markers (strategy 1 only)
+13
bench-results/v4-ymap-full/filesize-pds/results.csv
··· 1 + files,conflict_rate,collaborators,edits,strategy,time_ms,conflicts,success 2 + 50,medium,2,10,1-plain-git,7921,0,true 3 + 50,medium,2,10,2-yrs-diff,7817,0,true 4 + 50,medium,2,10,3-yrs-sidecar,9085,0,true 5 + 50,medium,2,10,4-yrs-on-pds,2066,0,true 6 + 50,medium,2,10,1-plain-git,8640,0,true 7 + 50,medium,2,10,2-yrs-diff,8501,0,true 8 + 50,medium,2,10,3-yrs-sidecar,10198,0,true 9 + 50,medium,2,10,4-yrs-on-pds,3210,0,true 10 + 50,medium,2,10,1-plain-git,8987,0,true 11 + 50,medium,2,10,2-yrs-diff,13013,0,true 12 + 50,medium,2,10,3-yrs-sidecar,11794,0,true 13 + 50,medium,2,10,4-yrs-on-pds,8870,0,true
+125
bench-results/v4-ymap-full/filesize-pds/results.json
··· 1 + [ 2 + { 3 + "file_count": 50, 4 + "avg_file_size": 1000, 5 + "collaborators": 2, 6 + "edits_per_branch": 10, 7 + "conflict_rate": "medium", 8 + "results": [ 9 + { 10 + "strategy": "1-plain-git", 11 + "merge_time_ms": 7921, 12 + "conflicts_reported": 0, 13 + "files_processed": 50, 14 + "success": true, 15 + "error": null 16 + }, 17 + { 18 + "strategy": "2-yrs-diff", 19 + "merge_time_ms": 7817, 20 + "conflicts_reported": 0, 21 + "files_processed": 170, 22 + "success": true, 23 + "error": null 24 + }, 25 + { 26 + "strategy": "3-yrs-sidecar", 27 + "merge_time_ms": 9085, 28 + "conflicts_reported": 0, 29 + "files_processed": 170, 30 + "success": true, 31 + "error": null 32 + }, 33 + { 34 + "strategy": "4-yrs-on-pds", 35 + "merge_time_ms": 2066, 36 + "conflicts_reported": 0, 37 + "files_processed": 50, 38 + "success": true, 39 + "error": null 40 + } 41 + ] 42 + }, 43 + { 44 + "file_count": 50, 45 + "avg_file_size": 10000, 46 + "collaborators": 2, 47 + "edits_per_branch": 10, 48 + "conflict_rate": "medium", 49 + "results": [ 50 + { 51 + "strategy": "1-plain-git", 52 + "merge_time_ms": 8640, 53 + "conflicts_reported": 0, 54 + "files_processed": 50, 55 + "success": true, 56 + "error": null 57 + }, 58 + { 59 + "strategy": "2-yrs-diff", 60 + "merge_time_ms": 8501, 61 + "conflicts_reported": 0, 62 + "files_processed": 171, 63 + "success": true, 64 + "error": null 65 + }, 66 + { 67 + "strategy": "3-yrs-sidecar", 68 + "merge_time_ms": 10198, 69 + "conflicts_reported": 0, 70 + "files_processed": 169, 71 + "success": true, 72 + "error": null 73 + }, 74 + { 75 + "strategy": "4-yrs-on-pds", 76 + "merge_time_ms": 3210, 77 + "conflicts_reported": 0, 78 + "files_processed": 50, 79 + "success": true, 80 + "error": null 81 + } 82 + ] 83 + }, 84 + { 85 + "file_count": 50, 86 + "avg_file_size": 50000, 87 + "collaborators": 2, 88 + "edits_per_branch": 10, 89 + "conflict_rate": "medium", 90 + "results": [ 91 + { 92 + "strategy": "1-plain-git", 93 + "merge_time_ms": 8987, 94 + "conflicts_reported": 0, 95 + "files_processed": 50, 96 + "success": true, 97 + "error": null 98 + }, 99 + { 100 + "strategy": "2-yrs-diff", 101 + "merge_time_ms": 13013, 102 + "conflicts_reported": 0, 103 + "files_processed": 169, 104 + "success": true, 105 + "error": null 106 + }, 107 + { 108 + "strategy": "3-yrs-sidecar", 109 + "merge_time_ms": 11794, 110 + "conflicts_reported": 0, 111 + "files_processed": 171, 112 + "success": true, 113 + "error": null 114 + }, 115 + { 116 + "strategy": "4-yrs-on-pds", 117 + "merge_time_ms": 8870, 118 + "conflicts_reported": 0, 119 + "files_processed": 50, 120 + "success": true, 121 + "error": null 122 + } 123 + ] 124 + } 125 + ]
+17
bench-results/v4-ymap-full/stress-pds/report.md
··· 1 + # Merge Strategy Benchmark Results 2 + 3 + Generated: 2026-03-14T04:45:40.405946773+00:00 4 + 5 + | Files | Collabs | Conflict | 1-git (ms) | 1-conflicts | 2-diff (ms) | 3-sidecar (ms) | 4-yrs (ms) | 2-ok | 3-ok | 4-ok | 6 + |-------|---------|----------|-----------|-------------|-------------|----------------|------------|------|------|------| 7 + | 1000 | 2 | medium | 9565 | 0 | 13327 | 11644 | 93896 | Y | Y | Y | 8 + | 1000 | 2 | high | 9965 | 0 | 11747 | 11991 | 81077 | Y | Y | Y | 9 + 10 + ### Legend 11 + 12 + - **1-git**: Plain git 3-way merge 13 + - **2-diff**: git-yrs-merge in diff-only mode 14 + - **3-sidecar**: git-yrs-merge with .yrs/ sidecars 15 + - **4-yrs**: Yrs CRDT merge (simulated, no network) 16 + - **ok**: merge completed successfully (Y/N) 17 + - **conflicts**: number of files with conflict markers (strategy 1 only)
+9
bench-results/v4-ymap-full/stress-pds/results.csv
··· 1 + files,conflict_rate,collaborators,edits,strategy,time_ms,conflicts,success 2 + 1000,medium,2,50,1-plain-git,9565,0,true 3 + 1000,medium,2,50,2-yrs-diff,13327,0,true 4 + 1000,medium,2,50,3-yrs-sidecar,11644,0,true 5 + 1000,medium,2,50,4-yrs-on-pds,93896,0,true 6 + 1000,high,2,50,1-plain-git,9965,0,true 7 + 1000,high,2,50,2-yrs-diff,11747,0,true 8 + 1000,high,2,50,3-yrs-sidecar,11991,0,true 9 + 1000,high,2,50,4-yrs-on-pds,81077,0,true
+84
bench-results/v4-ymap-full/stress-pds/results.json
··· 1 + [ 2 + { 3 + "file_count": 1000, 4 + "avg_file_size": 1000, 5 + "collaborators": 2, 6 + "edits_per_branch": 50, 7 + "conflict_rate": "medium", 8 + "results": [ 9 + { 10 + "strategy": "1-plain-git", 11 + "merge_time_ms": 9565, 12 + "conflicts_reported": 0, 13 + "files_processed": 1000, 14 + "success": true, 15 + "error": null 16 + }, 17 + { 18 + "strategy": "2-yrs-diff", 19 + "merge_time_ms": 13327, 20 + "conflicts_reported": 0, 21 + "files_processed": 3097, 22 + "success": true, 23 + "error": null 24 + }, 25 + { 26 + "strategy": "3-yrs-sidecar", 27 + "merge_time_ms": 11644, 28 + "conflicts_reported": 0, 29 + "files_processed": 3096, 30 + "success": true, 31 + "error": null 32 + }, 33 + { 34 + "strategy": "4-yrs-on-pds", 35 + "merge_time_ms": 93896, 36 + "conflicts_reported": 0, 37 + "files_processed": 1000, 38 + "success": true, 39 + "error": null 40 + } 41 + ] 42 + }, 43 + { 44 + "file_count": 1000, 45 + "avg_file_size": 1000, 46 + "collaborators": 2, 47 + "edits_per_branch": 50, 48 + "conflict_rate": "high", 49 + "results": [ 50 + { 51 + "strategy": "1-plain-git", 52 + "merge_time_ms": 9965, 53 + "conflicts_reported": 0, 54 + "files_processed": 1000, 55 + "success": true, 56 + "error": null 57 + }, 58 + { 59 + "strategy": "2-yrs-diff", 60 + "merge_time_ms": 11747, 61 + "conflicts_reported": 0, 62 + "files_processed": 3097, 63 + "success": true, 64 + "error": null 65 + }, 66 + { 67 + "strategy": "3-yrs-sidecar", 68 + "merge_time_ms": 11991, 69 + "conflicts_reported": 0, 70 + "files_processed": 3095, 71 + "success": true, 72 + "error": null 73 + }, 74 + { 75 + "strategy": "4-yrs-on-pds", 76 + "merge_time_ms": 81077, 77 + "conflicts_reported": 0, 78 + "files_processed": 1000, 79 + "success": true, 80 + "error": null 81 + } 82 + ] 83 + } 84 + ]
+24
bench-results/v4-ymap-index/default-pds/report.md
··· 1 + # Merge Strategy Benchmark Results 2 + 3 + Generated: 2026-03-14T04:30:42.537240493+00:00 4 + 5 + | Files | Collabs | Conflict | 1-git (ms) | 1-conflicts | 2-diff (ms) | 3-sidecar (ms) | 4-yrs (ms) | 2-ok | 3-ok | 4-ok | 6 + |-------|---------|----------|-----------|-------------|-------------|----------------|------------|------|------|------| 7 + | 10 | 2 | low | - | - | - | - | 1850 | - | - | Y | 8 + | 10 | 2 | medium | - | - | - | - | 2225 | - | - | Y | 9 + | 10 | 2 | high | - | - | - | - | 2145 | - | - | Y | 10 + | 50 | 2 | low | - | - | - | - | 3330 | - | - | Y | 11 + | 50 | 2 | medium | - | - | - | - | 4079 | - | - | Y | 12 + | 50 | 2 | high | - | - | - | - | 2339 | - | - | Y | 13 + | 200 | 2 | low | - | - | - | - | 9473 | - | - | Y | 14 + | 200 | 2 | medium | - | - | - | - | 7413 | - | - | Y | 15 + | 200 | 2 | high | - | - | - | - | 5081 | - | - | Y | 16 + 17 + ### Legend 18 + 19 + - **1-git**: Plain git 3-way merge 20 + - **2-diff**: git-yrs-merge in diff-only mode 21 + - **3-sidecar**: git-yrs-merge with .yrs/ sidecars 22 + - **4-yrs**: Yrs CRDT merge (simulated, no network) 23 + - **ok**: merge completed successfully (Y/N) 24 + - **conflicts**: number of files with conflict markers (strategy 1 only)
+10
bench-results/v4-ymap-index/default-pds/results.csv
··· 1 + files,conflict_rate,collaborators,edits,strategy,time_ms,conflicts,success 2 + 10,low,2,5,4-yrs-on-pds,1850,0,true 3 + 10,medium,2,5,4-yrs-on-pds,2225,0,true 4 + 10,high,2,5,4-yrs-on-pds,2145,0,true 5 + 50,low,2,10,4-yrs-on-pds,3330,0,true 6 + 50,medium,2,10,4-yrs-on-pds,4079,0,true 7 + 50,high,2,10,4-yrs-on-pds,2339,0,true 8 + 200,low,2,20,4-yrs-on-pds,9473,0,true 9 + 200,medium,2,20,4-yrs-on-pds,7413,0,true 10 + 200,high,2,20,4-yrs-on-pds,5081,0,true
+155
bench-results/v4-ymap-index/default-pds/results.json
··· 1 + [ 2 + { 3 + "file_count": 10, 4 + "avg_file_size": 1000, 5 + "collaborators": 2, 6 + "edits_per_branch": 5, 7 + "conflict_rate": "low", 8 + "results": [ 9 + { 10 + "strategy": "4-yrs-on-pds", 11 + "merge_time_ms": 1850, 12 + "conflicts_reported": 0, 13 + "files_processed": 10, 14 + "success": true, 15 + "error": null 16 + } 17 + ] 18 + }, 19 + { 20 + "file_count": 10, 21 + "avg_file_size": 1000, 22 + "collaborators": 2, 23 + "edits_per_branch": 5, 24 + "conflict_rate": "medium", 25 + "results": [ 26 + { 27 + "strategy": "4-yrs-on-pds", 28 + "merge_time_ms": 2225, 29 + "conflicts_reported": 0, 30 + "files_processed": 10, 31 + "success": true, 32 + "error": null 33 + } 34 + ] 35 + }, 36 + { 37 + "file_count": 10, 38 + "avg_file_size": 1000, 39 + "collaborators": 2, 40 + "edits_per_branch": 5, 41 + "conflict_rate": "high", 42 + "results": [ 43 + { 44 + "strategy": "4-yrs-on-pds", 45 + "merge_time_ms": 2145, 46 + "conflicts_reported": 0, 47 + "files_processed": 10, 48 + "success": true, 49 + "error": null 50 + } 51 + ] 52 + }, 53 + { 54 + "file_count": 50, 55 + "avg_file_size": 1000, 56 + "collaborators": 2, 57 + "edits_per_branch": 10, 58 + "conflict_rate": "low", 59 + "results": [ 60 + { 61 + "strategy": "4-yrs-on-pds", 62 + "merge_time_ms": 3330, 63 + "conflicts_reported": 0, 64 + "files_processed": 50, 65 + "success": true, 66 + "error": null 67 + } 68 + ] 69 + }, 70 + { 71 + "file_count": 50, 72 + "avg_file_size": 1000, 73 + "collaborators": 2, 74 + "edits_per_branch": 10, 75 + "conflict_rate": "medium", 76 + "results": [ 77 + { 78 + "strategy": "4-yrs-on-pds", 79 + "merge_time_ms": 4079, 80 + "conflicts_reported": 0, 81 + "files_processed": 50, 82 + "success": true, 83 + "error": null 84 + } 85 + ] 86 + }, 87 + { 88 + "file_count": 50, 89 + "avg_file_size": 1000, 90 + "collaborators": 2, 91 + "edits_per_branch": 10, 92 + "conflict_rate": "high", 93 + "results": [ 94 + { 95 + "strategy": "4-yrs-on-pds", 96 + "merge_time_ms": 2339, 97 + "conflicts_reported": 0, 98 + "files_processed": 50, 99 + "success": true, 100 + "error": null 101 + } 102 + ] 103 + }, 104 + { 105 + "file_count": 200, 106 + "avg_file_size": 1000, 107 + "collaborators": 2, 108 + "edits_per_branch": 20, 109 + "conflict_rate": "low", 110 + "results": [ 111 + { 112 + "strategy": "4-yrs-on-pds", 113 + "merge_time_ms": 9473, 114 + "conflicts_reported": 0, 115 + "files_processed": 200, 116 + "success": true, 117 + "error": null 118 + } 119 + ] 120 + }, 121 + { 122 + "file_count": 200, 123 + "avg_file_size": 1000, 124 + "collaborators": 2, 125 + "edits_per_branch": 20, 126 + "conflict_rate": "medium", 127 + "results": [ 128 + { 129 + "strategy": "4-yrs-on-pds", 130 + "merge_time_ms": 7413, 131 + "conflicts_reported": 0, 132 + "files_processed": 200, 133 + "success": true, 134 + "error": null 135 + } 136 + ] 137 + }, 138 + { 139 + "file_count": 200, 140 + "avg_file_size": 1000, 141 + "collaborators": 2, 142 + "edits_per_branch": 20, 143 + "conflict_rate": "high", 144 + "results": [ 145 + { 146 + "strategy": "4-yrs-on-pds", 147 + "merge_time_ms": 5081, 148 + "conflicts_reported": 0, 149 + "files_processed": 200, 150 + "success": true, 151 + "error": null 152 + } 153 + ] 154 + } 155 + ]
+18
bench-results/v4-ymap-index/filesize-pds/report.md
··· 1 + # Merge Strategy Benchmark Results 2 + 3 + Generated: 2026-03-14T04:30:09.362688559+00:00 4 + 5 + | Files | Collabs | Conflict | 1-git (ms) | 1-conflicts | 2-diff (ms) | 3-sidecar (ms) | 4-yrs (ms) | 2-ok | 3-ok | 4-ok | 6 + |-------|---------|----------|-----------|-------------|-------------|----------------|------------|------|------|------| 7 + | 50 | 2 | medium | - | - | - | - | 4083 | - | - | Y | 8 + | 50 | 2 | medium | - | - | - | - | 5061 | - | - | Y | 9 + | 50 | 2 | medium | - | - | - | - | 13764 | - | - | Y | 10 + 11 + ### Legend 12 + 13 + - **1-git**: Plain git 3-way merge 14 + - **2-diff**: git-yrs-merge in diff-only mode 15 + - **3-sidecar**: git-yrs-merge with .yrs/ sidecars 16 + - **4-yrs**: Yrs CRDT merge (simulated, no network) 17 + - **ok**: merge completed successfully (Y/N) 18 + - **conflicts**: number of files with conflict markers (strategy 1 only)
+4
bench-results/v4-ymap-index/filesize-pds/results.csv
··· 1 + files,conflict_rate,collaborators,edits,strategy,time_ms,conflicts,success 2 + 50,medium,2,10,4-yrs-on-pds,4083,0,true 3 + 50,medium,2,10,4-yrs-on-pds,5061,0,true 4 + 50,medium,2,10,4-yrs-on-pds,13764,0,true
+53
bench-results/v4-ymap-index/filesize-pds/results.json
··· 1 + [ 2 + { 3 + "file_count": 50, 4 + "avg_file_size": 1000, 5 + "collaborators": 2, 6 + "edits_per_branch": 10, 7 + "conflict_rate": "medium", 8 + "results": [ 9 + { 10 + "strategy": "4-yrs-on-pds", 11 + "merge_time_ms": 4083, 12 + "conflicts_reported": 0, 13 + "files_processed": 50, 14 + "success": true, 15 + "error": null 16 + } 17 + ] 18 + }, 19 + { 20 + "file_count": 50, 21 + "avg_file_size": 10000, 22 + "collaborators": 2, 23 + "edits_per_branch": 10, 24 + "conflict_rate": "medium", 25 + "results": [ 26 + { 27 + "strategy": "4-yrs-on-pds", 28 + "merge_time_ms": 5061, 29 + "conflicts_reported": 0, 30 + "files_processed": 50, 31 + "success": true, 32 + "error": null 33 + } 34 + ] 35 + }, 36 + { 37 + "file_count": 50, 38 + "avg_file_size": 50000, 39 + "collaborators": 2, 40 + "edits_per_branch": 10, 41 + "conflict_rate": "medium", 42 + "results": [ 43 + { 44 + "strategy": "4-yrs-on-pds", 45 + "merge_time_ms": 13764, 46 + "conflicts_reported": 0, 47 + "files_processed": 50, 48 + "success": true, 49 + "error": null 50 + } 51 + ] 52 + } 53 + ]
+18
bench-results/v4-ymap-index/stress-pds/report.md
··· 1 + # Merge Strategy Benchmark Results 2 + 3 + Generated: 2026-03-14T04:33:43.066882104+00:00 4 + 5 + | Files | Collabs | Conflict | 1-git (ms) | 1-conflicts | 2-diff (ms) | 3-sidecar (ms) | 4-yrs (ms) | 2-ok | 3-ok | 4-ok | 6 + |-------|---------|----------|-----------|-------------|-------------|----------------|------------|------|------|------| 7 + | 1000 | 2 | low | - | - | - | - | 118492 | - | - | Y | 8 + | 1000 | 2 | medium | - | - | - | - | 66822 | - | - | Y | 9 + | 1000 | 2 | high | - | - | - | - | 69108 | - | - | Y | 10 + 11 + ### Legend 12 + 13 + - **1-git**: Plain git 3-way merge 14 + - **2-diff**: git-yrs-merge in diff-only mode 15 + - **3-sidecar**: git-yrs-merge with .yrs/ sidecars 16 + - **4-yrs**: Yrs CRDT merge (simulated, no network) 17 + - **ok**: merge completed successfully (Y/N) 18 + - **conflicts**: number of files with conflict markers (strategy 1 only)
+4
bench-results/v4-ymap-index/stress-pds/results.csv
··· 1 + files,conflict_rate,collaborators,edits,strategy,time_ms,conflicts,success 2 + 1000,low,2,50,4-yrs-on-pds,118492,0,true 3 + 1000,medium,2,50,4-yrs-on-pds,66822,0,true 4 + 1000,high,2,50,4-yrs-on-pds,69108,0,true
+53
bench-results/v4-ymap-index/stress-pds/results.json
··· 1 + [ 2 + { 3 + "file_count": 1000, 4 + "avg_file_size": 1000, 5 + "collaborators": 2, 6 + "edits_per_branch": 50, 7 + "conflict_rate": "low", 8 + "results": [ 9 + { 10 + "strategy": "4-yrs-on-pds", 11 + "merge_time_ms": 118492, 12 + "conflicts_reported": 0, 13 + "files_processed": 1000, 14 + "success": true, 15 + "error": null 16 + } 17 + ] 18 + }, 19 + { 20 + "file_count": 1000, 21 + "avg_file_size": 1000, 22 + "collaborators": 2, 23 + "edits_per_branch": 50, 24 + "conflict_rate": "medium", 25 + "results": [ 26 + { 27 + "strategy": "4-yrs-on-pds", 28 + "merge_time_ms": 66822, 29 + "conflicts_reported": 0, 30 + "files_processed": 1000, 31 + "success": true, 32 + "error": null 33 + } 34 + ] 35 + }, 36 + { 37 + "file_count": 1000, 38 + "avg_file_size": 1000, 39 + "collaborators": 2, 40 + "edits_per_branch": 50, 41 + "conflict_rate": "high", 42 + "results": [ 43 + { 44 + "strategy": "4-yrs-on-pds", 45 + "merge_time_ms": 69108, 46 + "conflicts_reported": 0, 47 + "files_processed": 1000, 48 + "success": true, 49 + "error": null 50 + } 51 + ] 52 + } 53 + ]
+18
bench-results/v5-real-conflicts/conflict-pds/report.md
··· 1 + # Merge Strategy Benchmark Results 2 + 3 + Generated: 2026-03-14T17:59:16.966659237+00:00 4 + 5 + | Files | Collabs | Conflict | 1-git (ms) | 1-conflicts | 2-diff (ms) | 3-sidecar (ms) | 4-yrs (ms) | 2-ok | 3-ok | 4-ok | 6 + |-------|---------|----------|-----------|-------------|-------------|----------------|------------|------|------|------| 7 + | 10 | 2 | guaranteed | 8299 | 10 | 9511 | 7664 | 1823 | Y | Y | Y | 8 + | 50 | 2 | guaranteed | 9684 | 20 | 9249 | 8714 | 1951 | Y | Y | Y | 9 + | 200 | 2 | guaranteed | 10162 | 20 | 9485 | 9647 | 3144 | Y | Y | Y | 10 + 11 + ### Legend 12 + 13 + - **1-git**: Plain git 3-way merge 14 + - **2-diff**: git-yrs-merge in diff-only mode 15 + - **3-sidecar**: git-yrs-merge with .yrs/ sidecars 16 + - **4-yrs**: Yrs CRDT merge (simulated, no network) 17 + - **ok**: merge completed successfully (Y/N) 18 + - **conflicts**: number of files with conflict markers (strategy 1 only)
+13
bench-results/v5-real-conflicts/conflict-pds/results.csv
··· 1 + files,conflict_rate,collaborators,edits,strategy,time_ms,conflicts,success 2 + 10,guaranteed,2,10,1-plain-git,8299,10,false 3 + 10,guaranteed,2,10,2-yrs-diff,9511,0,true 4 + 10,guaranteed,2,10,3-yrs-sidecar,7664,0,true 5 + 10,guaranteed,2,10,4-yrs-on-pds,1823,0,true 6 + 50,guaranteed,2,20,1-plain-git,9684,20,false 7 + 50,guaranteed,2,20,2-yrs-diff,9249,0,true 8 + 50,guaranteed,2,20,3-yrs-sidecar,8714,0,true 9 + 50,guaranteed,2,20,4-yrs-on-pds,1951,0,true 10 + 200,guaranteed,2,20,1-plain-git,10162,20,false 11 + 200,guaranteed,2,20,2-yrs-diff,9485,0,true 12 + 200,guaranteed,2,20,3-yrs-sidecar,9647,0,true 13 + 200,guaranteed,2,20,4-yrs-on-pds,3144,0,true
+125
bench-results/v5-real-conflicts/conflict-pds/results.json
··· 1 + [ 2 + { 3 + "file_count": 10, 4 + "avg_file_size": 1000, 5 + "collaborators": 2, 6 + "edits_per_branch": 10, 7 + "conflict_rate": "guaranteed", 8 + "results": [ 9 + { 10 + "strategy": "1-plain-git", 11 + "merge_time_ms": 8299, 12 + "conflicts_reported": 10, 13 + "files_processed": 30, 14 + "success": false, 15 + "error": "" 16 + }, 17 + { 18 + "strategy": "2-yrs-diff", 19 + "merge_time_ms": 9511, 20 + "conflicts_reported": 0, 21 + "files_processed": 51, 22 + "success": true, 23 + "error": null 24 + }, 25 + { 26 + "strategy": "3-yrs-sidecar", 27 + "merge_time_ms": 7664, 28 + "conflicts_reported": 0, 29 + "files_processed": 51, 30 + "success": true, 31 + "error": null 32 + }, 33 + { 34 + "strategy": "4-yrs-on-pds", 35 + "merge_time_ms": 1823, 36 + "conflicts_reported": 0, 37 + "files_processed": 10, 38 + "success": true, 39 + "error": null 40 + } 41 + ] 42 + }, 43 + { 44 + "file_count": 50, 45 + "avg_file_size": 1000, 46 + "collaborators": 2, 47 + "edits_per_branch": 20, 48 + "conflict_rate": "guaranteed", 49 + "results": [ 50 + { 51 + "strategy": "1-plain-git", 52 + "merge_time_ms": 9684, 53 + "conflicts_reported": 20, 54 + "files_processed": 90, 55 + "success": false, 56 + "error": "" 57 + }, 58 + { 59 + "strategy": "2-yrs-diff", 60 + "merge_time_ms": 9249, 61 + "conflicts_reported": 0, 62 + "files_processed": 191, 63 + "success": true, 64 + "error": null 65 + }, 66 + { 67 + "strategy": "3-yrs-sidecar", 68 + "merge_time_ms": 8714, 69 + "conflicts_reported": 0, 70 + "files_processed": 191, 71 + "success": true, 72 + "error": null 73 + }, 74 + { 75 + "strategy": "4-yrs-on-pds", 76 + "merge_time_ms": 1951, 77 + "conflicts_reported": 0, 78 + "files_processed": 50, 79 + "success": true, 80 + "error": null 81 + } 82 + ] 83 + }, 84 + { 85 + "file_count": 200, 86 + "avg_file_size": 1000, 87 + "collaborators": 2, 88 + "edits_per_branch": 20, 89 + "conflict_rate": "guaranteed", 90 + "results": [ 91 + { 92 + "strategy": "1-plain-git", 93 + "merge_time_ms": 10162, 94 + "conflicts_reported": 20, 95 + "files_processed": 240, 96 + "success": false, 97 + "error": "" 98 + }, 99 + { 100 + "strategy": "2-yrs-diff", 101 + "merge_time_ms": 9485, 102 + "conflicts_reported": 0, 103 + "files_processed": 641, 104 + "success": true, 105 + "error": null 106 + }, 107 + { 108 + "strategy": "3-yrs-sidecar", 109 + "merge_time_ms": 9647, 110 + "conflicts_reported": 0, 111 + "files_processed": 641, 112 + "success": true, 113 + "error": null 114 + }, 115 + { 116 + "strategy": "4-yrs-on-pds", 117 + "merge_time_ms": 3144, 118 + "conflicts_reported": 0, 119 + "files_processed": 200, 120 + "success": true, 121 + "error": null 122 + } 123 + ] 124 + } 125 + ]
+24
bench-results/v5-real-conflicts/default-pds/report.md
··· 1 + # Merge Strategy Benchmark Results 2 + 3 + Generated: 2026-03-14T17:53:24.337828215+00:00 4 + 5 + | Files | Collabs | Conflict | 1-git (ms) | 1-conflicts | 2-diff (ms) | 3-sidecar (ms) | 4-yrs (ms) | 2-ok | 3-ok | 4-ok | 6 + |-------|---------|----------|-----------|-------------|-------------|----------------|------------|------|------|------| 7 + | 10 | 2 | low | 11455 | 0 | 8282 | 7247 | 1960 | Y | Y | Y | 8 + | 10 | 2 | medium | 8885 | 1 | 8659 | 9572 | 2173 | Y | Y | Y | 9 + | 10 | 2 | high | 9011 | 3 | 7619 | 7353 | 1961 | Y | Y | Y | 10 + | 50 | 2 | low | 9284 | 0 | 9075 | 8005 | 1797 | Y | Y | Y | 11 + | 50 | 2 | medium | 9135 | 2 | 8042 | 7835 | 1648 | Y | Y | Y | 12 + | 50 | 2 | high | 7639 | 7 | 9132 | 8269 | 1813 | Y | Y | Y | 13 + | 200 | 2 | low | 8995 | 1 | 9349 | 10067 | 3330 | Y | Y | Y | 14 + | 200 | 2 | medium | 9704 | 5 | 8768 | 9682 | 2848 | Y | Y | Y | 15 + | 200 | 2 | high | 8738 | 15 | 9755 | 8945 | 2962 | Y | Y | Y | 16 + 17 + ### Legend 18 + 19 + - **1-git**: Plain git 3-way merge 20 + - **2-diff**: git-yrs-merge in diff-only mode 21 + - **3-sidecar**: git-yrs-merge with .yrs/ sidecars 22 + - **4-yrs**: Yrs CRDT merge (simulated, no network) 23 + - **ok**: merge completed successfully (Y/N) 24 + - **conflicts**: number of files with conflict markers (strategy 1 only)
+37
bench-results/v5-real-conflicts/default-pds/results.csv
··· 1 + files,conflict_rate,collaborators,edits,strategy,time_ms,conflicts,success 2 + 10,low,2,5,1-plain-git,11455,0,true 3 + 10,low,2,5,2-yrs-diff,8282,0,true 4 + 10,low,2,5,3-yrs-sidecar,7247,0,true 5 + 10,low,2,5,4-yrs-on-pds,1960,0,true 6 + 10,medium,2,5,1-plain-git,8885,1,false 7 + 10,medium,2,5,2-yrs-diff,8659,0,true 8 + 10,medium,2,5,3-yrs-sidecar,9572,0,true 9 + 10,medium,2,5,4-yrs-on-pds,2173,0,true 10 + 10,high,2,5,1-plain-git,9011,3,false 11 + 10,high,2,5,2-yrs-diff,7619,0,true 12 + 10,high,2,5,3-yrs-sidecar,7353,0,true 13 + 10,high,2,5,4-yrs-on-pds,1961,0,true 14 + 50,low,2,10,1-plain-git,9284,0,true 15 + 50,low,2,10,2-yrs-diff,9075,0,true 16 + 50,low,2,10,3-yrs-sidecar,8005,0,true 17 + 50,low,2,10,4-yrs-on-pds,1797,0,true 18 + 50,medium,2,10,1-plain-git,9135,2,false 19 + 50,medium,2,10,2-yrs-diff,8042,0,true 20 + 50,medium,2,10,3-yrs-sidecar,7835,0,true 21 + 50,medium,2,10,4-yrs-on-pds,1648,0,true 22 + 50,high,2,10,1-plain-git,7639,7,false 23 + 50,high,2,10,2-yrs-diff,9132,0,true 24 + 50,high,2,10,3-yrs-sidecar,8269,0,true 25 + 50,high,2,10,4-yrs-on-pds,1813,0,true 26 + 200,low,2,20,1-plain-git,8995,1,false 27 + 200,low,2,20,2-yrs-diff,9349,0,true 28 + 200,low,2,20,3-yrs-sidecar,10067,0,true 29 + 200,low,2,20,4-yrs-on-pds,3330,0,true 30 + 200,medium,2,20,1-plain-git,9704,5,false 31 + 200,medium,2,20,2-yrs-diff,8768,0,true 32 + 200,medium,2,20,3-yrs-sidecar,9682,0,true 33 + 200,medium,2,20,4-yrs-on-pds,2848,0,true 34 + 200,high,2,20,1-plain-git,8738,15,false 35 + 200,high,2,20,2-yrs-diff,9755,0,true 36 + 200,high,2,20,3-yrs-sidecar,8945,0,true 37 + 200,high,2,20,4-yrs-on-pds,2962,0,true
+371
bench-results/v5-real-conflicts/default-pds/results.json
··· 1 + [ 2 + { 3 + "file_count": 10, 4 + "avg_file_size": 1000, 5 + "collaborators": 2, 6 + "edits_per_branch": 5, 7 + "conflict_rate": "low", 8 + "results": [ 9 + { 10 + "strategy": "1-plain-git", 11 + "merge_time_ms": 11455, 12 + "conflicts_reported": 0, 13 + "files_processed": 10, 14 + "success": true, 15 + "error": null 16 + }, 17 + { 18 + "strategy": "2-yrs-diff", 19 + "merge_time_ms": 8282, 20 + "conflicts_reported": 0, 21 + "files_processed": 37, 22 + "success": true, 23 + "error": null 24 + }, 25 + { 26 + "strategy": "3-yrs-sidecar", 27 + "merge_time_ms": 7247, 28 + "conflicts_reported": 0, 29 + "files_processed": 36, 30 + "success": true, 31 + "error": null 32 + }, 33 + { 34 + "strategy": "4-yrs-on-pds", 35 + "merge_time_ms": 1960, 36 + "conflicts_reported": 0, 37 + "files_processed": 10, 38 + "success": true, 39 + "error": null 40 + } 41 + ] 42 + }, 43 + { 44 + "file_count": 10, 45 + "avg_file_size": 1000, 46 + "collaborators": 2, 47 + "edits_per_branch": 5, 48 + "conflict_rate": "medium", 49 + "results": [ 50 + { 51 + "strategy": "1-plain-git", 52 + "merge_time_ms": 8885, 53 + "conflicts_reported": 1, 54 + "files_processed": 12, 55 + "success": false, 56 + "error": "" 57 + }, 58 + { 59 + "strategy": "2-yrs-diff", 60 + "merge_time_ms": 8659, 61 + "conflicts_reported": 0, 62 + "files_processed": 39, 63 + "success": true, 64 + "error": null 65 + }, 66 + { 67 + "strategy": "3-yrs-sidecar", 68 + "merge_time_ms": 9572, 69 + "conflicts_reported": 0, 70 + "files_processed": 39, 71 + "success": true, 72 + "error": null 73 + }, 74 + { 75 + "strategy": "4-yrs-on-pds", 76 + "merge_time_ms": 2173, 77 + "conflicts_reported": 0, 78 + "files_processed": 10, 79 + "success": true, 80 + "error": null 81 + } 82 + ] 83 + }, 84 + { 85 + "file_count": 10, 86 + "avg_file_size": 1000, 87 + "collaborators": 2, 88 + "edits_per_branch": 5, 89 + "conflict_rate": "high", 90 + "results": [ 91 + { 92 + "strategy": "1-plain-git", 93 + "merge_time_ms": 9011, 94 + "conflicts_reported": 3, 95 + "files_processed": 16, 96 + "success": false, 97 + "error": "" 98 + }, 99 + { 100 + "strategy": "2-yrs-diff", 101 + "merge_time_ms": 7619, 102 + "conflicts_reported": 0, 103 + "files_processed": 38, 104 + "success": true, 105 + "error": null 106 + }, 107 + { 108 + "strategy": "3-yrs-sidecar", 109 + "merge_time_ms": 7353, 110 + "conflicts_reported": 0, 111 + "files_processed": 40, 112 + "success": true, 113 + "error": null 114 + }, 115 + { 116 + "strategy": "4-yrs-on-pds", 117 + "merge_time_ms": 1961, 118 + "conflicts_reported": 0, 119 + "files_processed": 10, 120 + "success": true, 121 + "error": null 122 + } 123 + ] 124 + }, 125 + { 126 + "file_count": 50, 127 + "avg_file_size": 1000, 128 + "collaborators": 2, 129 + "edits_per_branch": 10, 130 + "conflict_rate": "low", 131 + "results": [ 132 + { 133 + "strategy": "1-plain-git", 134 + "merge_time_ms": 9284, 135 + "conflicts_reported": 0, 136 + "files_processed": 50, 137 + "success": true, 138 + "error": null 139 + }, 140 + { 141 + "strategy": "2-yrs-diff", 142 + "merge_time_ms": 9075, 143 + "conflicts_reported": 0, 144 + "files_processed": 166, 145 + "success": true, 146 + "error": null 147 + }, 148 + { 149 + "strategy": "3-yrs-sidecar", 150 + "merge_time_ms": 8005, 151 + "conflicts_reported": 0, 152 + "files_processed": 169, 153 + "success": true, 154 + "error": null 155 + }, 156 + { 157 + "strategy": "4-yrs-on-pds", 158 + "merge_time_ms": 1797, 159 + "conflicts_reported": 0, 160 + "files_processed": 50, 161 + "success": true, 162 + "error": null 163 + } 164 + ] 165 + }, 166 + { 167 + "file_count": 50, 168 + "avg_file_size": 1000, 169 + "collaborators": 2, 170 + "edits_per_branch": 10, 171 + "conflict_rate": "medium", 172 + "results": [ 173 + { 174 + "strategy": "1-plain-git", 175 + "merge_time_ms": 9135, 176 + "conflicts_reported": 2, 177 + "files_processed": 54, 178 + "success": false, 179 + "error": "" 180 + }, 181 + { 182 + "strategy": "2-yrs-diff", 183 + "merge_time_ms": 8042, 184 + "conflicts_reported": 0, 185 + "files_processed": 167, 186 + "success": true, 187 + "error": null 188 + }, 189 + { 190 + "strategy": "3-yrs-sidecar", 191 + "merge_time_ms": 7835, 192 + "conflicts_reported": 0, 193 + "files_processed": 168, 194 + "success": true, 195 + "error": null 196 + }, 197 + { 198 + "strategy": "4-yrs-on-pds", 199 + "merge_time_ms": 1648, 200 + "conflicts_reported": 0, 201 + "files_processed": 50, 202 + "success": true, 203 + "error": null 204 + } 205 + ] 206 + }, 207 + { 208 + "file_count": 50, 209 + "avg_file_size": 1000, 210 + "collaborators": 2, 211 + "edits_per_branch": 10, 212 + "conflict_rate": "high", 213 + "results": [ 214 + { 215 + "strategy": "1-plain-git", 216 + "merge_time_ms": 7639, 217 + "conflicts_reported": 7, 218 + "files_processed": 64, 219 + "success": false, 220 + "error": "" 221 + }, 222 + { 223 + "strategy": "2-yrs-diff", 224 + "merge_time_ms": 9132, 225 + "conflicts_reported": 0, 226 + "files_processed": 170, 227 + "success": true, 228 + "error": null 229 + }, 230 + { 231 + "strategy": "3-yrs-sidecar", 232 + "merge_time_ms": 8269, 233 + "conflicts_reported": 0, 234 + "files_processed": 169, 235 + "success": true, 236 + "error": null 237 + }, 238 + { 239 + "strategy": "4-yrs-on-pds", 240 + "merge_time_ms": 1813, 241 + "conflicts_reported": 0, 242 + "files_processed": 50, 243 + "success": true, 244 + "error": null 245 + } 246 + ] 247 + }, 248 + { 249 + "file_count": 200, 250 + "avg_file_size": 1000, 251 + "collaborators": 2, 252 + "edits_per_branch": 20, 253 + "conflict_rate": "low", 254 + "results": [ 255 + { 256 + "strategy": "1-plain-git", 257 + "merge_time_ms": 8995, 258 + "conflicts_reported": 1, 259 + "files_processed": 202, 260 + "success": false, 261 + "error": "" 262 + }, 263 + { 264 + "strategy": "2-yrs-diff", 265 + "merge_time_ms": 9349, 266 + "conflicts_reported": 0, 267 + "files_processed": 637, 268 + "success": true, 269 + "error": null 270 + }, 271 + { 272 + "strategy": "3-yrs-sidecar", 273 + "merge_time_ms": 10067, 274 + "conflicts_reported": 0, 275 + "files_processed": 639, 276 + "success": true, 277 + "error": null 278 + }, 279 + { 280 + "strategy": "4-yrs-on-pds", 281 + "merge_time_ms": 3330, 282 + "conflicts_reported": 0, 283 + "files_processed": 200, 284 + "success": true, 285 + "error": null 286 + } 287 + ] 288 + }, 289 + { 290 + "file_count": 200, 291 + "avg_file_size": 1000, 292 + "collaborators": 2, 293 + "edits_per_branch": 20, 294 + "conflict_rate": "medium", 295 + "results": [ 296 + { 297 + "strategy": "1-plain-git", 298 + "merge_time_ms": 9704, 299 + "conflicts_reported": 5, 300 + "files_processed": 210, 301 + "success": false, 302 + "error": "" 303 + }, 304 + { 305 + "strategy": "2-yrs-diff", 306 + "merge_time_ms": 8768, 307 + "conflicts_reported": 0, 308 + "files_processed": 639, 309 + "success": true, 310 + "error": null 311 + }, 312 + { 313 + "strategy": "3-yrs-sidecar", 314 + "merge_time_ms": 9682, 315 + "conflicts_reported": 0, 316 + "files_processed": 637, 317 + "success": true, 318 + "error": null 319 + }, 320 + { 321 + "strategy": "4-yrs-on-pds", 322 + "merge_time_ms": 2848, 323 + "conflicts_reported": 0, 324 + "files_processed": 200, 325 + "success": true, 326 + "error": null 327 + } 328 + ] 329 + }, 330 + { 331 + "file_count": 200, 332 + "avg_file_size": 1000, 333 + "collaborators": 2, 334 + "edits_per_branch": 20, 335 + "conflict_rate": "high", 336 + "results": [ 337 + { 338 + "strategy": "1-plain-git", 339 + "merge_time_ms": 8738, 340 + "conflicts_reported": 15, 341 + "files_processed": 230, 342 + "success": false, 343 + "error": "" 344 + }, 345 + { 346 + "strategy": "2-yrs-diff", 347 + "merge_time_ms": 9755, 348 + "conflicts_reported": 0, 349 + "files_processed": 640, 350 + "success": true, 351 + "error": null 352 + }, 353 + { 354 + "strategy": "3-yrs-sidecar", 355 + "merge_time_ms": 8945, 356 + "conflicts_reported": 0, 357 + "files_processed": 641, 358 + "success": true, 359 + "error": null 360 + }, 361 + { 362 + "strategy": "4-yrs-on-pds", 363 + "merge_time_ms": 2962, 364 + "conflicts_reported": 0, 365 + "files_processed": 200, 366 + "success": true, 367 + "error": null 368 + } 369 + ] 370 + } 371 + ]
+18
bench-results/v5-real-conflicts/filesize-pds/report.md
··· 1 + # Merge Strategy Benchmark Results 2 + 3 + Generated: 2026-03-14T18:03:34.788950262+00:00 4 + 5 + | Files | Collabs | Conflict | 1-git (ms) | 1-conflicts | 2-diff (ms) | 3-sidecar (ms) | 4-yrs (ms) | 2-ok | 3-ok | 4-ok | 6 + |-------|---------|----------|-----------|-------------|-------------|----------------|------------|------|------|------| 7 + | 50 | 2 | medium | 7855 | 2 | 9448 | 9503 | 2023 | Y | Y | Y | 8 + | 50 | 2 | medium | 9031 | 2 | 9374 | 8918 | 2390 | Y | Y | Y | 9 + | 50 | 2 | medium | 9580 | 2 | 9417 | 9809 | 4272 | Y | Y | Y | 10 + 11 + ### Legend 12 + 13 + - **1-git**: Plain git 3-way merge 14 + - **2-diff**: git-yrs-merge in diff-only mode 15 + - **3-sidecar**: git-yrs-merge with .yrs/ sidecars 16 + - **4-yrs**: Yrs CRDT merge (simulated, no network) 17 + - **ok**: merge completed successfully (Y/N) 18 + - **conflicts**: number of files with conflict markers (strategy 1 only)
+13
bench-results/v5-real-conflicts/filesize-pds/results.csv
··· 1 + files,conflict_rate,collaborators,edits,strategy,time_ms,conflicts,success 2 + 50,medium,2,10,1-plain-git,7855,2,false 3 + 50,medium,2,10,2-yrs-diff,9448,0,true 4 + 50,medium,2,10,3-yrs-sidecar,9503,0,true 5 + 50,medium,2,10,4-yrs-on-pds,2023,0,true 6 + 50,medium,2,10,1-plain-git,9031,2,false 7 + 50,medium,2,10,2-yrs-diff,9374,0,true 8 + 50,medium,2,10,3-yrs-sidecar,8918,0,true 9 + 50,medium,2,10,4-yrs-on-pds,2390,0,true 10 + 50,medium,2,10,1-plain-git,9580,2,false 11 + 50,medium,2,10,2-yrs-diff,9417,0,true 12 + 50,medium,2,10,3-yrs-sidecar,9809,0,true 13 + 50,medium,2,10,4-yrs-on-pds,4272,0,true
+125
bench-results/v5-real-conflicts/filesize-pds/results.json
··· 1 + [ 2 + { 3 + "file_count": 50, 4 + "avg_file_size": 1000, 5 + "collaborators": 2, 6 + "edits_per_branch": 10, 7 + "conflict_rate": "medium", 8 + "results": [ 9 + { 10 + "strategy": "1-plain-git", 11 + "merge_time_ms": 7855, 12 + "conflicts_reported": 2, 13 + "files_processed": 54, 14 + "success": false, 15 + "error": "" 16 + }, 17 + { 18 + "strategy": "2-yrs-diff", 19 + "merge_time_ms": 9448, 20 + "conflicts_reported": 0, 21 + "files_processed": 170, 22 + "success": true, 23 + "error": null 24 + }, 25 + { 26 + "strategy": "3-yrs-sidecar", 27 + "merge_time_ms": 9503, 28 + "conflicts_reported": 0, 29 + "files_processed": 170, 30 + "success": true, 31 + "error": null 32 + }, 33 + { 34 + "strategy": "4-yrs-on-pds", 35 + "merge_time_ms": 2023, 36 + "conflicts_reported": 0, 37 + "files_processed": 50, 38 + "success": true, 39 + "error": null 40 + } 41 + ] 42 + }, 43 + { 44 + "file_count": 50, 45 + "avg_file_size": 10000, 46 + "collaborators": 2, 47 + "edits_per_branch": 10, 48 + "conflict_rate": "medium", 49 + "results": [ 50 + { 51 + "strategy": "1-plain-git", 52 + "merge_time_ms": 9031, 53 + "conflicts_reported": 2, 54 + "files_processed": 54, 55 + "success": false, 56 + "error": "" 57 + }, 58 + { 59 + "strategy": "2-yrs-diff", 60 + "merge_time_ms": 9374, 61 + "conflicts_reported": 0, 62 + "files_processed": 169, 63 + "success": true, 64 + "error": null 65 + }, 66 + { 67 + "strategy": "3-yrs-sidecar", 68 + "merge_time_ms": 8918, 69 + "conflicts_reported": 0, 70 + "files_processed": 170, 71 + "success": true, 72 + "error": null 73 + }, 74 + { 75 + "strategy": "4-yrs-on-pds", 76 + "merge_time_ms": 2390, 77 + "conflicts_reported": 0, 78 + "files_processed": 50, 79 + "success": true, 80 + "error": null 81 + } 82 + ] 83 + }, 84 + { 85 + "file_count": 50, 86 + "avg_file_size": 50000, 87 + "collaborators": 2, 88 + "edits_per_branch": 10, 89 + "conflict_rate": "medium", 90 + "results": [ 91 + { 92 + "strategy": "1-plain-git", 93 + "merge_time_ms": 9580, 94 + "conflicts_reported": 2, 95 + "files_processed": 54, 96 + "success": false, 97 + "error": "" 98 + }, 99 + { 100 + "strategy": "2-yrs-diff", 101 + "merge_time_ms": 9417, 102 + "conflicts_reported": 0, 103 + "files_processed": 171, 104 + "success": true, 105 + "error": null 106 + }, 107 + { 108 + "strategy": "3-yrs-sidecar", 109 + "merge_time_ms": 9809, 110 + "conflicts_reported": 0, 111 + "files_processed": 168, 112 + "success": true, 113 + "error": null 114 + }, 115 + { 116 + "strategy": "4-yrs-on-pds", 117 + "merge_time_ms": 4272, 118 + "conflicts_reported": 0, 119 + "files_processed": 50, 120 + "success": true, 121 + "error": null 122 + } 123 + ] 124 + } 125 + ]
+21
bench-results/v5-real-conflicts/multi-collab-pds/report.md
··· 1 + # Merge Strategy Benchmark Results 2 + 3 + Generated: 2026-03-14T18:08:56.460255614+00:00 4 + 5 + | Files | Collabs | Conflict | 1-git (ms) | 1-conflicts | 2-diff (ms) | 3-sidecar (ms) | 4-yrs (ms) | 2-ok | 3-ok | 4-ok | 6 + |-------|---------|----------|-----------|-------------|-------------|----------------|------------|------|------|------| 7 + | 50 | 5 | low | 13403 | 0 | 11880 | 12315 | 2241 | Y | Y | Y | 8 + | 200 | 5 | low | 11960 | 1 | 13983 | 14977 | 2799 | Y | Y | Y | 9 + | 50 | 5 | medium | 11425 | 2 | 12032 | 13206 | 1709 | Y | Y | Y | 10 + | 200 | 5 | medium | 11003 | 5 | 11485 | 12707 | 3213 | Y | Y | Y | 11 + | 50 | 5 | high | 12925 | 7 | 10859 | 14679 | 1786 | Y | Y | Y | 12 + | 200 | 5 | high | 11664 | 15 | 14440 | 14288 | 2835 | Y | Y | Y | 13 + 14 + ### Legend 15 + 16 + - **1-git**: Plain git 3-way merge 17 + - **2-diff**: git-yrs-merge in diff-only mode 18 + - **3-sidecar**: git-yrs-merge with .yrs/ sidecars 19 + - **4-yrs**: Yrs CRDT merge (simulated, no network) 20 + - **ok**: merge completed successfully (Y/N) 21 + - **conflicts**: number of files with conflict markers (strategy 1 only)
+25
bench-results/v5-real-conflicts/multi-collab-pds/results.csv
··· 1 + files,conflict_rate,collaborators,edits,strategy,time_ms,conflicts,success 2 + 50,low,5,10,1-plain-git,13403,0,true 3 + 50,low,5,10,2-yrs-diff,11880,0,true 4 + 50,low,5,10,3-yrs-sidecar,12315,0,true 5 + 50,low,5,10,4-yrs-on-pds,2241,0,true 6 + 200,low,5,20,1-plain-git,11960,1,false 7 + 200,low,5,20,2-yrs-diff,13983,0,true 8 + 200,low,5,20,3-yrs-sidecar,14977,0,true 9 + 200,low,5,20,4-yrs-on-pds,2799,0,true 10 + 50,medium,5,10,1-plain-git,11425,2,false 11 + 50,medium,5,10,2-yrs-diff,12032,0,true 12 + 50,medium,5,10,3-yrs-sidecar,13206,0,true 13 + 50,medium,5,10,4-yrs-on-pds,1709,0,true 14 + 200,medium,5,20,1-plain-git,11003,5,false 15 + 200,medium,5,20,2-yrs-diff,11485,0,true 16 + 200,medium,5,20,3-yrs-sidecar,12707,0,true 17 + 200,medium,5,20,4-yrs-on-pds,3213,0,true 18 + 50,high,5,10,1-plain-git,12925,7,false 19 + 50,high,5,10,2-yrs-diff,10859,0,true 20 + 50,high,5,10,3-yrs-sidecar,14679,0,true 21 + 50,high,5,10,4-yrs-on-pds,1786,0,true 22 + 200,high,5,20,1-plain-git,11664,15,false 23 + 200,high,5,20,2-yrs-diff,14440,0,true 24 + 200,high,5,20,3-yrs-sidecar,14288,0,true 25 + 200,high,5,20,4-yrs-on-pds,2835,0,true
+248
bench-results/v5-real-conflicts/multi-collab-pds/results.json
··· 1 + [ 2 + { 3 + "file_count": 50, 4 + "avg_file_size": 1000, 5 + "collaborators": 5, 6 + "edits_per_branch": 10, 7 + "conflict_rate": "low", 8 + "results": [ 9 + { 10 + "strategy": "1-plain-git", 11 + "merge_time_ms": 13403, 12 + "conflicts_reported": 0, 13 + "files_processed": 50, 14 + "success": true, 15 + "error": null 16 + }, 17 + { 18 + "strategy": "2-yrs-diff", 19 + "merge_time_ms": 11880, 20 + "conflicts_reported": 0, 21 + "files_processed": 183, 22 + "success": true, 23 + "error": null 24 + }, 25 + { 26 + "strategy": "3-yrs-sidecar", 27 + "merge_time_ms": 12315, 28 + "conflicts_reported": 0, 29 + "files_processed": 183, 30 + "success": true, 31 + "error": null 32 + }, 33 + { 34 + "strategy": "4-yrs-on-pds", 35 + "merge_time_ms": 2241, 36 + "conflicts_reported": 0, 37 + "files_processed": 50, 38 + "success": true, 39 + "error": null 40 + } 41 + ] 42 + }, 43 + { 44 + "file_count": 200, 45 + "avg_file_size": 1000, 46 + "collaborators": 5, 47 + "edits_per_branch": 20, 48 + "conflict_rate": "low", 49 + "results": [ 50 + { 51 + "strategy": "1-plain-git", 52 + "merge_time_ms": 11960, 53 + "conflicts_reported": 1, 54 + "files_processed": 202, 55 + "success": false, 56 + "error": "" 57 + }, 58 + { 59 + "strategy": "2-yrs-diff", 60 + "merge_time_ms": 13983, 61 + "conflicts_reported": 0, 62 + "files_processed": 687, 63 + "success": true, 64 + "error": null 65 + }, 66 + { 67 + "strategy": "3-yrs-sidecar", 68 + "merge_time_ms": 14977, 69 + "conflicts_reported": 0, 70 + "files_processed": 680, 71 + "success": true, 72 + "error": null 73 + }, 74 + { 75 + "strategy": "4-yrs-on-pds", 76 + "merge_time_ms": 2799, 77 + "conflicts_reported": 0, 78 + "files_processed": 200, 79 + "success": true, 80 + "error": null 81 + } 82 + ] 83 + }, 84 + { 85 + "file_count": 50, 86 + "avg_file_size": 1000, 87 + "collaborators": 5, 88 + "edits_per_branch": 10, 89 + "conflict_rate": "medium", 90 + "results": [ 91 + { 92 + "strategy": "1-plain-git", 93 + "merge_time_ms": 11425, 94 + "conflicts_reported": 2, 95 + "files_processed": 54, 96 + "success": false, 97 + "error": "" 98 + }, 99 + { 100 + "strategy": "2-yrs-diff", 101 + "merge_time_ms": 12032, 102 + "conflicts_reported": 0, 103 + "files_processed": 190, 104 + "success": true, 105 + "error": null 106 + }, 107 + { 108 + "strategy": "3-yrs-sidecar", 109 + "merge_time_ms": 13206, 110 + "conflicts_reported": 0, 111 + "files_processed": 189, 112 + "success": true, 113 + "error": null 114 + }, 115 + { 116 + "strategy": "4-yrs-on-pds", 117 + "merge_time_ms": 1709, 118 + "conflicts_reported": 0, 119 + "files_processed": 50, 120 + "success": true, 121 + "error": null 122 + } 123 + ] 124 + }, 125 + { 126 + "file_count": 200, 127 + "avg_file_size": 1000, 128 + "collaborators": 5, 129 + "edits_per_branch": 20, 130 + "conflict_rate": "medium", 131 + "results": [ 132 + { 133 + "strategy": "1-plain-git", 134 + "merge_time_ms": 11003, 135 + "conflicts_reported": 5, 136 + "files_processed": 210, 137 + "success": false, 138 + "error": "" 139 + }, 140 + { 141 + "strategy": "2-yrs-diff", 142 + "merge_time_ms": 11485, 143 + "conflicts_reported": 0, 144 + "files_processed": 688, 145 + "success": true, 146 + "error": null 147 + }, 148 + { 149 + "strategy": "3-yrs-sidecar", 150 + "merge_time_ms": 12707, 151 + "conflicts_reported": 0, 152 + "files_processed": 690, 153 + "success": true, 154 + "error": null 155 + }, 156 + { 157 + "strategy": "4-yrs-on-pds", 158 + "merge_time_ms": 3213, 159 + "conflicts_reported": 0, 160 + "files_processed": 200, 161 + "success": true, 162 + "error": null 163 + } 164 + ] 165 + }, 166 + { 167 + "file_count": 50, 168 + "avg_file_size": 1000, 169 + "collaborators": 5, 170 + "edits_per_branch": 10, 171 + "conflict_rate": "high", 172 + "results": [ 173 + { 174 + "strategy": "1-plain-git", 175 + "merge_time_ms": 12925, 176 + "conflicts_reported": 7, 177 + "files_processed": 64, 178 + "success": false, 179 + "error": "" 180 + }, 181 + { 182 + "strategy": "2-yrs-diff", 183 + "merge_time_ms": 10859, 184 + "conflicts_reported": 0, 185 + "files_processed": 199, 186 + "success": true, 187 + "error": null 188 + }, 189 + { 190 + "strategy": "3-yrs-sidecar", 191 + "merge_time_ms": 14679, 192 + "conflicts_reported": 0, 193 + "files_processed": 199, 194 + "success": true, 195 + "error": null 196 + }, 197 + { 198 + "strategy": "4-yrs-on-pds", 199 + "merge_time_ms": 1786, 200 + "conflicts_reported": 0, 201 + "files_processed": 50, 202 + "success": true, 203 + "error": null 204 + } 205 + ] 206 + }, 207 + { 208 + "file_count": 200, 209 + "avg_file_size": 1000, 210 + "collaborators": 5, 211 + "edits_per_branch": 20, 212 + "conflict_rate": "high", 213 + "results": [ 214 + { 215 + "strategy": "1-plain-git", 216 + "merge_time_ms": 11664, 217 + "conflicts_reported": 15, 218 + "files_processed": 230, 219 + "success": false, 220 + "error": "" 221 + }, 222 + { 223 + "strategy": "2-yrs-diff", 224 + "merge_time_ms": 14440, 225 + "conflicts_reported": 0, 226 + "files_processed": 697, 227 + "success": true, 228 + "error": null 229 + }, 230 + { 231 + "strategy": "3-yrs-sidecar", 232 + "merge_time_ms": 14288, 233 + "conflicts_reported": 0, 234 + "files_processed": 697, 235 + "success": true, 236 + "error": null 237 + }, 238 + { 239 + "strategy": "4-yrs-on-pds", 240 + "merge_time_ms": 2835, 241 + "conflicts_reported": 0, 242 + "files_processed": 200, 243 + "success": true, 244 + "error": null 245 + } 246 + ] 247 + } 248 + ]
+161
bench-results/v5-real-conflicts/report.md
··· 1 + # v5-real-conflicts Benchmark Report 2 + 3 + **Date**: 2026-03-14 4 + **Code version**: v4 index-blob + fixed conflict generation 5 + **PDS**: bluesky-pds.t1cc.commoninternet.net 6 + **Run mode**: All suites run sequentially (no parallel contamination) 7 + 8 + ## What changed in v5 9 + 10 + The conflict generator was fixed so that medium/high overlap rates produce real git merge conflicts. 11 + Previously, overlapping edits used random file selection and random edit positions, so two 12 + collaborators rarely touched the same line even when targeting the same file pool. 13 + 14 + **Fix**: Overlapping edits now use: 15 + 1. **Deterministic file selection** (same as guaranteed mode) so all collaborators target the same files 16 + 2. **`apply_conflicting_edit`** which rewrites the same line, guaranteeing a git 3-way conflict 17 + 18 + Non-overlapping edits remain random. This makes conflict counts proportional to overlap rate. 19 + 20 + ## Strategy Legend 21 + 22 + | # | Strategy | Description | 23 + |---|----------|-------------| 24 + | 1 | plain-git | Standard `git merge` 3-way via PDS | 25 + | 2 | yrs-diff | git merge + git-yrs-merge CRDT driver (diff-only, no sidecars) | 26 + | 3 | yrs-sidecar | git merge + git-yrs-merge CRDT driver (with .yrs/ sidecar files) | 27 + | 4 | yrs-on-pds | pds-yrs: Yrs CRDT merge via ATProto (no git) | 28 + 29 + --- 30 + 31 + ## 1. Default (10/50/200 files x low/medium/high conflict, 2 collaborators) 32 + 33 + | Files | Conflict | 1-git (ms) | 1-conflicts | 2-diff (ms) | 3-sidecar (ms) | 4-yrs (ms) | 34 + |-------|----------|-----------|-------------|-------------|----------------|------------| 35 + | 10 | low | 11455 | 0 | 8282 | 7247 | **1960** | 36 + | 10 | medium | 8885 | 1 | 8659 | 9572 | **2173** | 37 + | 10 | high | 9011 | 3 | 7619 | 7353 | **1961** | 38 + | 50 | low | 9284 | 0 | 9075 | 8005 | **1797** | 39 + | 50 | medium | 9135 | 2 | 8042 | 7835 | **1648** | 40 + | 50 | high | 7639 | 7 | 9132 | 8269 | **1813** | 41 + | 200 | low | 8995 | 1 | 9349 | 10067 | **3330** | 42 + | 200 | medium | 9704 | 5 | 8768 | 9682 | **2848** | 43 + | 200 | high | 8738 | 15 | 9755 | 8945 | **2962** | 44 + 45 + **Key findings:** 46 + - Strategy 4 is **3-5x faster** than all git strategies across the board (10-200 files). 47 + - Plain git fails in 7/9 scenarios (only low-conflict at 10 and 50 files succeed). 48 + - Conflict count scales as expected: 200 files x high = 15 conflicts. 49 + - Git-based CRDT strategies (2, 3) are 8-10s regardless of conflict rate — network dominates. 50 + 51 + --- 52 + 53 + ## 2. Stress (1000 files, 50 edits/branch, 2 collaborators) 54 + 55 + | Conflict | 1-git (ms) | 1-conflicts | 2-diff (ms) | 3-sidecar (ms) | 4-yrs (ms) | 56 + |----------|-----------|-------------|-------------|----------------|------------| 57 + | low | 10068 | 2 | 10868 | 10288 | 23525 | 58 + | medium | 10812 | **12** | 12004 | 9339 | 23203 | 59 + | high | 9538 | **37** | 11901 | 12355 | 22852 | 60 + 61 + **Key findings:** 62 + - At 1000 files, git strategies (~10s) are **~2x faster** than pds-yrs (~23s). 63 + - Plain git fails all 3 scenarios (2-37 conflicts). 64 + - Strategy 4 time is stable (~23s) regardless of conflict count — CRDT merge cost is negligible vs network I/O. 65 + - No 413 Payload Too Large errors — index-blob approach keeps records small. 66 + 67 + --- 68 + 69 + ## 3. Guaranteed Conflict (100% same-line overlap, 2 collaborators) 70 + 71 + | Files | 1-git (ms) | 1-conflicts | 2-diff (ms) | 3-sidecar (ms) | 4-yrs (ms) | 72 + |-------|-----------|-------------|-------------|----------------|------------| 73 + | 10 | 8299 | **10** | 9511 | **7664** | **1823** | 74 + | 50 | 9684 | **20** | 9249 | **8714** | **1951** | 75 + | 200 | 10162 | **20** | 9485 | **9647** | **3144** | 76 + 77 + **Key findings:** 78 + - Plain git fails every scenario with maximum conflicts (10-20 files). 79 + - Strategy 3 (sidecar) is faster than strategy 2 (diff-only) at 10 and 50 files — the .yrs/ sidecars enable direct CRDT resolution without recomputing diffs. 80 + - Strategy 4 remains 3-5x faster than any git-based approach. 81 + 82 + --- 83 + 84 + ## 4. File Size Sweep (50 files, medium conflict, 2 collaborators) 85 + 86 + | Avg Size | 1-git (ms) | 1-conflicts | 2-diff (ms) | 3-sidecar (ms) | 4-yrs (ms) | 87 + |----------|-----------|-------------|-------------|----------------|------------| 88 + | 1 KB | 7855 | 2 | 9448 | 9503 | **2023** | 89 + | 10 KB | 9031 | 2 | 9374 | 8918 | **2390** | 90 + | 50 KB | 9580 | 2 | 9417 | 9809 | **4272** | 91 + 92 + **Key findings:** 93 + - Conflict count is stable (2) regardless of file size — expected since edits target the same line. 94 + - Git strategies are insensitive to file size (~8-10s) — packfile compression handles it. 95 + - Strategy 4 scales linearly: 2.0s at 1KB, 2.4s at 10KB, 4.3s at 50KB. 96 + - Strategy 4 is faster at all sizes, but the gap narrows from 4x at 1KB to 2x at 50KB. 97 + 98 + --- 99 + 100 + ## 5. Multi-Collaborator (5 collaborators, 50/200 files) 101 + 102 + | Files | Conflict | 1-git (ms) | 1-conflicts | 2-diff (ms) | 3-sidecar (ms) | 4-yrs (ms) | 103 + |-------|----------|-----------|-------------|-------------|----------------|------------| 104 + | 50 | low | 13403 | 0 | 11880 | 12315 | **2241** | 105 + | 200 | low | 11960 | 1 | 13983 | 14977 | **2799** | 106 + | 50 | medium | 11425 | 2 | 12032 | 13206 | **1709** | 107 + | 200 | medium | 11003 | 5 | 11485 | 12707 | **3213** | 108 + | 50 | high | 12925 | 7 | 10859 | 14679 | **1786** | 109 + | 200 | high | 11664 | 15 | 14440 | 14288 | **2835** | 110 + 111 + **Key findings:** 112 + - With 5 collaborators, git strategies jump to ~11-15s (more branches to push/clone/merge). 113 + - Strategy 4 stays at 2-3s — **5-7x faster** than git at 50 files, **4-5x faster** at 200 files. 114 + - Plain git fails 5/6 scenarios. 115 + - The multi-collab scenario is where strategy 4 shines most: pds-yrs saves each collaborator independently (O(collaborators) saves), but git must push/clone all branches serially. 116 + 117 + --- 118 + 119 + ## Summary Tables 120 + 121 + ### Speed: Strategy 4 (pds-yrs) vs fastest git strategy 122 + 123 + | Scenario | Git best (ms) | 4-yrs (ms) | Ratio | 124 + |----------|--------------|------------|-------| 125 + | 10 files, 2 collab | ~7600 | ~1900 | **4x faster** | 126 + | 50 files, 2 collab | ~7600 | ~1750 | **4.3x faster** | 127 + | 200 files, 2 collab | ~8700 | ~3000 | **2.9x faster** | 128 + | 1000 files, 2 collab | ~9500 | ~23000 | 2.4x slower | 129 + | 50 files, 5 collab | ~10800 | ~1900 | **5.7x faster** | 130 + | 200 files, 5 collab | ~11000 | ~2900 | **3.8x faster** | 131 + 132 + ### Conflict resolution across all scenarios 133 + 134 + | Strategy | Scenarios run | Failed (conflicts) | Success rate | 135 + |----------|-------------|-------------------|-------------| 136 + | 1-git | 24 | 17 | **29%** | 137 + | 2-diff | 24 | 0 | **100%** | 138 + | 3-sidecar | 24 | 0 | **100%** | 139 + | 4-yrs | 24 | 0 | **100%** | 140 + 141 + ### Strategy 2 vs 3 in high-conflict scenarios 142 + 143 + | Scenario | 2-diff (ms) | 3-sidecar (ms) | Winner | 144 + |----------|------------|----------------|--------| 145 + | 10 files, guaranteed | 9511 | **7664** | sidecar | 146 + | 50 files, guaranteed | 9249 | **8714** | sidecar | 147 + | 200 files, guaranteed | **9485** | 9647 | diff | 148 + | 50 files, 5 collab, high | **10859** | 14679 | diff | 149 + | 200 files, 5 collab, high | **14440** | 14288 | ~tied | 150 + 151 + Sidecar wins at small file counts with many conflicts (CRDT state avoids recomputing diffs). 152 + Diff-only wins at larger scales where the .yrs/ file overhead outweighs the resolution benefit. 153 + 154 + ### Where each strategy is best 155 + 156 + | Strategy | Best at | Why | 157 + |----------|---------|-----| 158 + | 1-git | N/A | Fails too often (29% success) to be practical | 159 + | 2-diff | Large repos with few conflicts | Lighter than sidecar, no extra files to push | 160 + | 3-sidecar | Small repos with many conflicts | Pre-computed CRDT state enables faster resolution | 161 + | 4-yrs | Everything except 1000+ files | No git overhead, no push/clone, direct CRDT merge |
+18
bench-results/v5-real-conflicts/stress-pds/report.md
··· 1 + # Merge Strategy Benchmark Results 2 + 3 + Generated: 2026-03-14T17:57:09.177032365+00:00 4 + 5 + | Files | Collabs | Conflict | 1-git (ms) | 1-conflicts | 2-diff (ms) | 3-sidecar (ms) | 4-yrs (ms) | 2-ok | 3-ok | 4-ok | 6 + |-------|---------|----------|-----------|-------------|-------------|----------------|------------|------|------|------| 7 + | 1000 | 2 | low | 10068 | 2 | 10868 | 10288 | 23525 | Y | Y | Y | 8 + | 1000 | 2 | medium | 10812 | 12 | 12004 | 9339 | 23203 | Y | Y | Y | 9 + | 1000 | 2 | high | 9538 | 37 | 11901 | 12355 | 22852 | Y | Y | Y | 10 + 11 + ### Legend 12 + 13 + - **1-git**: Plain git 3-way merge 14 + - **2-diff**: git-yrs-merge in diff-only mode 15 + - **3-sidecar**: git-yrs-merge with .yrs/ sidecars 16 + - **4-yrs**: Yrs CRDT merge (simulated, no network) 17 + - **ok**: merge completed successfully (Y/N) 18 + - **conflicts**: number of files with conflict markers (strategy 1 only)
+13
bench-results/v5-real-conflicts/stress-pds/results.csv
··· 1 + files,conflict_rate,collaborators,edits,strategy,time_ms,conflicts,success 2 + 1000,low,2,50,1-plain-git,10068,2,false 3 + 1000,low,2,50,2-yrs-diff,10868,0,true 4 + 1000,low,2,50,3-yrs-sidecar,10288,0,true 5 + 1000,low,2,50,4-yrs-on-pds,23525,0,true 6 + 1000,medium,2,50,1-plain-git,10812,12,false 7 + 1000,medium,2,50,2-yrs-diff,12004,0,true 8 + 1000,medium,2,50,3-yrs-sidecar,9339,0,true 9 + 1000,medium,2,50,4-yrs-on-pds,23203,0,true 10 + 1000,high,2,50,1-plain-git,9538,37,false 11 + 1000,high,2,50,2-yrs-diff,11901,0,true 12 + 1000,high,2,50,3-yrs-sidecar,12355,0,true 13 + 1000,high,2,50,4-yrs-on-pds,22852,0,true
+125
bench-results/v5-real-conflicts/stress-pds/results.json
··· 1 + [ 2 + { 3 + "file_count": 1000, 4 + "avg_file_size": 1000, 5 + "collaborators": 2, 6 + "edits_per_branch": 50, 7 + "conflict_rate": "low", 8 + "results": [ 9 + { 10 + "strategy": "1-plain-git", 11 + "merge_time_ms": 10068, 12 + "conflicts_reported": 2, 13 + "files_processed": 1004, 14 + "success": false, 15 + "error": "" 16 + }, 17 + { 18 + "strategy": "2-yrs-diff", 19 + "merge_time_ms": 10868, 20 + "conflicts_reported": 0, 21 + "files_processed": 3099, 22 + "success": true, 23 + "error": null 24 + }, 25 + { 26 + "strategy": "3-yrs-sidecar", 27 + "merge_time_ms": 10288, 28 + "conflicts_reported": 0, 29 + "files_processed": 3098, 30 + "success": true, 31 + "error": null 32 + }, 33 + { 34 + "strategy": "4-yrs-on-pds", 35 + "merge_time_ms": 23525, 36 + "conflicts_reported": 0, 37 + "files_processed": 1000, 38 + "success": true, 39 + "error": null 40 + } 41 + ] 42 + }, 43 + { 44 + "file_count": 1000, 45 + "avg_file_size": 1000, 46 + "collaborators": 2, 47 + "edits_per_branch": 50, 48 + "conflict_rate": "medium", 49 + "results": [ 50 + { 51 + "strategy": "1-plain-git", 52 + "merge_time_ms": 10812, 53 + "conflicts_reported": 12, 54 + "files_processed": 1024, 55 + "success": false, 56 + "error": "" 57 + }, 58 + { 59 + "strategy": "2-yrs-diff", 60 + "merge_time_ms": 12004, 61 + "conflicts_reported": 0, 62 + "files_processed": 3099, 63 + "success": true, 64 + "error": null 65 + }, 66 + { 67 + "strategy": "3-yrs-sidecar", 68 + "merge_time_ms": 9339, 69 + "conflicts_reported": 0, 70 + "files_processed": 3101, 71 + "success": true, 72 + "error": null 73 + }, 74 + { 75 + "strategy": "4-yrs-on-pds", 76 + "merge_time_ms": 23203, 77 + "conflicts_reported": 0, 78 + "files_processed": 1000, 79 + "success": true, 80 + "error": null 81 + } 82 + ] 83 + }, 84 + { 85 + "file_count": 1000, 86 + "avg_file_size": 1000, 87 + "collaborators": 2, 88 + "edits_per_branch": 50, 89 + "conflict_rate": "high", 90 + "results": [ 91 + { 92 + "strategy": "1-plain-git", 93 + "merge_time_ms": 9538, 94 + "conflicts_reported": 37, 95 + "files_processed": 1074, 96 + "success": false, 97 + "error": "" 98 + }, 99 + { 100 + "strategy": "2-yrs-diff", 101 + "merge_time_ms": 11901, 102 + "conflicts_reported": 0, 103 + "files_processed": 3101, 104 + "success": true, 105 + "error": null 106 + }, 107 + { 108 + "strategy": "3-yrs-sidecar", 109 + "merge_time_ms": 12355, 110 + "conflicts_reported": 0, 111 + "files_processed": 3100, 112 + "success": true, 113 + "error": null 114 + }, 115 + { 116 + "strategy": "4-yrs-on-pds", 117 + "merge_time_ms": 22852, 118 + "conflicts_reported": 0, 119 + "files_processed": 1000, 120 + "success": true, 121 + "error": null 122 + } 123 + ] 124 + } 125 + ]
+24
bench-results/v6-refactor/default-pds/report.md
··· 1 + # Merge Strategy Benchmark Results 2 + 3 + Generated: 2026-03-14T20:42:29.752215582+00:00 4 + 5 + | Files | Collabs | Conflict | 1-git (ms) | 1-conflicts | 2-diff (ms) | 3-sidecar (ms) | 4-yrs (ms) | 2-ok | 3-ok | 4-ok | 6 + |-------|---------|----------|-----------|-------------|-------------|----------------|------------|------|------|------| 7 + | 10 | 2 | low | 7331 | 0 | 7408 | 9307 | 1544 | Y | Y | Y | 8 + | 10 | 2 | medium | 6384 | 1 | 7468 | 8372 | 1658 | Y | Y | Y | 9 + | 10 | 2 | high | 6744 | 3 | 8322 | 7036 | 1748 | Y | Y | Y | 10 + | 50 | 2 | low | 8144 | 0 | 7558 | 7748 | 1966 | Y | Y | Y | 11 + | 50 | 2 | medium | 8112 | 2 | 7447 | 6944 | 1501 | Y | Y | Y | 12 + | 50 | 2 | high | 7430 | 7 | 7910 | 7688 | 1629 | Y | Y | Y | 13 + | 200 | 2 | low | 6939 | 1 | 7365 | 7741 | 2832 | Y | Y | Y | 14 + | 200 | 2 | medium | 8077 | 5 | 7519 | 8375 | 3004 | Y | Y | Y | 15 + | 200 | 2 | high | 6940 | 15 | 7871 | 7809 | 2666 | Y | Y | Y | 16 + 17 + ### Legend 18 + 19 + - **1-git**: Plain git 3-way merge 20 + - **2-diff**: git-yrs-merge in diff-only mode 21 + - **3-sidecar**: git-yrs-merge with .yrs/ sidecars 22 + - **4-yrs**: Yrs CRDT merge (simulated, no network) 23 + - **ok**: merge completed successfully (Y/N) 24 + - **conflicts**: number of files with conflict markers (strategy 1 only)
+37
bench-results/v6-refactor/default-pds/results.csv
··· 1 + files,conflict_rate,collaborators,edits,strategy,time_ms,conflicts,success 2 + 10,low,2,5,1-plain-git,7331,0,true 3 + 10,low,2,5,2-yrs-diff,7408,0,true 4 + 10,low,2,5,3-yrs-sidecar,9307,0,true 5 + 10,low,2,5,4-yrs-on-pds,1544,0,true 6 + 10,medium,2,5,1-plain-git,6384,1,false 7 + 10,medium,2,5,2-yrs-diff,7468,0,true 8 + 10,medium,2,5,3-yrs-sidecar,8372,0,true 9 + 10,medium,2,5,4-yrs-on-pds,1658,0,true 10 + 10,high,2,5,1-plain-git,6744,3,false 11 + 10,high,2,5,2-yrs-diff,8322,0,true 12 + 10,high,2,5,3-yrs-sidecar,7036,0,true 13 + 10,high,2,5,4-yrs-on-pds,1748,0,true 14 + 50,low,2,10,1-plain-git,8144,0,true 15 + 50,low,2,10,2-yrs-diff,7558,0,true 16 + 50,low,2,10,3-yrs-sidecar,7748,0,true 17 + 50,low,2,10,4-yrs-on-pds,1966,0,true 18 + 50,medium,2,10,1-plain-git,8112,2,false 19 + 50,medium,2,10,2-yrs-diff,7447,0,true 20 + 50,medium,2,10,3-yrs-sidecar,6944,0,true 21 + 50,medium,2,10,4-yrs-on-pds,1501,0,true 22 + 50,high,2,10,1-plain-git,7430,7,false 23 + 50,high,2,10,2-yrs-diff,7910,0,true 24 + 50,high,2,10,3-yrs-sidecar,7688,0,true 25 + 50,high,2,10,4-yrs-on-pds,1629,0,true 26 + 200,low,2,20,1-plain-git,6939,1,false 27 + 200,low,2,20,2-yrs-diff,7365,0,true 28 + 200,low,2,20,3-yrs-sidecar,7741,0,true 29 + 200,low,2,20,4-yrs-on-pds,2832,0,true 30 + 200,medium,2,20,1-plain-git,8077,5,false 31 + 200,medium,2,20,2-yrs-diff,7519,0,true 32 + 200,medium,2,20,3-yrs-sidecar,8375,0,true 33 + 200,medium,2,20,4-yrs-on-pds,3004,0,true 34 + 200,high,2,20,1-plain-git,6940,15,false 35 + 200,high,2,20,2-yrs-diff,7871,0,true 36 + 200,high,2,20,3-yrs-sidecar,7809,0,true 37 + 200,high,2,20,4-yrs-on-pds,2666,0,true
+371
bench-results/v6-refactor/default-pds/results.json
··· 1 + [ 2 + { 3 + "file_count": 10, 4 + "avg_file_size": 1000, 5 + "collaborators": 2, 6 + "edits_per_branch": 5, 7 + "conflict_rate": "low", 8 + "results": [ 9 + { 10 + "strategy": "1-plain-git", 11 + "merge_time_ms": 7331, 12 + "conflicts_reported": 0, 13 + "files_processed": 10, 14 + "success": true, 15 + "error": null 16 + }, 17 + { 18 + "strategy": "2-yrs-diff", 19 + "merge_time_ms": 7408, 20 + "conflicts_reported": 0, 21 + "files_processed": 38, 22 + "success": true, 23 + "error": null 24 + }, 25 + { 26 + "strategy": "3-yrs-sidecar", 27 + "merge_time_ms": 9307, 28 + "conflicts_reported": 0, 29 + "files_processed": 39, 30 + "success": true, 31 + "error": null 32 + }, 33 + { 34 + "strategy": "4-yrs-on-pds", 35 + "merge_time_ms": 1544, 36 + "conflicts_reported": 0, 37 + "files_processed": 10, 38 + "success": true, 39 + "error": null 40 + } 41 + ] 42 + }, 43 + { 44 + "file_count": 10, 45 + "avg_file_size": 1000, 46 + "collaborators": 2, 47 + "edits_per_branch": 5, 48 + "conflict_rate": "medium", 49 + "results": [ 50 + { 51 + "strategy": "1-plain-git", 52 + "merge_time_ms": 6384, 53 + "conflicts_reported": 1, 54 + "files_processed": 12, 55 + "success": false, 56 + "error": "" 57 + }, 58 + { 59 + "strategy": "2-yrs-diff", 60 + "merge_time_ms": 7468, 61 + "conflicts_reported": 0, 62 + "files_processed": 38, 63 + "success": true, 64 + "error": null 65 + }, 66 + { 67 + "strategy": "3-yrs-sidecar", 68 + "merge_time_ms": 8372, 69 + "conflicts_reported": 0, 70 + "files_processed": 37, 71 + "success": true, 72 + "error": null 73 + }, 74 + { 75 + "strategy": "4-yrs-on-pds", 76 + "merge_time_ms": 1658, 77 + "conflicts_reported": 0, 78 + "files_processed": 10, 79 + "success": true, 80 + "error": null 81 + } 82 + ] 83 + }, 84 + { 85 + "file_count": 10, 86 + "avg_file_size": 1000, 87 + "collaborators": 2, 88 + "edits_per_branch": 5, 89 + "conflict_rate": "high", 90 + "results": [ 91 + { 92 + "strategy": "1-plain-git", 93 + "merge_time_ms": 6744, 94 + "conflicts_reported": 3, 95 + "files_processed": 16, 96 + "success": false, 97 + "error": "" 98 + }, 99 + { 100 + "strategy": "2-yrs-diff", 101 + "merge_time_ms": 8322, 102 + "conflicts_reported": 0, 103 + "files_processed": 40, 104 + "success": true, 105 + "error": null 106 + }, 107 + { 108 + "strategy": "3-yrs-sidecar", 109 + "merge_time_ms": 7036, 110 + "conflicts_reported": 0, 111 + "files_processed": 40, 112 + "success": true, 113 + "error": null 114 + }, 115 + { 116 + "strategy": "4-yrs-on-pds", 117 + "merge_time_ms": 1748, 118 + "conflicts_reported": 0, 119 + "files_processed": 10, 120 + "success": true, 121 + "error": null 122 + } 123 + ] 124 + }, 125 + { 126 + "file_count": 50, 127 + "avg_file_size": 1000, 128 + "collaborators": 2, 129 + "edits_per_branch": 10, 130 + "conflict_rate": "low", 131 + "results": [ 132 + { 133 + "strategy": "1-plain-git", 134 + "merge_time_ms": 8144, 135 + "conflicts_reported": 0, 136 + "files_processed": 50, 137 + "success": true, 138 + "error": null 139 + }, 140 + { 141 + "strategy": "2-yrs-diff", 142 + "merge_time_ms": 7558, 143 + "conflicts_reported": 0, 144 + "files_processed": 169, 145 + "success": true, 146 + "error": null 147 + }, 148 + { 149 + "strategy": "3-yrs-sidecar", 150 + "merge_time_ms": 7748, 151 + "conflicts_reported": 0, 152 + "files_processed": 167, 153 + "success": true, 154 + "error": null 155 + }, 156 + { 157 + "strategy": "4-yrs-on-pds", 158 + "merge_time_ms": 1966, 159 + "conflicts_reported": 0, 160 + "files_processed": 50, 161 + "success": true, 162 + "error": null 163 + } 164 + ] 165 + }, 166 + { 167 + "file_count": 50, 168 + "avg_file_size": 1000, 169 + "collaborators": 2, 170 + "edits_per_branch": 10, 171 + "conflict_rate": "medium", 172 + "results": [ 173 + { 174 + "strategy": "1-plain-git", 175 + "merge_time_ms": 8112, 176 + "conflicts_reported": 2, 177 + "files_processed": 54, 178 + "success": false, 179 + "error": "" 180 + }, 181 + { 182 + "strategy": "2-yrs-diff", 183 + "merge_time_ms": 7447, 184 + "conflicts_reported": 0, 185 + "files_processed": 167, 186 + "success": true, 187 + "error": null 188 + }, 189 + { 190 + "strategy": "3-yrs-sidecar", 191 + "merge_time_ms": 6944, 192 + "conflicts_reported": 0, 193 + "files_processed": 168, 194 + "success": true, 195 + "error": null 196 + }, 197 + { 198 + "strategy": "4-yrs-on-pds", 199 + "merge_time_ms": 1501, 200 + "conflicts_reported": 0, 201 + "files_processed": 50, 202 + "success": true, 203 + "error": null 204 + } 205 + ] 206 + }, 207 + { 208 + "file_count": 50, 209 + "avg_file_size": 1000, 210 + "collaborators": 2, 211 + "edits_per_branch": 10, 212 + "conflict_rate": "high", 213 + "results": [ 214 + { 215 + "strategy": "1-plain-git", 216 + "merge_time_ms": 7430, 217 + "conflicts_reported": 7, 218 + "files_processed": 64, 219 + "success": false, 220 + "error": "" 221 + }, 222 + { 223 + "strategy": "2-yrs-diff", 224 + "merge_time_ms": 7910, 225 + "conflicts_reported": 0, 226 + "files_processed": 171, 227 + "success": true, 228 + "error": null 229 + }, 230 + { 231 + "strategy": "3-yrs-sidecar", 232 + "merge_time_ms": 7688, 233 + "conflicts_reported": 0, 234 + "files_processed": 169, 235 + "success": true, 236 + "error": null 237 + }, 238 + { 239 + "strategy": "4-yrs-on-pds", 240 + "merge_time_ms": 1629, 241 + "conflicts_reported": 0, 242 + "files_processed": 50, 243 + "success": true, 244 + "error": null 245 + } 246 + ] 247 + }, 248 + { 249 + "file_count": 200, 250 + "avg_file_size": 1000, 251 + "collaborators": 2, 252 + "edits_per_branch": 20, 253 + "conflict_rate": "low", 254 + "results": [ 255 + { 256 + "strategy": "1-plain-git", 257 + "merge_time_ms": 6939, 258 + "conflicts_reported": 1, 259 + "files_processed": 202, 260 + "success": false, 261 + "error": "" 262 + }, 263 + { 264 + "strategy": "2-yrs-diff", 265 + "merge_time_ms": 7365, 266 + "conflicts_reported": 0, 267 + "files_processed": 637, 268 + "success": true, 269 + "error": null 270 + }, 271 + { 272 + "strategy": "3-yrs-sidecar", 273 + "merge_time_ms": 7741, 274 + "conflicts_reported": 0, 275 + "files_processed": 640, 276 + "success": true, 277 + "error": null 278 + }, 279 + { 280 + "strategy": "4-yrs-on-pds", 281 + "merge_time_ms": 2832, 282 + "conflicts_reported": 0, 283 + "files_processed": 200, 284 + "success": true, 285 + "error": null 286 + } 287 + ] 288 + }, 289 + { 290 + "file_count": 200, 291 + "avg_file_size": 1000, 292 + "collaborators": 2, 293 + "edits_per_branch": 20, 294 + "conflict_rate": "medium", 295 + "results": [ 296 + { 297 + "strategy": "1-plain-git", 298 + "merge_time_ms": 8077, 299 + "conflicts_reported": 5, 300 + "files_processed": 210, 301 + "success": false, 302 + "error": "" 303 + }, 304 + { 305 + "strategy": "2-yrs-diff", 306 + "merge_time_ms": 7519, 307 + "conflicts_reported": 0, 308 + "files_processed": 634, 309 + "success": true, 310 + "error": null 311 + }, 312 + { 313 + "strategy": "3-yrs-sidecar", 314 + "merge_time_ms": 8375, 315 + "conflicts_reported": 0, 316 + "files_processed": 639, 317 + "success": true, 318 + "error": null 319 + }, 320 + { 321 + "strategy": "4-yrs-on-pds", 322 + "merge_time_ms": 3004, 323 + "conflicts_reported": 0, 324 + "files_processed": 200, 325 + "success": true, 326 + "error": null 327 + } 328 + ] 329 + }, 330 + { 331 + "file_count": 200, 332 + "avg_file_size": 1000, 333 + "collaborators": 2, 334 + "edits_per_branch": 20, 335 + "conflict_rate": "high", 336 + "results": [ 337 + { 338 + "strategy": "1-plain-git", 339 + "merge_time_ms": 6940, 340 + "conflicts_reported": 15, 341 + "files_processed": 230, 342 + "success": false, 343 + "error": "" 344 + }, 345 + { 346 + "strategy": "2-yrs-diff", 347 + "merge_time_ms": 7871, 348 + "conflicts_reported": 0, 349 + "files_processed": 641, 350 + "success": true, 351 + "error": null 352 + }, 353 + { 354 + "strategy": "3-yrs-sidecar", 355 + "merge_time_ms": 7809, 356 + "conflicts_reported": 0, 357 + "files_processed": 640, 358 + "success": true, 359 + "error": null 360 + }, 361 + { 362 + "strategy": "4-yrs-on-pds", 363 + "merge_time_ms": 2666, 364 + "conflicts_reported": 0, 365 + "files_processed": 200, 366 + "success": true, 367 + "error": null 368 + } 369 + ] 370 + } 371 + ]
+18
bench-results/v6-refactor/stress-pds/report.md
··· 1 + # Merge Strategy Benchmark Results 2 + 3 + Generated: 2026-03-14T20:46:07.056198991+00:00 4 + 5 + | Files | Collabs | Conflict | 1-git (ms) | 1-conflicts | 2-diff (ms) | 3-sidecar (ms) | 4-yrs (ms) | 2-ok | 3-ok | 4-ok | 6 + |-------|---------|----------|-----------|-------------|-------------|----------------|------------|------|------|------| 7 + | 1000 | 2 | low | 8192 | 2 | 9252 | 9031 | 24791 | Y | Y | Y | 8 + | 1000 | 2 | medium | 8559 | 12 | 9742 | 10792 | 26336 | Y | Y | Y | 9 + | 1000 | 2 | high | 8326 | 37 | 11281 | 11917 | 26208 | Y | Y | Y | 10 + 11 + ### Legend 12 + 13 + - **1-git**: Plain git 3-way merge 14 + - **2-diff**: git-yrs-merge in diff-only mode 15 + - **3-sidecar**: git-yrs-merge with .yrs/ sidecars 16 + - **4-yrs**: Yrs CRDT merge (simulated, no network) 17 + - **ok**: merge completed successfully (Y/N) 18 + - **conflicts**: number of files with conflict markers (strategy 1 only)
+13
bench-results/v6-refactor/stress-pds/results.csv
··· 1 + files,conflict_rate,collaborators,edits,strategy,time_ms,conflicts,success 2 + 1000,low,2,50,1-plain-git,8192,2,false 3 + 1000,low,2,50,2-yrs-diff,9252,0,true 4 + 1000,low,2,50,3-yrs-sidecar,9031,0,true 5 + 1000,low,2,50,4-yrs-on-pds,24791,0,true 6 + 1000,medium,2,50,1-plain-git,8559,12,false 7 + 1000,medium,2,50,2-yrs-diff,9742,0,true 8 + 1000,medium,2,50,3-yrs-sidecar,10792,0,true 9 + 1000,medium,2,50,4-yrs-on-pds,26336,0,true 10 + 1000,high,2,50,1-plain-git,8326,37,false 11 + 1000,high,2,50,2-yrs-diff,11281,0,true 12 + 1000,high,2,50,3-yrs-sidecar,11917,0,true 13 + 1000,high,2,50,4-yrs-on-pds,26208,0,true
+125
bench-results/v6-refactor/stress-pds/results.json
··· 1 + [ 2 + { 3 + "file_count": 1000, 4 + "avg_file_size": 1000, 5 + "collaborators": 2, 6 + "edits_per_branch": 50, 7 + "conflict_rate": "low", 8 + "results": [ 9 + { 10 + "strategy": "1-plain-git", 11 + "merge_time_ms": 8192, 12 + "conflicts_reported": 2, 13 + "files_processed": 1004, 14 + "success": false, 15 + "error": "" 16 + }, 17 + { 18 + "strategy": "2-yrs-diff", 19 + "merge_time_ms": 9252, 20 + "conflicts_reported": 0, 21 + "files_processed": 3097, 22 + "success": true, 23 + "error": null 24 + }, 25 + { 26 + "strategy": "3-yrs-sidecar", 27 + "merge_time_ms": 9031, 28 + "conflicts_reported": 0, 29 + "files_processed": 3097, 30 + "success": true, 31 + "error": null 32 + }, 33 + { 34 + "strategy": "4-yrs-on-pds", 35 + "merge_time_ms": 24791, 36 + "conflicts_reported": 0, 37 + "files_processed": 1000, 38 + "success": true, 39 + "error": null 40 + } 41 + ] 42 + }, 43 + { 44 + "file_count": 1000, 45 + "avg_file_size": 1000, 46 + "collaborators": 2, 47 + "edits_per_branch": 50, 48 + "conflict_rate": "medium", 49 + "results": [ 50 + { 51 + "strategy": "1-plain-git", 52 + "merge_time_ms": 8559, 53 + "conflicts_reported": 12, 54 + "files_processed": 1024, 55 + "success": false, 56 + "error": "" 57 + }, 58 + { 59 + "strategy": "2-yrs-diff", 60 + "merge_time_ms": 9742, 61 + "conflicts_reported": 0, 62 + "files_processed": 3100, 63 + "success": true, 64 + "error": null 65 + }, 66 + { 67 + "strategy": "3-yrs-sidecar", 68 + "merge_time_ms": 10792, 69 + "conflicts_reported": 0, 70 + "files_processed": 3093, 71 + "success": true, 72 + "error": null 73 + }, 74 + { 75 + "strategy": "4-yrs-on-pds", 76 + "merge_time_ms": 26336, 77 + "conflicts_reported": 0, 78 + "files_processed": 1000, 79 + "success": true, 80 + "error": null 81 + } 82 + ] 83 + }, 84 + { 85 + "file_count": 1000, 86 + "avg_file_size": 1000, 87 + "collaborators": 2, 88 + "edits_per_branch": 50, 89 + "conflict_rate": "high", 90 + "results": [ 91 + { 92 + "strategy": "1-plain-git", 93 + "merge_time_ms": 8326, 94 + "conflicts_reported": 37, 95 + "files_processed": 1074, 96 + "success": false, 97 + "error": "" 98 + }, 99 + { 100 + "strategy": "2-yrs-diff", 101 + "merge_time_ms": 11281, 102 + "conflicts_reported": 0, 103 + "files_processed": 3100, 104 + "success": true, 105 + "error": null 106 + }, 107 + { 108 + "strategy": "3-yrs-sidecar", 109 + "merge_time_ms": 11917, 110 + "conflicts_reported": 0, 111 + "files_processed": 3099, 112 + "success": true, 113 + "error": null 114 + }, 115 + { 116 + "strategy": "4-yrs-on-pds", 117 + "merge_time_ms": 26208, 118 + "conflicts_reported": 0, 119 + "files_processed": 1000, 120 + "success": true, 121 + "error": null 122 + } 123 + ] 124 + } 125 + ]
+11 -10
src/gen.rs
··· 134 134 let mut edits = Vec::new(); 135 135 let client_id = (collab_idx + 1) as u64; 136 136 137 + let overlap_count = (edits_per as f64 * overlap) as usize; 138 + 137 139 for edit_idx in 0..edits_per { 140 + let is_overlapping = edit_idx < overlap_count; 141 + 138 142 // Pick a file to edit 139 - let file_idx = if matches!(config.conflict_rate, ConflictRate::Guaranteed) { 140 - // Guaranteed conflict: ALL collaborators edit the same files deterministically. 141 - // Each edit targets file (edit_idx % file_count), so all collaborators 142 - // edit the same set of files in the same order. 143 + let file_idx = if is_overlapping { 144 + // Overlapping edit — deterministic file selection so all collaborators 145 + // target the same files in the same order. This is what produces 146 + // actual git merge conflicts. 143 147 edit_idx % files.len() 144 - } else if edit_idx < (edits_per as f64 * overlap) as usize { 145 - // Overlapping edit — pick from first N files (shared) 146 - rng.random_range(0..std::cmp::max(1, files.len() / 4)) 147 148 } else { 148 149 // Non-overlapping edit — pick from this collaborator's "region" 149 150 let start = (collab_idx * files.len()) / config.collaborators; ··· 160 161 let full_path = output_dir.join(path); 161 162 let current = std::fs::read_to_string(&full_path).unwrap_or_default(); 162 163 163 - let edited = if matches!(config.conflict_rate, ConflictRate::Guaranteed) { 164 - // For guaranteed conflicts, always edit the same line (first content paragraph). 165 - // Each collaborator writes different text, guaranteeing a git merge conflict. 164 + let edited = if is_overlapping { 165 + // Overlapping edits rewrite the same line — guarantees a git conflict 166 + // when multiple collaborators both edit this file. 166 167 apply_conflicting_edit(&current, collab_idx, edit_idx) 167 168 } else { 168 169 apply_random_edit(&mut rng, &current, collab_idx, edit_idx)
+95 -37
src/runner.rs
··· 916 916 } 917 917 918 918 /// Save a directory to PDS via pds-yrs library (reuses existing client). 919 + /// Also ensures a YrsRepo record exists listing this branch. 919 920 async fn pds_yrs_save_with_client( 920 921 dir: &Path, 921 922 client: &pds_yrs::PdsClient, ··· 925 926 let local_state = pds_yrs::LocalState::open(dir)?; 926 927 let (rkey, _is_new) = 927 928 local_state.ensure_device_rkey(project, client.base_url(), "bench", did)?; 928 - pds_yrs::save(dir, client, did, &rkey, project, None, false).await?; 929 + pds_yrs::save(dir, client, did, &rkey, false).await?; 930 + // Ensure the project-level YrsRepo record lists this branch 931 + ensure_repo_record(client, did, project, &rkey).await?; 932 + Ok(()) 933 + } 934 + 935 + /// Create or update the YrsRepo record so it lists the given branch rkey. 936 + async fn ensure_repo_record( 937 + client: &pds_yrs::PdsClient, 938 + did: &str, 939 + project: &str, 940 + branch_rkey: &str, 941 + ) -> Result<(), String> { 942 + let existing = client 943 + .get_record(did, pds_yrs::REPO_COLLECTION, project) 944 + .await?; 945 + 946 + match existing { 947 + None => { 948 + let repo = pds_yrs::YrsRepo { 949 + schema_type: pds_yrs::REPO_COLLECTION.to_string(), 950 + name: project.to_string(), 951 + branches: vec![pds_yrs::BranchRef { 952 + rkey: branch_rkey.to_string(), 953 + label: None, 954 + }], 955 + updated_at: chrono::Utc::now().to_rfc3339(), 956 + }; 957 + let json = serde_json::to_value(&repo) 958 + .map_err(|e| format!("serialize YrsRepo: {}", e))?; 959 + client 960 + .put_record(did, pds_yrs::REPO_COLLECTION, project, json, None) 961 + .await?; 962 + } 963 + Some(record) => { 964 + let mut repo: pds_yrs::YrsRepo = serde_json::from_value(record.value) 965 + .map_err(|e| format!("parse YrsRepo: {}", e))?; 966 + 967 + if repo.branches.iter().any(|b| b.rkey == branch_rkey) { 968 + return Ok(()); 969 + } 970 + 971 + repo.branches.push(pds_yrs::BranchRef { 972 + rkey: branch_rkey.to_string(), 973 + label: None, 974 + }); 975 + repo.updated_at = chrono::Utc::now().to_rfc3339(); 976 + 977 + let json = serde_json::to_value(&repo) 978 + .map_err(|e| format!("serialize YrsRepo: {}", e))?; 979 + client 980 + .put_record(did, pds_yrs::REPO_COLLECTION, project, json, record.cid) 981 + .await?; 982 + } 983 + } 929 984 Ok(()) 930 985 } 931 986 ··· 936 991 project: &str, 937 992 output_dir: &Path, 938 993 ) -> Result<(), String> { 939 - pds_yrs::merge_project(client, did, project, None, output_dir, false).await 994 + pds_yrs::merge_project(client, did, project, output_dir, false).await 940 995 } 941 996 942 997 /// Cleanup all PDS repos for a project (best-effort, via curl). ··· 945 1000 } 946 1001 947 1002 /// Cleanup all PDS repos for a project (best-effort). 1003 + /// Deletes the YrsRepo record and all associated YrsBranch records. 948 1004 fn pds_yrs_cleanup(pds: &PdsConfig, project: &str) -> Result<(), String> { 949 1005 let token = get_pds_token(pds)?; 950 - // List all records and delete those matching the project 951 - let list_output = Command::new("curl") 1006 + 1007 + // First, fetch the YrsRepo record to find branch rkeys 1008 + let repo_output = Command::new("curl") 952 1009 .args([ 953 1010 "-s", 954 1011 &format!( 955 - "{}/xrpc/com.atproto.repo.listRecords?repo={}&collection=net.commoninternet.yrsrepo&limit=100", 956 - pds.pds, pds.did 1012 + "{}/xrpc/com.atproto.repo.getRecord?repo={}&collection={}&rkey={}", 1013 + pds.pds, pds.did, pds_yrs::REPO_COLLECTION, project 957 1014 ), 958 1015 ]) 959 1016 .output() 960 - .map_err(|e| format!("list records: {}", e))?; 1017 + .map_err(|e| format!("get repo record: {}", e))?; 961 1018 962 - if let Ok(text) = String::from_utf8(list_output.stdout) { 1019 + if let Ok(text) = String::from_utf8(repo_output.stdout) { 963 1020 if let Ok(json) = serde_json::from_str::<serde_json::Value>(&text) { 964 - if let Some(records) = json["records"].as_array() { 965 - for record in records { 966 - let name = record["value"]["name"].as_str().unwrap_or(""); 967 - if name != project { 968 - continue; 969 - } 970 - if let Some(uri) = record["uri"].as_str() { 971 - if let Some(rkey) = uri.rsplit('/').next() { 972 - let _ = Command::new("curl") 973 - .args([ 974 - "-s", 975 - "-X", 976 - "POST", 977 - &format!( 978 - "{}/xrpc/com.atproto.repo.deleteRecord", 979 - pds.pds 980 - ), 981 - "-H", 982 - "Content-Type: application/json", 983 - "-H", 984 - &format!("Authorization: Bearer {}", token), 985 - "-d", 986 - &format!( 987 - r#"{{"repo":"{}","collection":"net.commoninternet.yrsrepo","rkey":"{}"}}"#, 988 - pds.did, rkey 989 - ), 990 - ]) 991 - .output(); 992 - } 1021 + // Delete each branch record listed in the repo 1022 + if let Some(branches) = json["value"]["branches"].as_array() { 1023 + for branch in branches { 1024 + if let Some(rkey) = branch["rkey"].as_str() { 1025 + let _ = delete_record_curl(pds, &token, pds_yrs::BRANCH_COLLECTION, rkey); 993 1026 } 994 1027 } 995 1028 } 996 1029 } 997 1030 } 1031 + 1032 + // Delete the YrsRepo record itself 1033 + let _ = delete_record_curl(pds, &token, pds_yrs::REPO_COLLECTION, project); 1034 + 1035 + Ok(()) 1036 + } 1037 + 1038 + fn delete_record_curl(pds: &PdsConfig, token: &str, collection: &str, rkey: &str) -> Result<(), String> { 1039 + let _ = Command::new("curl") 1040 + .args([ 1041 + "-s", 1042 + "-X", 1043 + "POST", 1044 + &format!("{}/xrpc/com.atproto.repo.deleteRecord", pds.pds), 1045 + "-H", 1046 + "Content-Type: application/json", 1047 + "-H", 1048 + &format!("Authorization: Bearer {}", token), 1049 + "-d", 1050 + &format!( 1051 + r#"{{"repo":"{}","collection":"{}","rkey":"{}"}}"#, 1052 + pds.did, collection, rkey 1053 + ), 1054 + ]) 1055 + .output(); 998 1056 Ok(()) 999 1057 } 1000 1058