Tags: rename/merge is slow — no full reconcile, batched parallel rewrite, optimistic UI #1186
Closed
opened 2026-10-06 07:35:16 +00:00 by kayg
·
92 comments
No Branch/Tag specified
dev
wip/cards2-1083
wip/cards-1083
wip/canvas-visual
wip/canvasvis2-976
wip/calhdr-1112
wip/blocks-1125
wip/allday-1107
wip/agenda-1086
wip/trayicons2-1095
wip/trayicons-1095
wip/sidebar3-1094
wip/previewcard-1098
wip/palette2-1123
wip/palette-1093
wip/nlpchip-1127
wip/mchrome-1084
wip/mailghost2-1094
wip/mailghost-1094
wip/kbpreview2-1118
wip/kbpreview-1118
wip/kanban-1092
wip/editreg-1132
wip/editorrail3-1113
wip/editorrail2-1113
wip/editorrail-1113
wip/draw4-1101
wip/draw3-1101
wip/draw2-1101
wip/draw-1101
wip/delete-1119
job/txentry-1198
job/rev1586
job/rev2-money-ident
job/rev2-webperf
job/morph-1104
job/previewcard-1098
job/importhang-1121
job/kanban-1092
job/merge-round-7b
job/merge-round-7c
job/calcards-1115
job/collabrev3-1197
job/e2e-b-1071
job/agenda-1086
job/agenda-decks
job/allday-1107
job/browserfix
job/calact9
job/adv7c-1105
wip/collabrev3-1197
wip/calcards-1115
wip/calact9
wip/calact10
wip/browserfix
wip/agenda-decks
wip/adv7c-1105
wip/txentry-1198
wip/rev2-webperf
wip/rev2-money-ident
wip/rev1586
wip/morph-1104
wip/merge-round-7c5
wip/merge-round-7c4
wip/merge-round-7c3
wip/merge-round-7c2
wip/merge-round-7c
wip/importhang-1121
wip/fix1586
wip/e2e-b2-1071
wip/e2e-b-1071
job/noncanon-1618
wip/noncanon-1618
job/edrevert-1616
job/partial-1605
wip/partial-1605
job/calact6
job/cold-1586
job/perfvm-1587
wip/cold-1586
job/cal404-1581
wip/calact6
wip/cal404-1581
job/dname-1584
wip/dname-1584
job/merge41
wip/merge41b
wip/merge41
job/rev1573c
job/hscroll-1579
wip/rev1573c
job/rev1573b
job/rev1573
wip/fix1573
wip/hscroll2
wip/hscroll-1579
job/rev1574
wip/fix1574
wip/rev1574
job/startup-1573c
job/merge40
wip/startup-1573d
wip/startup-1573c
job/calact5
wip/remtext2
wip/merge40c
wip/merge40b
wip/merge40
job/calact4
job/startup-1573
job/calprof
wip/calprof
wip/startup-1573
job/fs1575
job/fix1570
job/calact3
job/rec1540c
wip/fix1570
job/rev1570-review
wip/calact3
job/calact2
wip/calact2
job/calcold-1560
wip/calcold-1560
wip/rec1540c
job/fix1569
wip/fix1569
job/calact-1557
wip/calact-1557
job/remtext-1568
wip/remtext-1568
job/fix1566
wip/fix1566
job/rec1540b
job/reconcile-1540
job/money2rev
wip/money2rev
job/merge39
wip/merge39
wip/reconcile-1540
job/tabswitch2
job/merge38
wip/merge38
job/autherr-1553
wip/autherr-1553
job/money-688
wip/money688rev3
wip/money688rev2
wip/money688rev
wip/money688l
wip/money688k
wip/money688j
wip/money688i
wip/money688h
wip/money688g
wip/money688f
wip/money688e
wip/money688d
wip/money688c
wip/money688b
wip/money-688
wip/tabswitch2
wip/merge37
job/merge37
job/jobnames-1538
wip/jobnames-1538
job/tabcomp-perf
job/calscript-1492
wip/tabcomp-perf
wip/calscript-1492
job/mailbody-1533
wip/mailbody-1533
job/intlfmt-1461
job/merge36
wip/intlfmt2
wip/intlfmt-1461
wip/merge36
job/merge35c
job/tagperf-1186
wip/tagrev2
wip/tagrev
wip/tagperf4
wip/tagperf2-1186
wip/tagperf-1186
wip/tagfix5
wip/tagfix3
wip/tagfast2
wip/tagfast
wip/merge35c
job/notesel-1493
wip/notesel2
wip/notesel-1493
job/merge35b
wip/merge35b
wip/m35btriage
wip/m35bratchet
wip/calsel-1491
job/calsel-1491
job/notifread-1387
job/bulkwrite-1393
wip/notifread2
wip/notifread-1387
job/slowsel-1392
wip/bulkwrite-1393
wip/bulkrev4
wip/bulkrev3
wip/bulkrev2
wip/bulkrev
wip/bulkfix4
wip/bulkfix3
wip/bulkfix2
wip/bulkfix
job/mail7-1340
job/bigscroll-1481
job/searchperf-1425
wip/mailrev4
wip/mailrev3
wip/mailrev2
wip/mailrev
wip/mail7f
wip/mail7e
wip/mail7d
wip/searchperf2
wip/searchperf-1425
wip/mail7c
wip/mail7b
wip/mail7-1340
job/photoopen-1367
job/mailsel-1449
wip/bigscroll-1481
wip/slowsel3
wip/slowsel2
wip/slowsel-1392
wip/selroot
job/journaldup
wip/journaldup8
wip/journaldup7
wip/journaldup6
wip/journaldup5
wip/journaldup4
wip/journaldup3
wip/journaldup2
wip/journaldup
wip/jdrev5
wip/jdrev4
wip/jdrev3
wip/jdrev2
wip/jdrev
wip/jdfix9
job/bignote-1349
wip/mailsel-1449
wip/bignote3
wip/bignote2
wip/bignote-1349
job/statusmark-1457
wip/statusmark-1457
wip/photoopen4
wip/photoopen3
wip/photoopen2
wip/photoopen-1367
job/authflash-1473
job/merge35
wip/authflash-1473
job/phototags-1370
wip/phototags-1370
wip/merge35
wip/m35triage
job/tick-1446
wip/tick-1446
job/restartidx-1450
job/exmove-1333
job/coldnote-1451
wip/restartidx-1450
wip/exmove-1333
wip/coldnote-1451
job/undo412-1430
wip/undo412-1430
job/calwrite-1441
job/xcancel-1443
job/calscroll-1362
wip/xcancel-1443
wip/calwrite-1441
job/xsub-1445
wip/calscroll3
wip/calscroll2
wip/calscroll-1362
wip/xsub-1445
job/linkdup-1440
wip/linkdup2
wip/linkdup-1440
wip/tabswitch4
wip/tabswitch3
wip/tabswitch-1233
wip/navrev
job/tabswitch-1233
job/mdpaste-1431
job/taskundo-1433
job/directory-1199
wip/taskundo-1433
job/remind-1432
job/nfd-1411
wip/remind-1432
wip/dirfix4
wip/dirfix3
wip/dirfix2
wip/dirfix-1199
wip/directory-1199-r
wip/directory-1199
job/readerx-1427
wip/readerx-1427
job/scrollfade-1416
job/tipphone-1439
wip/nfd-1411
job/purge-1420
job/notifrow-1414
wip/purge-1420
wip/notifrow-1414
job/slop-1385
wip/slop2
wip/slop-1385
job/tbover-1409
job/qltitle-1408
job/grantlive-1405
job/taskclick-1434
wip/tbover-1409
wip/taskclick-1434
wip/qltitle-1408
job/scrub-1422
job/hotfix35
job/ticks-1361
wip/scrub-1422
job/taskprev-1401
wip/grantlive-1405
job/ghost-1323
wip/ticks3
wip/ticks2
wip/ticks-1361
wip/taskprev-1401
job/bash3-settings
wip/ghost-1323
job/mailmorph-1368
wip/bash3-settings
job/apiaudit-1374
wip/bash3-filesphotos
job/bash3-filesphotos
job/xuser39-1402
job/bash3-money
job/mailhtml-1372
wip/mailhtml2
wip/mailhtml-1372
job/bash3-interop
job/bash3-calendar
wip/bash3-money
wip/bash3-interop
wip/bash3-calendar
wip/mailmorph2
wip/mailmorph-1368
wip/bash3-tasks
job/outro-1391
job/linkpick-1379
job/linkdel-1384
wip/linkpick2
wip/linkpick-1379
wip/linkdel3
wip/linkdel2
wip/linkdel-1384
job/mailrows-1390
wip/mailrows-1390
wip/apiaudit2
wip/apiaudit-1374
job/bash-core
wip/outro-1391
wip/bash-core2
wip/bash-core
job/bash3-notes
job/bash3-tasks
job/merge34
job/notifdel-1363
wip/merge34
wip/notifdel2
wip/notifdel-1363
job/wklink-1371
wip/wklink-1371
job/searchbar-1360
wip/searchbar2
wip/searchbar-1360
job/merge33-1122
wip/merge33c
wip/merge33b
wip/merge33-1122
job/bash-security
job/mailglass-1373
wip/bash-security2
wip/bash-security
wip/mailglass-1373
job/instaudit-1369
wip/instaudit-1369
job/tabstorm-1338
wip/tabstorm2
wip/tabstorm-1338
wip/bash-files2
wip/bash-files
job/bash-files
job/bash-money
job/editfuzz-1335
wip/bash-money
wip/moneyrev
job/tasksperf-1286
wip/tasksperf3
wip/tasksperf2
wip/tasksperf-1286
wip/editfuzz2
wip/editfuzz-1335
review/dirrev-1199
job/merge32
wip/merge32b
wip/merge32
job/bash-chrome
job/tagdnd-1187
job/bash-notes
wip/bash-notes2
wip/bash-notes
wip/bash-chrome
wip/reconcile-c1
wip/adv-c1
wip/tagdnd2-1187
wip/tagdnd-1187
job/bash-calendar
job/deploy-c1
job/editbreak-1334
job/bash-perf
wip/bash-calendar2
wip/bash-calendar
wip/bash-perf
job/hunt-20261006
job/bash-interop
job/collabloss-1197
wip/collabrev-1197
wip/collabloss5-1197
wip/collabloss4-1197
wip/collabloss3-1197
wip/collabloss2-1197
wip/collabloss-1197
wip/bash-interop
job/bash-mail
wip/bash-mail
job/vis-1293
wip/vis-1293
wip/restyle-search-r
wip/restyle-search-fix2
wip/restyle-search-fix
wip/restyle-search
job/restyle-settings
job/restyle-search
wip/restyle-settings-fix
wip/restyle-settings
job/adv31
wip/advfix-a
wip/adv31
job/bash-tasks
wip/bash-tasks
job/restyle-files
wip/restyle-files-fix
wip/restyle-files
job/fmtbar-1210
wip/fmtbar2-1210
wip/fmtbar-1210
job/perf2-1124
wip/perf2-1124
job/proflog-1204
job/merge31
wip/restyle-notes
wip/merge31
wip/proflog-1204
job/restyle-notes
job/fix-1213
wip/fix-1213
job/hide-1153
job/restyle-mailmoney
job/notestatus-1209
wip/hide-1153
wip/hiderev2-1153
wip/hiderev-1153
wip/hide5-1153
wip/hide4-1153
wip/hide3-1153
wip/hide2-1153
job/sidebarblur-1208
wip/notestatus-1209
wip/sidebarblur-1208
wip/restyle-mailmoney
job/onboard-1141
wip/onboard2-1141
wip/onboard-1141.aborted-early
wip/onboard-1141
job/adv-1202
job/segmented-1200
wip/segmented-1200
job/merge30
job/notifloop-1194
job/toastmorph-1201
wip/notifloop-1194
job/perf-1124
job/tocrail-1191
job/cards-1179
wip/cards2-1179
wip/cards-1179
wip/tocrail-1191
wip/perf-1124
wip/merge30j
job/wizchoices-1140
wip/wizchoices-1140
wip/restyle-1190
job/moneyfmt-1180
wip/moneyfmt2-1180
wip/moneyfmt-1180-r
wip/moneyfmt-1180
job/pillglass-1189
job/flags-1181
wip/flags-1181
job/restyle-1190
job/settingsreg-1195
job/wizard-1140
site/website
wip/wizardrev2-1140
wip/wizardrev-1140
wip/wizard5-1140
wip/wizard4-1140
wip/wizard3-1140
wip/wizard2-1140
wip/wizard-1140
wip/pillglass-1189
wip/settingsreg-1195
job/merge29
job/fu-1171
wip/merge29j
wip/fu-1171
job/fu-1166
job/txresearch-1188
wip/fu-1166
job/merge28
job/search-1066
wip/search-1066
wip/merge28j
job/gateslot-1182
job/bulkimport-1157
job/mailnet-1160
wip/mailnetrev-1160
wip/mailnet-1160
wip/bulkrev-1157
wip/bulkimport-1157
job/startup-1161
wip/startup-1161
job/merge27
job/linkcards-1151
wip/linkcards3-1151
wip/linkcards2-1151
wip/linkcards-1151
job/traydate-1144
wip/traydate3-1144
wip/traydate2-1144
wip/traydate-1144
job/draw-1101
wip/merge27j
job/blockpill-1152
wip/blockpill3-1152
wip/blockpill2-1152
wip/blockpill-1152
job/minihover-1149
wip/minihover2-1149
wip/minihover-1149
job/merge25
wip/merge25-r
wip/merge25b
wip/merge25
job/inspector-1129
job/tags-1110
wip/inspector3-1129
wip/inspector2-1129
wip/inspector-1129
wip/tagsrev-1110
wip/tags2-1110
wip/tags-1110
job/dates-1148
wip/datesrev-1148
wip/dates2-1148
wip/dates-1148
job/licence-1145
wip/licence2-1145
wip/licence-1145
job/selfhost-1156
fixbatch-25
job/merge23
wip/merge23
job/tagfilter-1109
wip/tagfilter2-1109
wip/tagfilter-1109
job/kbd-1134
wip/kbd2-1134
wip/kbd-1134
job/palfoot-1137
wip/selfhost-1156
wip/palfoot2-1137
wip/palfoot-1137
job/toggle-1158
wip/toggle-1158
fixbatch-23
job/kbpreview-1118
job/docratchet-1155
job/perflint-1133
job/devtests-1159
wip/docratchet-1155
wip/devtests-1159
job/segv-1136
wip/toast-1142
wip/segv-1136
job/toast-1142
job/blockreload-1147
wip/blockreload-1147
job/font-1150
wip/font-1150
job/importui-1120
job/minimonth-1149
wip/importui-1120
wip/minimonth-1149
job/depcheck-1146
wip/perflint-1133
wip/depcheck-1146
job/blocks-1125
job/plus-1128
job/shift-1138
wip/plus2-1128
wip/plus-1128
wip/shift-1138
job/moneyfid-1130
job/editorrail-1113
wip/moneyrev-1130
wip/moneyfid-1130
job/noext-851
wip/noext-851
wip/noext3-851
wip/noext2-851
job/week-1135
wip/week-1135
job/editreg-1132
job/smoke-1122
wip/smoke-1122
job/docs-1143
job/palette2-1123
job/calhdr-1112
job/nlpchip-1127
job/mailghost-1094
job/reconnect-1131
wip/reconnect-1131
job/trayicons-1095
job/delete-1119
hotfix-sidebar2
job/cards-1083
job/palette-1093
job/mchrome-1084
job/e2e-a-1071
job/canvas-visual
wip/e2e-a2-1071
wip/e2e-a-1071
backup/canvas-visual-before-reconcile
wip/surfaces-p2
job/merge-round-9
wip/merge-round-9
job/7cfix-small
wip/7cfix-small
job/mailui-1078
job/merge-round-8
wip/merge-round-8
wip/mailui-1078
job/mailround-1038
job/applemail-accept
wip/settitle-1068
wip/mailround2-1038
wip/mailround-1038
wip/e2e-7b
job/crash-1069
wip/crash-1069
job/searchlost-1066
wip/searchlost-1066
job/7b-reconcile
job/flake-1065
wip/flake-1065
wip/merge-round-7b7
wip/merge-round-7b6
wip/merge-round-7b5
wip/merge-round-7b4
wip/7b-reconcile
job/appupdate-1059
job/nfd-1044
wip/appupdate-1059
job/e2e-7b
job/loop-1062
wip/loop-1062
job/pdfprev-1045
job/invtoggle-1053
wip/pdfprev-1045
wip/nfd-1044
wip/invtoggle-1053
job/7bfix-e2e
job/mailstress-b
wip/7bfix-e2e
wip/mailstress-b
job/7bfix-adv
wip/7bfix-adv
job/mailstress-a
job/stack-1054
wip/stack-1054
wip/mailstress-a
job/mailstress-1038
wip/mailstress-1038
job/upload500-1051
wip/upload500-1051
job/share-1034
wip/share-1034
job/syncerr-1037
job/7bfix-photos
wip/7bfix-photos
job/paste-1036
job/setside-1039
wip/setside-1039
wip/paste-1036
job/lease-1042
wip/syncerr-1037
wip/lease-1042
job/7bfix-data
job/passkeybind-1043
wip/apprevoke-1041
job/invite-1035
wip/invite-1035
job/merge-round-7b2
wip/merge-round-7b2
job/mailproxy-486
job/apprevoke-1041
job/rebuild-1033
job/pillborder-1029
wip/pillborder-1029
wip/mailproxy-486
wip/applemail-486
job/headless-998
wip/headless-998
job/groups-1028
wip/groups-1028
job/rebuildwarn-1016
wip/rebuildwarn-1016
job/startup-1011
wip/startup-1011
job/monthpill-1009
job/bgthumb-1025
job/sharetitle-1012
wip/monthpill-1009
wip/bgthumb-1025
wip/sharetitle-1012
job/canvas-cards-977
wip/canvas-cards-977
job/canvas-pencil-978
job/canvas-sketch-990
wip/canvas-sketch-990
wip/canvas-pencil-978
job/canvas-files-989
wip/canvas-files-989
job/canvas-collab-991
wip/canvas-collab-991
job/weekscroll-1018
wip/weekscroll-1018
wip/canvas-core-976
job/canvas-core-976
job/round-drag
wip/round-drag
job/round-settings
wip/oapi-974
job/oapi-974
job/hist2-integrate
job/mailhtml-726
wip/mailhtml-726
wip/hist2-integrate
job/moneyfu-984
job/drag-1015
wip/drag-1015
job/rename-1017
wip/rename-1017
job/hist2-api
wip/hist2-api
job/oneacct-1014
wip/oneacct-1014
wip/moneyfu-984
job/hist2-bench
job/hist2-restore
wip/hist2-bench
job/hist2-write
job/hotfix-724
wip/hotfix-724
wip/hist2-write
wip/hist2-restore
job/hist2-store
job/hist2-ui
wip/hist2-ui
wip/hist2-store
job/searchstarve-965
job/shutdown-963
wip/shutdown-963
wip/pubedit-981
job/pubedit-981
job/analytics-973
wip/searchstarve-965
job/authflash-850
job/weeklane-969
job/pvtitle-1004
job/hist-975
wip/authflash-850
job/voicepill-617
wip/pvtitle-1004
job/headring-1003
wip/weeklane-969
wip/voicepill-617
wip/headring-1003
wip/analytics-973
job/agentscope-980
wip/thumbsandbox-988
job/thumbsandbox-988
wip/hist-975
job/links-856
wip/links-856
job/davetag-966
wip/davetag-966
job/filesstorm-1000
job/hoverpad-725
wip/filesstorm-1000
job/ffmpegblas-993
job/merge-round-7a
wip/hoverpad-725
wip/ffmpegblas-993
job/nowdot-1002
wip/verify-7a
job/noteid-857
wip/nowdot-1002
wip/noteid-857
wip/merge-round-7a
wip/agentscope-980
job/imapedge
job/a11yfix2
wip/imapedge-941
wip/imapedge
wip/a11yfix2
job/notetask-986
job/logheading
wip/logheading-998
job/textthumb-652
job/photolive-987
wip/photolive-987
job/davactive-983
job/savefix-985
job/tabicons-607
wip/davactive-983
wip/tabicons-607
wip/notetask-986
wip/savefix-985
job/dirid-627
job/buildspeed-1007
wip/dirid-627
job/staging-imap
job/perfguards-impl
job/undo-a11y
wip/undo-a11y
job/mailperf
job/wal-824
wip/settings-50
job/settings-50
job/notesfilter-606
wip/notesfilter-606
job/surfaces-p2
wip/wal-824
job/maillayouts
wip/mailperf
wip/maillayouts
job/taskmeta-659
job/money-ident
wip/money-ident
wip/taskmeta-659
job/errstates
wip/perfguards-impl
job/headings-881
wip/headings-881
wip/errstates
job/voice-619
job/gaps-827
job/notesperf
wip/notesperf
wip/voice-619
job/hddsql-549
job/perf-stream-668
wip/perf-stream-668
wip/deeplinks-fix
job/deeplinks-fix
job/authfix
job/docsfix-rust
wip/docsfix-rust
job/webperf
job/docsfix-web
job/datafix2
job/webdav-lock-476
job/copyfix
wip/copyfix
wip/webperf
job/focus-658
wip/protofix
job/mediafix
job/protofix
wip/mediafix
job/agentfix
job/hhmm-724
wip/agentfix
job/undo-722
job/reuse
wip/webdav-lock-476
wip/reuse
job/scopefix
job/datafix
wip/hhmm-724
wip/undo-722
job/surfaces-p1
wip/hddsql-549
job/voicememos-618
wip/datafix2
wip/surfaces-p1
job/fix-940
wip/fix-940
job/blaze-surfaces
wip/datafix
wip/blaze-surfaces
job/taskday-655
job/linknav-639
wip/linknav-639
wip/gaps-827
job/isolation-707
job/audiophotos-720
wip/audiophotos-720
job/advfind-664
wip/voicememos-618
wip/taskday-655
wip/isolation-707
wip/advfind-664
wip/scopefix
wip/focus-658
job/testgaps
wip/testgaps
job/overscroll-718
wip/authfix
job/deps
wip/overscroll-718
job/rev2-agentfix
job/rev2-mailperf
wip/deps
job/hardening-728
wip/hardening-728
job/searchgen-832
wip/searchgen-832
job/photopw-849
job/mailsql-825
wip/photopw-849
job/sharefix
wip/sharefix
job/rev2-mailhtml-726
job/rev2-perfguards
job/copyval-723
job/lightglass-r2
wip/lightglass-r2
wip/docsfix-web
job/copy-audit
job/macinterop-staging-r2
job/design-sync
job/rev2-taskmeta-659
job/docs-audit
job/rev2-advfind-664
job/rev2-mailproxy-486
job/states-audit
job/rev2-datafix
job/design-drift
job/test-gaps
job/rev2-voicememos-618
job/rev2-mediafix
job/rev2-deps
job/rev2-datafix2
job/licence-audit
job/issue-hygiene
job/rev2-protofix
job/rev2-voice-619
job/rev2-isolation-707
job/rev2-surfaces-p1
job/deeplink-audit2
job/rev2-audiophotos-720
wip/test-gaps
job/rev2-overscroll-718
job/rev2-undo-722
wip/states-audit
job/rev2-dropmd-719
job/rev2-linknav-639
job/merge-7b-plan
wip/merge-7b-plan
job/rev2-taskday-655
wip/mailsql-825
job/rev2-webdav-lock-476
job/rev2-browserfix
wip/design-drift
job/rev2-hddsql-549
wip/deeplink-audit2
job/rev2-scopefix
job/rev2-authfix
job/rev2-hardening-728
job/rev2-wal-824
job/rev2-sharefix
job/calsidebar-638
job/chrome-audit
job/ioperf
wip/ioperf
wip/chrome-audit
wip/calsidebar-638
job/dropmd-719
wip/dropmd-719
job/ocr-build
wip/ocr-build
job/blaze-settings
wip/copyval-723
job/toastring-721
wip/toastring-721
job/deployfix-732
wip/deployfix-732
wip/blaze-settings
job/money-import-recheck
job/rev-a11y
job/perf-arch-db
job/rev-7b-data
wip/textthumb-652
wip/perf-arch-db
job/sec-protocols
job/sidehdr-660
job/rev-7b-security
job/research-surfaces
job/rev-design-gaps
job/rev-mcp-api
wip/sidehdr-660
job/perf-arch-memory
wip/sec-protocols
job/perf-arch-bundle
job/snapedge-714
wip/rev-mcp-api
job/sec-supplychain
wip/research-surfaces
job/perf-arch-sync
job/rev-consistency
job/perf-arch-server
wip/perf-arch-server
wip/perf-arch-memory
job/perf-arch-io
job/perf-arch-client
job/sec-fs
job/sec-mcp-scopes
job/sec-sharing
job/perf-guards
job/sec-browser
job/sec-admin-deploy
job/sec-auth
wip/snapedge-714
job/bgpicker-717
wip/perf-arch-bundle
wip/money-import-recheck
job/advsetup-654
wip/bgpicker-717
wip/advsetup-654
job/burst-709
job/kbdcaps-710
job/app-pw-chooser
wip/burst-709
wip/app-pw-chooser
job/imaptest-625
wip/kbdcaps-710
job/fix-499
wip/fix-499
job/perf-mut-667
job/calimg-589
job/perf-snap-666
wip/calimg-589
wip/perf-snap-666
wip/perf-mut-667
job/perf-cache-665
wip/perf-cache-665
job/voicefiles-620
wip/voicefiles-620
job/admin-burst-705
wip/admin-burst-705
job/voicememos-review
wip/voicememos-review
wip/ryw-653
job/ryw-653
job/writeonopen-661
job/instant-663
wip/writeonopen-661
job/money-import-review
wip/money-import-review
wip/importjs-610
review/integrations-407-round6
wip/integrations-review
job/dragghost-612
wip/dragghost-612
job/integrations
wip/integrations
job/decider-656
job/merge-round-6
job/perf-rerun
wip/merge-round-6
job/integrations-review-round5
job/selalign-576
wip/selalign-576
job/mcp-events-491
job/files-631
job/cal-e2e-569
wip/cal-e2e-569
job/reload-423
wip/reload-423
wip/mcp-events-491
wip/files-631
job/notesbridge-644
wip/notesbridge-644
job/editor-series
job/calcard-series
wip/calcard-series
job/mcp-events-review-491
wip/mcp-events-review
wip/editor-series
job/quirks-546
job/integrations-recheck
job/tocrail-636
wip/tocrail-636
wip/quirks-546
wip/reminders-643
job/reminders-643
wip/davscale-573
job/davscale-573
job/integrations-review
wip/ocr-eval-584
job/ocr-eval-584
job/esc-537
wip/esc-537
job/toastname-586
wip/toastname-586
job/submenu-579
wip/submenu-579
job/tasks-mode
wip/tasks-mode
job/agentdocs-630
job/dupwrite-634
wip/agentdocs-630
wip/dupwrite-634
job/lightglass-588
wip/lightglass-588
job/tabswitch-549
job/ghosttask-623
wip/ghosttask-623
job/toaststack-616
job/weekstate-609
job/mailsync-613
wip/mailsync-613
wip/weekstate-609
job/maildup-626
wip/tabswitch-549
wip/maildup-626
wip/toaststack-616
job/motion-611
wip/motion-611
job/tlstest-601
wip/tlstest-601
job/perf-495
job/floating-sheet
wip/floating-sheet
job/remdup-585
wip/remdup-585
job/fix-502
wip/fix-502
job/attachplay-622
job/perf-batch
wip/perf-batch-563
wip/perf-495
hotfix/mail-sync-diag
job/mail-m3
wip/mail-m3
job/attach-poof-603
job/calhover-608
job/editorbar-604
job/mentions-605
job/merge-round-4
job/allday-514
wip/merge-round-4
wip/allday-514
job/merge-round-4a
wip/merge-round-4a
job/sharestack-580
job/fix-501
wip/sharestack-580
wip/fix-501
job/perf-batch-563
job/theme-detail
job/apw-cache-review
wip/apw-cache-review
job/probe-520
wip/probe-520
job/mac-393
wip/mac-393
job/header-571
job/flake-513
wip/flake-513
job/docs-thumb-547
wip/header-571
job/webcal-572
wip/webcal-572
wip/shortcuts-542
job/shortcuts-542
wip/docs-thumb-547
job/caldav-stress
wip/caldav-stress
wip/sweep-478
job/apw-cache-512
wip/apw-cache-512
job/money-empty-540
wip/restart-505
wip/money-empty-540
wip/fix-510
job/restart-505
job/fix-503
job/perf-496
wip/perf-496
job/fix-498
wip/fix-498
job/info-inspector-465
wip/info-inspector-465
job/fix-510
job/fix-507
wip/fix-507
wip/fix-503
job/fix-493
job/money-kinds
wip/money-kinds
job/hygiene-548
job/merge-round-3
wip/fix-493
job/drag-snap-536
wip/merge-round-3
wip/merge-round-0930
wip/drag-snap-536
job/align-538
wip/align-538
job/bg-flash
wip/bg-flash
job/money-import
job/search-count-544
wip/search-count-544
wip/money-import
job/settings-key-541
wip/settings-key-541
job/toast-539
job/preview-421
wip/preview-421
wip/toast-539
job/tasks-500-531
job/title-plain-526
wip/title-plain-526
wip/tasks-500-531
job/notes-bridge
wip/parity-484
job/parity-484
job/files-slow
job/crash-525
wip/notes-bridge
wip/files-slow
wip/crash-525
job/kbd-motion-527
wip/bg-422
job/analytics-504
wip/analytics-504
wip/kbd-motion-527
job/upload-pill-523
wip/upload-pill-523
wip/tray-order
job/tray-order
wip/overflow-mid
wip/merge-round-2
job/perf-494
wip/perf-494
job/merge-round-3-pre-rebuild
wip/mcp-fast-492
wip/motion-477
wip/asr-ab-489
wip/theme-variants-506
wip/overflow-511
wip/week-header-508
wip/attach-427
job/dav-delete-471
job/iso-435
wip/iso-435
wip/files-sel-keys
wip/dav-delete-471
job/align-253
job/siwc-490
wip/siwc-490
job/money-kinds-review
wip/align-253
wip/money-kinds-review
job/small-bugs-3
wip/overlay-title-487
wip/multiget-500
wip/hidden-420
wip/webcal-ui
wip/webcal-431
job/perf-367
job/location
wip/small-bugs-3
wip/location
wip/perf-367
wip/admin-deny-483
job/tag-unicode-473
wip/tag-unicode-473
job/blur-436
wip/photos-470
wip/blur-436
wip/small-bugs-4
wip/hunt-20260930
wip/settings-hdr-482
wip/chips-416
job/dedup-375
wip/dedup-375
job/doc-stack
wip/doc-stack
job/tokens-literals
wip/tokens-literals
job/jobs-leftovers
wip/send-fast
wip/paste-467
wip/money-numbers
job/money-plugin
wip/money-plugin
backup/doc-stack-r3-reset-source
job/break-dav
wip/merge-batch
wip/crossday-469
wip/mac-verify
wip/mail-m2
wip/break-dav
wip/money-review2
job/money-md
job/modes-424
wip/money-md
wip/jobs-leftovers
job/agenda-413
wip/agenda-413
job/dedup-375-clean
job/dedup-375-before-rebase
wip/modes-424
job/recog-417
wip/recog-417
wip/bounce-425
wip/ab-384-luna
backup/doc-stack-round3-before-rebuild
job/webdav-perf
wip/webdav-perf
job/toast-ring
wip/toast-ring
job/money-review
wip/money-review
wip/micro-motion
wip/settings-card
wip/minical
job/notes-imap-428
job/least-priv
wip/ui-small-2
wip/flaky-426
wip/drag-end-418
job/jank
wip/jank
wip/least-priv
wip/docs-site
job/agenda
job/sec-batch
wip/sec-batch
wip/per-user-index
job/area-calendars
wip/area-calendars
job/parity
wip/parity
job/documents-research
wip/documents-research
job/test-infra
job/reminders-sync
wip/small-bugs-2
wip/reminders-sync
wip/gestures
job/google-oauth
wip/tags-merge
wip/tags
job/e2e-theme
wip/e2e-theme
job/icon-align
wip/test-infra
wip/select-align
wip/editor-385
job/voice
wip/webdav
job/webdav
job/app-pw-ui
job/editor-integrity
wip/editor-integrity
wip/voice
wip/quota
wip/cal-followups
wip/icon-align
job/composer-scale
wip/composer-scale
job/jobs-page
wip/jobs-page
job/hig-type
wip/hig-type
wip/app-pw-ui
job/motion-spring
job/mcp
wip/motion-spring
wip/mcp
job/small-bugs
wip/push-hosts
job/profile-sign
wip/touch-369
wip/profile-sign
job/mobile-focus
wip/mobile-focus
wip/ui-polish-354
wip/small-bugs
wip/dup-task
job/toast-polish
job/app-pw-scopes
wip/toast-polish
wip/app-pw-scopes
wip/cli-agent
wip/selection-pills
job/preview-attach
wip/preview-attach
job/dav-proppatch
wip/dav-proppatch
wip/cal-switcher
job/atomic-race
wip/atomic-race
job/photos-shared
wip/photos-shared
wip/cal-grid
wip/note-rewrite
wip/search-rebuild
job/mail-m1
job/paperless-import
wip/paperless-import
wip/mail-m1
wip/hidden-activity
wip/search-d
wip/pricing-research
wip/cursors
wip/auto-scheme
job/single-pills
wip/single-pills
wip/xuser-matrix
wip/money-format
wip/app-pw-setup
wip/purge-dos
wip/vault-health
wip/caldav-apple
wip/xuser-audit
wip/e2e-green
wip/tabbar
wip/adv-harness
wip/maple-mono
job/search-fix
wip/search-fix
wip/search-perf-c
job/adv-harness
wip/sidebar-headers
job/glass
wip/temp-index
job/polish
wip/polish
wip/file-protocols
wip/money-research
wip/glass
wip/voice-models
wip/collab-redo
job/voice-research
wip/hunt-20260928
wip/notes-actions-research
wip/search-pad
wip/search-perf
wip/search-sticky
wip/editor-undo
wip/chrome-rules
wip/motion
wip/appearance-research
wip/appearance
wip/audit-bugs
wip/cal-glass
wip/block-actions
wip/authz-order
wip/event-stripes
wip/chrome-sidebar
wip/auth-flaky
wip/robust-2
wip/gate-fix
wip/menu-blur
wip/import-calternaljs
wip/tray-fix
job/import-calternaljs
wip/index-order
wip/audit-fixes
wip/search-chevrons
research/mail
wip/phone-chrome
wip/dedup-break
wip/csp
wip/ui-audit
wip/select-toast
wip/perf
wip/flat-layout
wip/fonts
wip/event-tint
wip/sync-converge
wip/data-split
wip/glass-audit
wip/robustness
wip/sync-chaos
wip/search-thumbs
wip/fuzz
wip/menu-icons
wip/search-pill
wip/sync-changing
wip/heading-links
wip/date-formats
wip/a11y
wip/break-editor
wip/e2e-fix
wip/settings-sections
wip/sync-root-guard
wip/search-palette
wip/share-edit
job/toasts
wip/toasts
wip/cont-analytics
wip/authz-review
wip/popovers
wip/overlay-glass
wip/change-feed
wip/editor-modes
wip/composer-align
wip/cont-agenda
wip/agenda-merge
job/agent-conventions
wip/agent-conventions
wip/backend-misc
job/route-audit
wip/route-audit
wip/ui-batch
wip/heif-hardening
wip/grid-resize
wip/ask-page
wip/webmcp
job/deeplink-audit
wip/deeplinks
wip/shortcuts
wip/cont-tz-days
main
No results found.
Labels
Clear labels
No items
No labels
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
1 participant
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Dependencies
No dependencies set
Reference
kayg/calternal-v0#1186
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Owner report (2026-10-06): "updating tags takes too long (sequential? synchronous) — we are not writing performant code by default!"
Orchestrator reading of crates/calternal-tags/src/rewrite.rs:
preparerunsindex::reconcile_user(a full Home reconcile) before every rename/merge, thenrun_untilprocesses targets one by one: take the namespace mutation lock, write the file, save the journal, refresh the Index, checkpoint (disk write) — per file.Do (keep crash safety, resumability and exact Undo from #1110):
Gates per crate +
bun run check+bun run testquoted; numbers in the report and docs/perf/. A data-safety review follows.Starting #1186 on
job/tagperf-1186, based atf5fbced3c733370b5b37544d7816732628be2fd0(worktree reports three commits behindorigin/dev). I have readCLAUDE.md,CONTEXT.md, and the relevant Tag/index and instant interaction sections ofdocs/DESIGN.md. I am inspecting the existing benchmark and will record the ~1,000-item rename/merge baseline on the locked perf VM before changing the rewrite path.Baseline setup is ready: the 1,000-item runner and concurrent request sampler are committed in
65a5a1f77and77629d50b, and a release server from basef5fbced3cis staged on the perf VM. Source inspection confirmsrewrite::preparecallsindex::reconcile_userbefore querying candidate Tag paths, then reads all indexed MIME values;run_untilwrites and checkpoints one source at a time, andrefresh_indexperforms separate item lookups and writes. The required/root/perf.lockis held by another run (observed lock owners areflockandbash); this job is waiting for the exclusive measurement window. No baseline timings are available yet, and no implementation files have been changed.The first baseline attempt did not reach a rewrite sample. Seeding 1,000 Notes with 16 concurrent POSTs hit HTTP 500 at item 985 (
Notes operation failed). The server log had repeated SQLite busy errors (sqlite_code=5) and a search-indexerTooManyOpenFileserror. The partial Home and profile were discarded. I am changing the fixture seeder to create Notes serially and report progress; this keeps setup outside the measured interval and avoids turning profile setup into a concurrency storm.The serial API seed reached 1,000 Notes, but the server then logged repeated Notes Index SQLite busy errors, and the final Tag-count read stalled beyond its 120-second timeout;
/readyzalso stopped responding (server RSS was about 811 MB). I discarded that Home and addedcrates/calternal-tags/examples/tag_rewrite_1186_seed.rs: it creates actual Markdown Notes throughcalternal-fs, runs one normal Tags reconciliation, and checks both Index counts. The profile now verifies that fixture before timing rewrites.cargo fmt --check, focused Clippy and all 44calternal-tagstests pass; the baseline timing is still pending.Performance baseline finding: the 1,000-item fixture is now seeded directly through calternal-fs and its Tag counts verify. Under the perf lock, the first baseline rename had not reached a terminal receipt after more than five minutes of observation, with no completed sample yet. The current path therefore includes substantial setup/serialized work; I am keeping the run active to capture end-to-end wall time and overlapping Tag-read p95 before implementation changes.
Baseline finding: with the direct 1,000-Note fixture, the pre-change server accepted the first rename but did not reach a terminal receipt within the configured 1,800-second timeout. The locked VM reported load average 2.46875, 2.68115234375, 1.79248046875 at start and 5.14990234375, 7.09521484375, 6.75341796875 after stop. The initial profiler discarded concurrent-read samples on timeout, so it did not produce a p95; I am fixing that reporting path and will record the incomplete wall time as a lower bound rather than claim a completed sample.
Finding for #1186: after the first batch implementation, receipt progress counted Sidecar files as source records. A folder Sidecar can represent many visible Files, so 1,000 tagged Files would show fewer than 1,000 completed items. Progress now counts the visible items in each source and validates journal cursors before indexing offsets.
cargo clippy -p calternal-tags --all-targets -- -D warningspassed;cargo test -p calternal-tagspassed (45 tests).Baseline evidence for #1186 (pre-change release, perf VM, each run under
flock /root/perf.lock, 1,000 source Notes + one destination, 16 concurrent Tag readers): rename remained nonterminal after 61.12 s; reader p95 416.96 ms, max 902.24 ms, 5,215 reads, 0 errors; server CPU 33.83 s, average RSS 264,019,955 bytes, peak RSS 268,505,088 bytes. Merge remained nonterminal after 61.04 s; reader p95 430.16 ms, max 892.24 ms, 4,763 reads, 0 errors; server CPU 37.40 s, average RSS 257,196,516 bytes, peak RSS 264,237,056 bytes. The older rename run also remained nonterminal after 1,800 s. Lock-held load averages (1/5/15 min) were 2.39→3.63 for rename and 2.43→3.78 for merge. The two 60-second operations are censored lower bounds; their disposable Homes were not reused.Finding for #1186: the first optimized 1,000-item rename reached 832/1,000, then the receipt failed with
tag filesystem operation failedandcan_undo=true. The admin job detail recordedlast_error=tag filesystem operation failed. Sanitized server diagnostics at the same time showToo many open files (os error 24)from accept, search-index and file-index work, followed by Index pool closure during shutdown. The sample had 16 continuous/api/v1/tagsreaders. I stopped the run, preserved the separate untouched fixture, and am isolating whether the repeated-read profile or rewrite path exhausts descriptors before continuing the performance comparison.Performance and data-safety finding: the first 1,000-item run reached item 832 with 484 of 499 server descriptors held by
users/<user>/Notesdirectory proofs. The queued filesystem changes kept each optional proof fd alive until consumers drained them, then the rewrite hitEMFILE. The batch writer now uses the same checked BLAKE3 replacement and path event without retaining that optional proof; the Files projection keeps its existing conservative check. A focused filesystem test covers this event path.The interrupted run's Undo reported 103 conflicts. A byte audit showed that a background
calternal-idbackfill changed Notes while the old fixture was being rewritten, so the journal no longer represented a stable byte state. The performance fixture now uses stable IDs and upgrades only the exact known legacy fixture bytes. I will rerun both versions from that clean fixture before reporting comparable timings.cargo clippy -p calternal-fs --all-targets -- -D warningsandcargo clippy -p calternal-tags --all-targets -- -D warningspassed. All 45calternal-tagstests passed. The full filesystem test run had one unrelatedhistory_rejects_symlinked_segments_and_keeps_lock_after_foldEAGAINfrom nonblockingflock; that test passes when run alone. Its assertion was not changed.The first lock-held post-change rename profile completed all 1,000 targets and exact Undo on the perf VM. One sample took 575.96 s (9m 35.96s); other-request p95 was 13.90 ms, with 0 read errors. Server CPU was 120.03 s, average RSS 257,457,544 bytes (peak 279,846,912), and open descriptors averaged 116.11 (peak 136). Host load under the lock was 3.14/4.56/4.36 before and 4.35/4.11/4.16 after.
The old implementation did not finish within 180 s: rename reached 70/1,000 and other-request p95 was 11.98 ms; merge reached 70/1,000 and p95 was 12.29 ms. The first optimized run reached 256/1,000 in 180 s. The latest run is about 4.5x the old observed per-target throughput, below the 10x goal, and p95 is higher. CPU time accounts for 120 s of the 576 s wall time, which points to synchronous durable filesystem work as the remaining cost. I am grouping the per-file install intents and directory durability work into the existing 64-target batch while keeping the batch journal and exact Undo.
Status
The #1186 implementation is committed on
job/tagperf-1186, but this run is incomplete and is not ready for merge. I stopped at the owner’s four-hour job cap.Head:
6a481b0a1200fd0076d22aba4339d8694171b17a.Built
reconcile_user. The checked Root writer verifies each source revision before publication.#1186benchmark/seeder and a real-server screenshot driver.Files owned by this job:
apps/web/e2e/tag-rewrite-1186.mjs,apps/web/src/lib/components/TagRow.svelte,apps/web/src/lib/components/TagRow.svelte.test.ts,apps/web/src/lib/components/app-sidebar.svelte,apps/web/src/lib/stores/tagRewrite.svelte.test.ts,apps/web/src/lib/stores/tagRewrite.svelte.ts,apps/web/src/routes/tag/[tag]/+page.svelte,apps/web/src/routes/tags/+page.svelte,bench/tag-rewrite-1186-controller.py,bench/tag-rewrite-1186.py,crates/calternal-fs/src/journal.rs,crates/calternal-fs/src/lib.rs,crates/calternal-fs/src/quota.rs,crates/calternal-fs/src/root.rs,crates/calternal-fs/src/versions.rs,crates/calternal-fs/src/write.rs,crates/calternal-fs/tests/storage.rs,crates/calternal-tags/examples/tag_rewrite_1186_seed.rs,crates/calternal-tags/src/index.rs,crates/calternal-tags/src/rewrite.rs,crates/calternal-tags/src/source.rs, plus exact generated perf contracts.Gates
cargo fmt --check: exit 0, no output.cargo clippy -p calternal-fs --all-targets -- -D warnings:cargo test -p calternal-fs:cargo clippy -p calternal-tags --all-targets -- -D warnings:cargo test -p calternal-tags:The first post-merge
bun run checkfound a stale exactrender.boundpin inapp-sidebar.svelte;scripts/perf-lint --adopt-7crefreshed exact live hashes and reduced the ratchet from 22,615 to 22,605. Its output ended:The second
bun run checkdid not finish. It was stopped at the time cap while Svelte diagnostics were still running:bun run testwas not run.Performance and UX gaps
Perf VM baseline (1000 source items; measurements held under
/root/perf.lock): rename was incomplete after 180.151 s at 70/1000, other-request p95 11.98 ms; merge was incomplete after 180.193 s at 70/1000, p95 12.29 ms. A later interim rename profile, before the final per-batch journal/sync change, completed in 575.962 s with p95 13.90 ms and exact Undo. Host load was higher during that sample. There is no after measurement for the final batch journal code, so the ≥10× target and p95 target remain unverified. Nodocs/perf/result was added.When a Home quota is configured,
reserve_batch_write_quotastill walks Home once per 64-target batch. The Index reconcile is gone, but this remaining quota walk needs review against the no-full-Home-scan performance rule.Only three phone/light macOS screenshots exist from the earlier real-server run:
artifacts/tag-rewrite-1186/progress-phone-light-mac.png,artifacts/tag-rewrite-1186/tags-phone-light-mac.png, andartifacts/tag-rewrite-1186/tag-detail-phone-light-mac.png. The sidebar locator was corrected afterward, but the final real-server matrix was not rerun or attached. Tablet/desktop, dark theme, and sidebar evidence are missing. A one-time adversarial round and the full web tests also remain for the merge round.Decisions
syncfsper affected data filesystem so staged data and Version directories exist before the WAL can name them, followed by one post-publicationsyncfsper affected filesystem before deleting the intent. The existing per-file journal path is unchanged.TagRow,ItemActionMenu, status/Undo toast, and sidebar; no new visual primitive was added.For the merge round: run
cd apps/web && bun run check,cd apps/web && bun run test -- --maxWorkers=2,cd apps/web && bun e2e/tag-rewrite-1186.mjs, then run one adversarial pass withbash tests/adversarial/run.shagainst the real local server. The UI run must capture macOS-emulated phone (390), tablet (820), and desktop (1440) in light and dark. Run final rename and merge profiles on the perf VM under separateflock /root/perf.lockphases, record load average inside each lock, and add the final numbers todocs/perf/.Continuing #1186 on
job/tagperf-1186. Worktree head at resume:6a481b0a1200fd0076d22aba4339d8694171b17a; currentorigin/devbase to merge before final gates:3601719b80a39f712daf07b37879b22929dfffa0. I read the previous report and the requiredCLAUDE.md,CONTEXT.md, and relevantdocs/DESIGN.mdsections. The implementation is committed; this run will finish the requested full web gates, final 1,000-target interleaved rename/merge measurements, quota-walk assessment, production screenshot matrix, and e2e driver. No new code findings yet.Finding during the required full web suite after merging
origin/dev: Vitest reported× a tag chip opens the tag menu and a pick rewrites only that token(5,736 ms) atapps/web/src/lib/composer/Composer.svelte.test.ts:262. This is in the merged Composer code, outside the #1186 Tag rewrite files. I have not changed the assertion. The full suite is still running; I will record its final diagnostic and aggregate result when it exits.Additional finding from the still-running full
bun run test: Vitest reports failures inapps/web/src/routes/settings/mail/MailSection.svelte.test.ts(links selected Mail options through shared identity shared-account, 5,895 ms),apps/web/src/lib/mail/MailSidebar.svelte.test.ts(keeps the sidebar empty of folder placeholders until real folders arrive (#1094), 5,638 ms), andapps/web/src/routes/settings/admin/LicenceGroup.svelte.test.ts(saves a pasted key, clears it from the page, and removes it without changing Users, 6,700 ms;requires confirmation to replace a saved key and lets Cancel keep it, 5,814 ms). These merged Mail and Admin tests are outside the #1186 files. No existing expectation has been changed. The suite is still running; final stacks and totals are pending.Further output from the same full
bun run test:apps/web/src/routes/settings/apps/CalendarFeedsGroup.svelte.test.tsfailsfreezes edits and retries the complete submitted body after assertion(8,798 ms), andapps/web/src/lib/history/VersionHistory.svelte.test.tsfailspreflights an author session and shows the items kept before undo(12,298 ms). Vitest has reported seven failures so far across Composer, Mail, Admin settings, Calendar settings and VersionHistory. They are outside the #1186 files; all assertions remain unchanged. The full suite is still running and its final totals are pending.Additional full-suite finding:
apps/web/src/lib/backgroundGroup.svelte.test.tsfailsoffers theme colour and picture without a shared light/dark toggle(5,761 ms). Vitest has reported eight failures so far across unrelated merged Composer, Mail, Admin, Calendar settings, VersionHistory and background settings tests. No expectation was changed; final suite output is pending.Full web gate finding after origin/dev merge:
Command:
cd apps/web && bun run testVitest summary (verbatim):
Each failed assertion reported
Test timed out in 5000ms. All 11 are outside the Tag rewrite files. The suite ran concurrently with Rust compilation on the shared build host, which may have added contention; no test expectations were changed.The production E2E rerun reached the real 1,000-Note rewrite and saved four progress screenshots (phone and tablet, light and dark). It then hit Playwright's 30 s
setThemedata-themewait while moving to the desktop capture, before checking the completed receipt. I changed the screenshot matrix to seed the review theme in the test User's local settings without writing Appearance during the background rewrite, and added explicit receipt/Undo-journal checks. I am rerunning the driver.The next screenshot retry confirmed that local
userStoragealone cannot select Dark: the rendered state remained Light while the test seam reported Dark and the server Appearance mode was Light. The driver now changes Appearance through the real API on/readyzbefore TagRow mounts. It also checks the completed receipt before mounting the Undo toast, so the toast timer does not run during theme setup.The production run captured all six Undo-toast screenshots. The final assertion then waited for the original page's Undo action after the driver had spent about a minute capturing those six contexts, so its documented eight-second toast had expired. The captured fresh contexts prove the durable receipt still exposes Undo. I am changing the driver to click Undo immediately in a new signed-in context and verify the terminal Undo receipt before the final Tags list/detail captures.
The fresh-context Undo flow completed and restored the source Tag; the run advanced to the final surface screenshots. At phone width, Calendar sidebar capture then timed out because its locator resolved 57 times to a hidden responsive copy of the Tags section after the Show sidebar action. I am selecting the visible section instance and rerunning the complete screenshot matrix.
The visible-section selector still timed out because the phone Tags section is inside the Navigation dialog, not an
aside. The Show sidebar action opens that dialog. The desktop shell and phone dialog use the samesection[aria-labelledby="calendar-tags"]; I am querying that shared section and waiting for the Navigation dialog at phone widths.With the phone Navigation selector fixed, the full run passed progress and Undo screenshots, completed the reverse receipt and reached the post-Undo assertion. That assertion counted matching links across the entire page and found one renamed link. I am scoping it to the Tags card and checking
/api/v1/tagsseparately to distinguish the real list from responsive navigation copies.The scoped check now reads the real
/api/v1/tagsresponse after the reverse receipt reachescompleted. It still containstagperf/renamed. The previous page-wide selector was unrelated to this: the server Index itself reports the renamed Tag. I am adding the reverse receipt's conflict count and per-Tag item counts to the next run before fixing the responsible path.The retained #1186 fixture showed why Undo reported conflicts. The first differing Notes had
dateandlast editedfields added while the server was running its post-startup Note date migration; the journal captured bytes before those fields existed. The run with screenshots had 127 conflicts, while the shorter diagnostic run had 27, matching migration progress. Undo preserved those later writes as designed. I am adding managed dates to the real fixture before server restart so this performance and UI flow measures Tag rewrite work without racing the independent Note migration.The failed sidebar screenshot was a fixture mismatch. The Calendar sidebar only renders Tags in the
area/namespace (areaTagLeavesinapps/web/src/lib/components/tagTree.ts), while the performance fixture usedtagperf/source. The shared Tags list and detail correctly included that Tag, but Calendar had no matching area Tag. I updated the E2E and benchmark fixture to usearea/tagperf/sourceand its renamed and destination siblings so the screenshots exercise the real Calendar surface.Progress for #1186 on
job/tagperf-1186(headb54a24255895cec4582ee8a0288a7dae752ffa72).bun run checkpassed with 0 errors and 1 pre-existing warning inpackages/ui/src/components/calendar/AttachmentDeck.svelte.Screenshot archives: Tags list, Tag detail, sidebar, progress, Undo toast.
Merged origin/dev at
8f89c1458after preserving its #1197 Note-room source preflight and publication hooks in both the legacy and batched Tag rewrite paths. Batched replay republishes an already-written Markdown revision before advancing its cursor, so a stop between file commit and room publication does not leave an open Note stale. The perf ratchet combines this branch's updates with dev's four fewer unresolved-call sites: total 22534. Evidence: cargo fmt --check passed; calternal-tags Clippy passed; 52 calternal-tags tests passed; perf-lint reported 0 violations and 22534 scoped exceptions; bun run check reports 0 errors and 1 existing warning. Final tests and performance run are in progress.Corrected the extrapolation in docs/perf/2026-10-07-tag-rewrite-1186.md: 180.151s × 1000/70 = 2573.59s for rename; 180.193s × 1000/70 = 2574.19s for merge. The separate 10× median targets are 257.36s and 257.42s. The prior 2571s estimate was low by about 2.6s. Commit:
1e0c3a1e4.Extra calternal-collab verification: Clippy passed. The full default-thread test run completed 132 tests and had two elapsed-timeout failures: each_source_writer_keeps_concurrent_typing waited 10s for its injected publication point, and history_preflight_drops_idle_room_after_error waited 5s for room cleanup. The 96-case writer/lock matrix passed. Both failed tests passed alone with --test-threads=1 (34.35s and 2.11s). This suggests host scheduling pressure in the parallel run; no test expectation or production code was changed. The required calternal-tags and calternal-fs gates pass.
Merged-release round 10 (fresh 1,000-Note Home, one destination, 16 Tag readers): rename 46.410s; merge 35.659s. Other-request p95 was 312.22ms during rename and 319.70ms during merge. The matching 12s idle profile had 192 requests, 0 errors and p95 249.10ms at load averages 4.51/3.03/3.07 before the run. Quota probe: 6.76ms; 16-walk estimate: 108.16ms. This sample is well below the 10× duration thresholds, but p95 is above 50ms even at idle; I will report medians after rounds 11 and 12. Raw profiles committed as
e5d67ee6f.Round 11 is committed as
838ebbd73indocs/perf/runs/tag-rewrite-1186-round11.json. On a fresh 1,000-Note Home, rename completed in 44.205 s and merge in 30.337 s. Sixteen authenticated Tag readers returned no errors; their p95 was 343.68 ms during rename and 548.84 ms during merge, above the 50 ms target. The idle profile was already 249.10 ms p95 at load average 4.51/3.03/3.07, so the final three-run report will compare these values without attributing all latency to the rewrite. Quota usage probe was 7.74 ms; 16 batch walks estimate to 123.84 ms per operation.Final report — #1186
Head:
aca393266eb2eda3cbeffcb75dbc7ab40533d5eaPerformance
The measured before values cover 70 source Notes and one destination Note: rename 180.151 s and merge 180.193 s. Linear estimates for 1,000 Notes are 2,573.59 s and 2,574.19 s. These are not full-size before measurements. They set 10x targets of 257.36 s for rename and 257.42 s for merge.
Three interleaved runs used a fresh 1,000-Note Home each time, one destination Note, a 1 GB quota and 16 authenticated Tag readers at one request per second each. The final release server was built locally from the merged source and copied to the perf VM. It completed every operation with 1,000 targets and no concurrent-read errors.
The rename median is 57.45x faster than its estimated before time. The merge median is 84.85x faster. Both pass the 10x time target. The other-request p95 target was below 50 ms. It was not met: the measured medians were 312.22 ms during rename and 502.81 ms during merge. An idle profile on the same Home measured 249.10 ms p95 across 192 requests with no errors. The old p95 values came from a 70-Note Home, so they are not a like-for-like comparison. The final report and raw profiles are in
docs/perf/2026-10-07-tag-rewrite-1186.mdanddocs/perf/runs/tag-rewrite-1186-{round10,round11,round12,idle-merged}.json.Quota usage probes were 6.76, 7.74 and 8.81 ms; the median was 7.74 ms. Sixteen walks estimate to 123.84 ms per operation, about 0.3% of rename and 0.4% of merge. I left the quota path unchanged because this cost is small beside the measured operation times.
Production E2E and screenshots
The production E2E driver passed with 1,000 Notes, completed rename, and exact Undo. It produced 30 fresh macOS captures: Tags list, Tag detail, sidebar, progress and Undo toast at phone (390 px), tablet (820 px) and desktop (1440 px), in light and dark themes. The PNGs are local at
artifacts/tag-rewrite-1186-final/and are not committed. The screenshot archives already attached to this issue are:Gates
Commands ran after merging
origin/dev. Output excerpts are verbatim.The two full
calternal-collabfailures were timeouts in the concurrent typing and idle-room cleanup tests. Both passed when run alone with one test thread. No assertions or expectations changed.bun run checkreports one existing empty CSS ruleset warning inpackages/ui/src/components/calendar/AttachmentDeck.svelte:1055.UX gaps closed
UX gaps left
calternal-collabtest run had two timeout failures; the two focused reruns passed.Decisions
For the merge round
Run
tests/adversarial/run.shagainst the local server. It must cover the full XUser, authorization and robustness matrices for the merged branch. The verification policy defers those matrices from this job.Continuing #1186 on
job/tagperf-1186, headaca393266, base0419170fe456b58614befcb12d9c9d255118f1c0. New target: durable Index intent at acceptance, bounded source replay, immediate Note reads and exact Undo. Existing batch writer already uses filesystem-wide flushes; current acceptance only enqueues and Index updates follow file batches. No pushes or deploys.Progress: committed the compact sidebar count-slot fix as
503868bec; focused web tests:Test Files 2 passed (2)/Tests 11 passed (11). Backend acceptance regressions passed:test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 52 filtered out; finished in 30.67s. The queue-only acceptance regression failed first with old memberships still present. The new path uses one FULL SQLite transaction for source witnesses, the queue receipt, Tags memberships and Notes memberships. Markdown editor reads finish their pending source before returning an ETag. The existing legacy receipt test found that saved batches can start off the normal 64-file grid; the inverse now follows the actual saved journals. Final gates and release measurements remain pending. No performance target is claimed yet.#1186 checkpoint
Branch
job/tagperf-1186, durable intent commit56d97d94f, immediate UI refresh commit9bfa982a7.git fetch originand the one requestedgit merge origin/devcompleted:Already up to date.Tags migration 7 is free on origin/dev.Acceptance now commits the owner-scoped source identity/hash witnesses, queue receipt and Tags/Notes memberships in one FULL SQLite transaction. It performs no Markdown reads. Bounded worker batches use the existing checked calternal-fs staging and syncfs protocol, retaining exact Home journals until completion. Notes reads finish their pending source before returning a real-byte ETag.
Review found and fixes cover: plan without checkpoint after crash; Undo before the first worker lease; replacement Note identity at an old path; moved Notes; accepted inverse projection after reconcile; retry after a lost acceptance response. A further fix now blocks a new operation while a cancelled/dead acceptance still owns source changes, and resolves identities for inverse batches as well.
Verification evidence before those last focused fixes:
Production web build exited 0. Final per-crate gates and web check/test are running. Release measurements and screenshot capture remain; no timing target is claimed yet.
Decision: use the existing two syncfs barriers per source batch (staged data before the filesystem write-ahead record, then namespace publication before checkpoint). Directory-only fsync cannot make the staged file contents durable. WebDAV/CalDAV may briefly read old physical bytes; this is recorded in DESIGN §2.
#1186 recovery finding and correction
The durable intent must also cover early cancellation, a lost Home checkpoint, and a Note moved while its journal is pending. The current recovery changes keep the original stable Note identity, journal the current path, create a missing checkpoint independently of the plan, and block a second forward intent until a cancelled accepted intent is resolved. Undo restores only matching byte revisions and consumes its original receipt. A newer edit is preserved, including an edit that restores a Tag after an earlier skipped journal entry.
The focused regressions also include actual subprocess SIGKILL at the journal and durable-replacement boundaries, restart and exact inverse replay. The full touched-crate gates are running. The read-only review found no remaining crash, data-loss or security blocker; this is not a passing-gate or timing claim.
cargo clippy -p calternal-plugin-notes --all-targets -- -D warningsfinished successfully. The exact performance guard refresh passes:The ratchet fell from 22534 to 22532; no threshold was raised. The two Notes read boundaries explicitly remain content reads with bounded-source proof references. Release timing and screenshot measurements remain outstanding. I interrupted the cold release build to let the required crate gates run before resuming it.
#1186 checkpoint at
0b76f61a6The branch now has separate commits for compact sidebar progress, durable-intent acceptance and replay, immediate accepted-membership refresh, the revised benchmark, production screenshot coverage, and the measurement method. Recovery and pending-editor-read corrections await their final crate gates before commit.
The Notes test build is still compiling its test target. At 19:18 CEST its rustc process had run for about 20 minutes and consumed about 103 CPU seconds. The host load average was about 80. The cold release build was paused to release the Cargo lock for these gates. No new release timing or screenshot evidence exists yet; the previous 44.798-second Rename median remains the old-worker baseline, not evidence for the new target.
The web test run now uses two workers and a 30-second command-line timeout because default five-second timeouts failed under this load. No assertion or existing test expectation was changed. The corrected performance guard reports zero violations and 22532 scoped exceptions. Final Svelte checking and full tests remain running.
#1186 finding: per-Note source callbacks must not restore a whole intent
An accepted 1,000-Note intent stays present while the source worker emits Note updates. The public Tags
index_markdownhook originally restored all 1,000 candidate memberships after each individual Note projection. That could repeat the large membership update 1,000 times.The correction scopes an incremental callback to its own path. Full reconciliation still restores the complete intent. Inverse parsing also happens before the SQLite writer transaction. A regression models three stale projections and proves one callback repairs one Note, while full reconciliation repairs all three. This bounds the SQL update work to the changed source; intent deserialization still reads the packed journal.
New viewer-Share acceptance coverage passes:
The new quota test already proved an exact one-byte-over-limit refusal without any source or usage change. Its final Undo setup used the wrong stored queue state; it is corrected to
dead. The SIGKILL fixture now keeps a stable executable copy, because another Cargo gate can replace the running test binary. Both corrections and the scoped projection regression are being rerun. No timing or READY claim yet.#1186 tagfast: NOT READY FOR MERGE
Head:
46037c0fbonjob/tagperf-1186. Started fromaca393266. Fetched and mergedorigin/devonce; it was already up to date. No push or deploy. The job reached its four-hour limit; the remaining verification is listed below.Built:
Files:
crates/calternal-tags/src/{lib,index,rewrite}.rs,crates/calternal-tags/migrations/0007_tag_rewrite_acceptance.sql,crates/plugins/notes/src/{lib,store}.rs,crates/calternal-collab/src/session.rs,apps/web/src/lib/components/TagRow.svelte,apps/web/src/lib/stores/tagRewrite.svelte.ts, its.test.ts,apps/web/e2e/tag-rewrite-1186.mjs,bench/tag-rewrite-1186.py,contracts/perf/{registry,exceptions,adoption-1058,ratchet}.json,docs/DESIGN.md,docs/perf/2026-10-07-tag-rewrite-1186.md.Gate output, verbatim result lines (full logs remain under
artifacts/tagfast/):cd apps/web && bun run build— passed:cargo fmt --check— exit 0, no output.Tags clippy:
Tags full test, with the shared compiler wrapper bypassed after its deleted-temp-directory failure:
Notes clippy:
Notes full unit and integration tests:
Collaboration clippy:
Collaboration full test — FAILED:
The failure is
session::external_persistence_race_tests::each_source_writer_keeps_concurrent_typing, waiting ten seconds for the Tag writer publication hook. A one-thread focused retry also timed out. No expectation was changed:Related source/typing integration tests pass:
Server clippy:
Server test: interrupted during compilation at the job limit; no passing result.
bun run check— exit 0:The warning is the existing empty
.attachment-row:focusruleset in AttachmentDeck.svelte. The exact performance ratchet decreased from 22534 to 22532; no threshold increased.bun run test --maxWorkers=2 --testTimeout=30000— passed:The initial runs hit existing five-second timeouts under host load around 80. The final command changes the execution timeout only; assertions and existing expectations remain unchanged.
Correctness coverage: actual SIGKILL at journal and durable-publication boundaries, a randomized interruption window during application, old-or-new file checks, restart/resume, exact Undo, newer edits, moved/replaced Notes, an exact one-byte quota refusal, and viewer Share isolation. The read-only review found no crash/data-loss/security blocker in the recovery diff.
Performance and known gaps:
Expected cost: Rename acceptance handles 1,000 Index witnesses in one transaction with no Markdown reads. Source publication handles 1,000 Notes in 16 batches of 64, with at most eight independent file tasks. Undo reads the exact byte journals with the same concurrency bound before accepting its inverse. Per-Note projection repairs update one source, but still deserialize the packed intent.
UX gaps closed: compact count-slot progress, accepted Tags refresh before source completion, pre-existing merge destination memberships survive Undo refresh, and editor reads receive real durable revisions.
UX gaps left: mixed-source Undo intent, the already-open-room timing bound, and the missing complete screenshot walkthrough.
Decisions: reuse Root's two syncfs barriers, rather than directory-only fsync; keep exact byte journals before publication; finish an editor's requested source before returning its ETag; serialize a cancelled accepted intent until Retry/Undo resolves it; scope incremental projection repair to one path. WebDAV/CalDAV can briefly see old bytes, as recorded in DESIGN §2.
Remaining work / for the merge round or a continuation:
cargo test -p calternal-collab -- --test-threads=4after the fix.cargo test -p calternal-server -- --test-threads=4.cargo build --release -p calternal-server -p calternal-tags --bin calternal-server --example tag_rewrite_1186_seedhere. Use the private fixture setup and locked run prototypes underartifacts/tagfast/; never print their credential file. Run SSD and HDD phases only throughperf-run calternal tagfast 20 -- <command>, with HDD usingbench/hdd-emu.sh run-limited. Record five samples per operation and actual browser click p95.CALTERNAL_SERVER_BIN=<release binary> TAG_REWRITE_SEED_BIN=<release seeder> TAG_REWRITE_SCREENSHOTS_DIR=artifacts/tagfast TMPDIR=<worktree>/target/tmp node apps/web/e2e/tag-rewrite-1186.mjs. Review real during/after evidence at 390/820/1440, light/dark, macOS. A fast worker may finish before a new review context opens; repeat real operations as needed to capture each active phase.tests/adversarial/run.shagainst the combined real server must prove malformed/oversized input, authorization, quota and cross-plugin behaviour. Full adversarial matrices were not run in this performance job, per the verification policy.Cleanup: own remaining server build work was stopped. Cargo clean and deletion of the web build output are running; their final result is appended below.
#1186 final cleanup: head
46037c0fbba8e4c1186f57e7243d20ef6c4ba373, clean worktree. Own server compilation was stopped; web build output was removed. Cargo clean output, verbatim:The final report above remains NOT READY FOR MERGE. Performance targets, screenshot evidence, complete server tests, mixed-source inverse intent and the collaboration publication-hook timeout remain outstanding. No push or deploy.
Continuing tagfast2 on job/tagperf-1186 at
46037c0fbb. Read the contracts and predecessor report. First checking the unchanged concurrent-typing publication regression against origin/dev; then removing repeated quota walks before release measurements. No pushes or deployment.Finding: reserve_batch_write_quota scans Home once per batch. The continuation now prepares an intent-wide source byte allowance from candidate sources only (bounded reads) and exchanges its reservation for actual bytes after each durable commit. This keeps unrelated writes quota-aware between batches. Regression coverage is being added for partial commits and exhausted allowances. The required origin/dev merge is committed at
5e2ee2aa6; it preserves both sidebar context menus (#1222) and rewrite progress. Exact performance pins refresh to 22532, with no threshold increase.Blocker isolation: the unchanged each_source_writer_keeps_concurrent_typing test PASSES on the origin/dev source snapshot (all seven writer families, including Tag rename and Undo). Result: test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 133 filtered out. The branch reproduction is compiling. The branch uses two filesystem-wide syncfs barriers even for a singleton Tag edit, unlike the baseline checked per-file writer; that is the leading publication-delay suspect, to be confirmed by the unchanged test.
The current continuation test also passes unchanged (14.72 s), so the predecessor timeout did not reproduce under this host load. The source snapshot passes in 13.47 s. I am reducing the singleton writer’s filesystem-wide flush coupling, without moving the publication hook or changing assertions/timeouts, then running the full collaboration suite. Filesystem quota gates have passed Clippy and unit tests (101 passed, 1 ignored); integration tests are finishing.
Quota slice committed at
bc25beff6. All 63 Tags tests pass unchanged, including mixed Markdown/XMP/folder sources, legacy partial journals, restart, moved identities and exact one-byte quota refusal. Filesystem gates: 102 unit tests pass (1 ignored), plus integration groups 1/1/53/2 pass. Singleton crash injection passes at every journal step, preserving source and Version. The full collaboration run has passed the unchanged concurrent-typing test; its 96-case writer-lock matrix is still running. Web full suite: 297 passed files, 2119 passed tests.Finding: the server upgrade test fails only because its exact pending frontier omits calternal-tags migration 0007 added by this issue. The focused failure lists identical left/right frontiers except that one entry. I am adding that receipt to the pending and final-frontier pins; deployed SQL, original receipt equality, data-preservation assertions and timeouts stay unchanged.
Server gate evidence: initial full suite completed (270 passed, 2 failed, 12 ignored). One failure is the exact Tags migration pin, now corrected. The other is SLOW-only: startup_search_reconciliation_keeps_calendar_writes_responsive_on_large_home reported Calendar write p95=17496 ms versus its unchanged 10000 ms budget during a 20000-file startup. No assertion or timeout was weakened. Final clippy and the focused migration regression are running; the final full run follows.
Progress at
2b42e12d6: final calternal-server suite completed successfully: test result: ok. 272 passed; 0 failed; 12 ignored; 0 measured; 0 filtered out; finished in 339.53s; integration groups each passed (37.94s and 0.37s). Source quota admission is now once per worker attempt. Important remaining limitation: Home byte journals/checkpoints still go through ordinary Root writes, whose quota checks scan the Home; these are still per-batch O(Home) costs and must not be described as eliminated. VM measurements are queued through perf-run; no unlocked measurements or builds ran there.VM continuation finding: the first paired 1,000-Note production-SPA sample completed on the branch in 22,887.9 ms, with first paint at 900.3 ms and concurrent Tag-list p95 35.09 ms (384 reads, no errors). The shared origin/dev release did not finish within the 600 s cap and had no renamed Tag paint within 5 s. These are one sample per variant, not the required three-sample result. The source reservation is now once per worker attempt, but ordinary durable Tag journal/progress writes still invoke Root Home quota checks. This remaining O(Home) work and the missed paint/durability targets keep the branch NOT READY. Browser review also found that an initially hidden item-menu surface loses synchronous keyboard focus inside the phone Navigation dialog; a shared Menu focus option now uses the existing post-placement focus path. Focused tests passed; production-build review is next.
Finding from the #1374 rerun, branch head
94b056bfe9b49d24aee6da2412a88dd9f955f935, measured on the perf VM with the shared release server fromd395b6e25:Renaming the Tag across 100 Notes did not acknowledge or become visible before the 120,000 ms harness timeout. The durable lower bound is 120,186.76 ms, against the 500 ms visibility target. The fixture had 100 tagged Notes. This is not a successful completion time. The call path is
crates/calternal-tags/src/lib.rs::rename_taginto the rewrite worker incrates/calternal-tags/src/rewrite.rs; this confirms the existing #1186 cause, so I am not filing a duplicate.Quota continuation: commit
45ec97eafadds Root::write_from_batch_allowance. Normal file/Version durability remains; journal bytes debit the admitted ledger without walking the Home. The full calternal-fs suite passes (104 unit tests, 1 ignored, plus integrations). New tests cover staged-source budget preservation, oversized journal refusal before install, allowance exhaustion, cross-Home rejection and a reduced quota. The Tags worker now admits candidate source bytes plus serialized journal/checkpoint bounds once, before its first batch write. An initial combined admission changed the projected value in accepted_quota_refusal_is_exact_and_preserves_sources; the assertion was not changed. The implementation now retains the exact source-only refusal amount when sources alone exceed quota, using the same admission measurement. Its focused retry passes (1 passed; 62 filtered; 7.39 s). Full Tags/server gates are running. The 1,000-Note VM profile sampled SQLite VM execution (6.95%) and ONNX GEMM (6.54%) as the largest leaf symbols; background work is part of this fixture. The 5,000-Note phase is queued behind another project job that declared a 50-minute VM lease.Correction to my previous comment, branch head
95223dde0194a91a9b7783f4e814e1943e3384ce: the rename request returned HTTP 200 and was acknowledged in 382.30 ms. The visibility poll did not observe the new Tag before its 120,186.76 ms deadline. The rewrite status returnedcompletedin the following completion check, but that check did not record an exact visible-state time. The measured visibility is therefore a lower bound, not an unacknowledged request.The checkpoint row's
action_acknowledged:falsewas a harness bug: the timeout callback hard-coded that field. I fixed the runner so future rows record whether the request returned (commit95223dde0). This already-running process loaded the earlier code. Its summary row records the HTTP 200 and 382.30 ms response time; the final CSV will include an explicit correction row.Final full server gate completed and did not pass. The unchanged 20,000-file Calendar write profile failed in its isolated subprocess:
A focused retry with the documented SERVER_WORKER_STACK_SIZE=4 MiB also failed only its latency budget:
One direct diagnostic invocation initially omitted RUST_MIN_STACK and overflowed the default 2 MiB test stack. wire.rs documents that deep live-app future and sets 4 MiB in the normal isolated runner (#549). The retry used that existing configuration and did not crash. No assertion, fixture or timeout was changed. This is SLOW evidence, not a clean final server gate.
The final web suite passed:
The final focused concurrent-typing publication test passed after the shared quota change, with its assertion and timeout unchanged:
The same test passed on the origin/dev snapshot (13.47 s) and on the original job head before my changes (14.72 s). The earlier failure was not reproduced. The complete collab suite passed earlier in this continuation; the final shared-FS change was followed by this focused publication regression. No claim is made that host I/O coupling caused the predecessor failure.
Performance lint now reports:
Commit
7d7841ba8refreshes exact live hashes and synchronizes existing #1058 adoption entries. The ratchet count is unchanged.The final quota binary is now being measured under perf-run calternal on the perf VM. Its SHA-256 is 50bb7fc56527c88f3edda5d0d06f2a620e2d2c85ee97ee25e12dbc89cb25adea. The common saved production SPA includes early validated Rename projection. Its later sidebar focus-only fix is reviewed separately in production screenshots.
First final 1,000-Note sample (99 Hz cycles profiling enabled):
This sample meets the paint and Tag-list p95 targets. It misses the 2-second durability target. The fixture has a cold Notes Index and startup work overlaps the rewrite; this is not an all-route steady-state claim.
First final 5,000-Note sample: paint 110 ms, durable receipt incomplete at 120,002.61 ms, Tag-list read p95 146 ms, peak RSS 373,035,008 bytes. The incomplete time is a lower bound.
The second profile has ONNX matrix work at 8.23%, sqlite3VdbeExec at 6.15%, malloc at 2.17% and SQLite JSON translation at 2.09% of leaf samples. These samples cannot separate the rewrite from startup work. No third optimization/measurement round is started. The remaining paired samples are running in the same locked phase. Status remains NOT READY because the owner durability target is not met.
NOT READY —
a3db565a48b148f79f5dcee3b50fa721a24259f9Built
Files:
crates/calternal-fs/src/{root,quota,write}.rs;crates/calternal-tags/src/rewrite.rsand its existing seeder;crates/calternal-server/src/upgrade_tests.rs; TagRow, ItemActionMenu, inputModality and tagRewrite store/tests inapps/web/src/lib; shared TimeGrid, Menu and FloatingSurface inpackages/ui;apps/web/e2e/tag-rewrite-1186.mjs;bench/tag-rewrite-1186{.py,-browser.mjs}; exact performance contracts; DESIGN durability notes;docs/perf/2026-10-08-tagfast2-1186.mdand both raw round profiles.Shared controls used: existing TagRow inline field/count slot, ItemActionMenu, Menu/MenuItem, FloatingSurface, ConfirmSheet, Pill and the shared focus helper. No new visual style was added in this continuation.
Measurements
Final release SHA-256:
50bb7fc56527c88f3edda5d0d06f2a620e2d2c85ee97ee25e12dbc89cb25adea. Built locally; copied to the perf VM. Every measurement ran underperf-run calternal. Load averages are in the committed raw profiles. No build ran on that VM.Operation p95 uses nearest rank across three samples; it is the largest sample. All concurrent reads had zero errors. Completed operations verified every source file. Capped times remain lower bounds, not completed samples.
The earlier shared-release baseline had three incomplete 1,000-Note runs and three incomplete 5,000-Note runs. First samples had 600 s caps; later ones had 120 s caps. The initial 1,000-Note baseline/job pairs were interleaved. Final 1,000-Note reruns preceded the final 5,000-Note job samples. The first 5,000-Note baseline used the older SPA; later baseline/job samples shared the saved final SPA. That SPA includes early optimism and menu focus fixes, but precedes the final sidebar wrapper-only focus fix shown in the attached captures.
The fixture has a cold Notes Index and startup work overlaps the rewrite. Sixteen readers send one Tag-list request per second each. Other route classes, a request storm and an already indexed Home were not measured. The generic Tag-route number in
docs/perf/baseline.jsonis a different workload. No completed baseline median or speedup is claimed.The second profile has ONNX matrix work at 8.23%, SQLite VM work at 6.15%, malloc at 2.17% and SQLite JSON translation at 2.09% of leaf samples. It does not isolate the rewrite from startup work. No third optimization round was started.
Expected worker cost: one O(Home) admission walk per attempt, O(N) candidate reads with eight workers, and ceil(N / 64) source batches (16 / 79 here). Ordinary acceptance writes retain their existing checked quota path.
Publication failure
The exact concurrent-typing test passed on origin/dev (13.47 s), the starting job head (14.72 s), and after the final shared-FS change (15.37 s), with the assertion and timeout unchanged. The complete collab suite passed earlier. The predecessor failure did not reproduce; no root cause is claimed.
UX gaps closed
Known gaps / UX gaps left
Decisions
Gates (verbatim excerpts)
cargo fmt --check: exit 0, no output. Full logs as run are attached ingates-verbatim.log.gz, including the exact command, complete output and stage notes.cargo clippy -p calternal-fs --all-targets -- -D warnings;cargo test -p calternal-fs:cargo clippy -p calternal-tags --all-targets -- -D warnings;cargo test -p calternal-tags:cargo clippy -p calternal-collab --all-targets -- -D warnings;cargo test -p calternal-collab:cargo clippy -p calternal-server --all-targets -- -D warnings;cargo test -p calternal-server -- --test-threads=4:The final collab focused regression:
Final
cd apps/web && bun run check:Complete web suite before the final wrapper-only focus fix, then that fix's focused regression:
Final production build:
Scoped Notes adversarial round and final-release Tags boundaries:
The full server gate's unchanged child profile reported:
The focused retry used the documented 4 MiB worker stack:
One earlier direct diagnostic invocation omitted that stack setting and overflowed the default 2 MiB test stack. The normal subprocess runner already supplies 4 MiB; the correctly configured retry did not crash. The gate remains failed; this is not a passing result.
For the merge round / continuation
bash tests/adversarial/run.sh: full authz, concurrency, cross-plugin and robustness matrices.cd apps/web && bun run test --maxWorkers=2: combined branch suite including the final wrapper regression.node apps/web/e2e/tag-rewrite-1186.mjs: finish the real Notes/visible Undo path and comparisons with matching production server/web builds. Do not weaken its assertions or timeouts.cargo test -p calternal-server -- --test-threads=4: resolve/verify the existing 20,000-file latency profile and complete the full server gate.Evidence attachments
All 24 sidebar PNGs use the actual production SPA and real server at 390/820/1440, light/dark, with macOS emulated. They cover mouse opening, Shift+F10 opening, real pending/running progress and completed count. No screenshot was committed. Claude/orchestrator remains the visual reviewer.
sidebar-mouse-rename-desktop-dark-mac.png
sidebar-mouse-rename-desktop-light-mac.png
sidebar-mouse-rename-phone-dark-mac.png
sidebar-mouse-rename-phone-light-mac.png
sidebar-mouse-rename-tablet-dark-mac.png
sidebar-mouse-rename-tablet-light-mac.png
sidebar-shortcut-rename-desktop-dark-mac.png
sidebar-shortcut-rename-desktop-light-mac.png
sidebar-shortcut-rename-phone-dark-mac.png
sidebar-shortcut-rename-phone-light-mac.png
sidebar-shortcut-rename-tablet-dark-mac.png
sidebar-shortcut-rename-tablet-light-mac.png
sidebar-progress-desktop-dark-mac.png
sidebar-progress-desktop-light-mac.png
sidebar-progress-phone-dark-mac.png
sidebar-progress-phone-light-mac.png
sidebar-progress-tablet-dark-mac.png
sidebar-progress-tablet-light-mac.png
sidebar-done-desktop-light-mac.png
sidebar-done-phone-dark-mac.png
sidebar-done-phone-light-mac.png
sidebar-done-tablet-dark-mac.png
sidebar-done-tablet-light-mac.png
gates-verbatim.log.gz
sidebar-done-desktop-dark-mac.png
NOT READY —
a3db565a48b148f79f5dcee3b50fa721a24259f9Independent read-only data-safety review started on job/tagperf-1186 at
a3db565a48. Reviewing the diff and running independent real-server probes; no author reports or result files used. No tracked edits or ref changes. Evidence: artifacts/tagrev-findings.md.Independent review progress: head
a3db565a48remains unchanged. The reviewed server build, production web build and cargo fmt --check passed. The first 14,010-Note fixture setup timed out before rename (120 s, then 1,200 s), so these runs are not rename evidence. The current probe seeds a 1,000-Note set and a 5,000-Note set, and reuses them with fresh byte baselines for crash and failure tests. About 4,000 Notes are indexed so far. No tracked edits, commits or ref changes. Evidence accumulates in artifacts/tagrev-findings.md. A Playwright timeout exposed a disposable test session in the first run; it was scrubbed from artifacts and its test Instance was deleted to invalidate it. No production credentials were involved.P1 — Accepted rename at quota blocks Note access and Undo
Evidence:
TMPDIR=$PWD/target/tmp node artifacts/tagrev-quota.mjsagainst the reviewed server binary. Create 10 Notes taggedreviewquota/a; set the User quota to exact Home size (2,130 bytes); restart to reload policy; POST/api/v1/tags/rewrites(reviewquota/a→reviewquota/z, confirmed). Acceptance returned 200/pending. Worker returned failed; GET an affected Note returned 500; POST receipt Undo returned 500/internal/tag operation failed. Every source was byte-for-byte unchanged. Raising quota to 1,000,000,000 and restarting permitted Undo (200, completed, 10/10 exact bytes).Impact: quota exhaustion can strand an accepted operation and make existing Note reads unavailable. This is a correctness failure, not a slow-host finding. Source content loss was not observed. Final projection read showed the old tag; do not claim permanent new projection from this case.
Repro and machine-readable evidence: artifacts/tagrev-quota.mjs; artifacts/tagrev-quota-results.json; artifacts/tagrev-quota.log.
P1 — Failed rewrite leaves the early UI projection inconsistent with files
Real production browser UI, 256 Notes: rename
reviewfive/ztoreviewfail/z; after 64 new sources, SIGSTOP the server, chmod the disposable Notes folder 0500, SIGCONT, then restore permissions after terminal failure. Status: failed/current=64/total=256/can_undo=true. Sources: 64 new, 192 old. GET Tags projectedreviewfail/zand its child for all 256 Notes. Browser: old row=0, new row=1, Undo button=1, failure toast visible. The UI did not roll back the early projection to source truth. Screenshot: artifacts/tagrev-focused-midway-failure.png.Click the actual failure toast Undo: completed 256/256, every source restored byte-exact to its pre-rename value. This case demonstrates the projection inconsistency, not failed Undo or source loss.
Repro:
TMPDIR=$PWD/target/tmp node artifacts/tagrev-focused.mjs; evidence: artifacts/tagrev-focused-results.json and artifacts/tagrev-focused.log. The same runner also proves all three SIGKILL windows on 128 Notes (0/128, journal before publication, 64/128 durable prefix), exact convergence, consistent final projection and idempotent retry.tagfix3 started on job/tagperf-1186, base
a3db565a48. Reading the complete independent review and its probes; controlled 128–256 Note reproductions precede fixes. No pushes or deployments. Will report each of the four safety items separately with source-byte and job evidence.Controlled pre-fix run of items 3/4: 128 owner Notes plus one Daily note and 10 untouched foreign Notes with the same Tag, reviewed binary
a3db565a4. Removed the review runner's deliberate baseline/busy writes to foreign Note 0; waited for BOTH live markers to echo to the other collaborator before inspecting files. Rename completed 129/129, conflicts=0; both markers persisted and both editors retained both markers; 127 plain Notes matched exact expected bytes; Journal baseline and concurrent append persisted. All 10/10 foreign sources stayed byte-identical and kept the old Tag; foreign receipt GET returned 404. artifacts/tagfix3-live-results.json. The original 10th foreign body was the runner's explicitly edited latency target, not an owner rename target. Original missing marker 1 had only local visibility (peer=false), so it was not proven acknowledged; controlled peer-confirmed case has no loss. Cross-user regression will also cover Undo.Item 1 independently reproduced on 128 Notes using the reviewed binary: SIGSTOP at 64 rewritten files, chmod Notes to 0500, resume. Receipt failed at 64/128 with Undo. Actual files: 64 old, 64 new; GET Tags showed new=128, old absent. An additional terminal GET of an untouched Note returned 200 but rewrote that file to the new Tag despite the failed receipt. artifacts/tagfix3-failure-before.log. The fix must therefore disable editor-side publication as well as repair both Tag and Notes memberships; keeping only the failure toast is insufficient.
Item 2: restarted the retained 5,000-Note disposable Instance (same reviewed binary, no new fixture or load generator). The exact job moved from leased/attempts=3/max_attempts=3/current=4992/total=5001 to dead with the same progress and last_error. artifacts/tagfix3-lease-recovery.log. This proves expired final-attempt recovery already works: a claimed third attempt is not a finished third attempt. No permanently leased job reproduced. The original generic 'tag Index operation failed' does not record a SQLx class/code, so its underlying Index error cannot be recovered from that field; adding content-free class/code diagnostics rather than inventing a cause. The new source-backed repair also handles terminal orphan/cancelled intents, with Undo retained.
Item 4 denominator correction: the original metric is
foreign.notes.slice(1).filter(...).length; its maximum is nine, and it reported nine. It excludes Note 0 by construction. That Note was deliberately edited by the foreign User in 20 baseline and up to 20 busy conditional PUTs. The retained source keeps the original body and old Tag plus the runner's B baseline/B busy five lines; no owner-rename replacement appears. The new controlled run compares the full ten-element array with no foreign writes and reports 10/10 exact. This is NOT REPRODUCED, not a cross-User data change.Safety slice committed:
b764854b9. Failed attempts now switch their retained intent to source-backed memberships and repair the saved candidates in bounded batches before settlement. Both Tags and Notes rows are repaired; terminal Note reads stop on-demand publication. Startup and the receipt route repair exhausted orphan/cancelled intents, retaining Retry and exact Undo. A weak keyed mutex shares repair across concurrent receipt polls. GET Tags still performs no source IO. No migration or dependency was added.Focused crate gates (verbatim):
cargo fmt --check: exit 0, no output.cargo clippy -p calternal-tags --all-targets -- -D warnings:cargo test -p calternal-tags -- --test-threads=4:All new regressions passed: read-only failure at 64/128 with both projections matching files and exact Undo; exhausted final orphan lease with visible failed receipt/Undo; same-Tag foreign Home exact through forward and inverse. The first run found a test-fixture error in the new foreign-Undo test (the fixture had not settled its forward queue lease); fixed the fixture's queue lifecycle, with no existing expectation changed. Server gates and the real-server regression follow.
Web test gate passed (verbatim):
bun run checkhas zero Svelte errors so far, but perf-lint found exact hashes moved in Notes read consumers of the changed shared Tag helper. Refreshing only the existing live hashes; no rule, limit or ratchet increase. The earlier attempt to put source repair inside GET Tags was removed: repair belongs in the failed worker/startup/receipt paths so ordinary Tag lists do no source IO.Perf-pin refresh committed separately: the two existing
read_visible_sourcecall sites in Notesget_noteandopen_filenow resolve asio.unresolved-callinstead ofio.content-readafter the shared helper change. Same sites and hashes; the exact #1058 checkpoint was refreshed. Total exceptions remain 22,532; per-rule counts move by -2/+2 to match live entries. No scanner rule or source contract was weakened.Verbatim validation:
Controlled terminal recovery evidence for tagfix3 (#1186), source fix
b764854b9, regression22eda56b3:Controlled collaborative/cross-User follow-up, source fix
b764854b9:Capture coverage correction: the first post-fix fixture used
reviewfail/*, which populated the Tags page but not the area-Tag sidebar. Its source/API/Undo checks passed, but that capture did not prove the sidebar claim. The probe now usesarea/reviewfail/*and requires the actual mounted sidebar leaves before capture. I am rebuilding the evidence server after the earlier cleanup and will report that result separately. No implementation behavior or existing test expectation changed.Server gate result: 271 passed, 1 failed, 12 ignored. The only failure is the existing 20,000-file startup Calendar-write latency test: p50=17,320ms, p95=17,874ms against10,000ms. This is a SLOW-only local-host finding. The assertion is unchanged; no repeated full suite or timing-budget increase. Full output: artifacts/tagfix3-server-test.log.
tagfix3 — Tag rename data safety (#1186)
Branch:
job/tagperf-1186. Head:be82a149a5.Merged
origin/devonce before final gates (7970a90e7). No push or deploy.Built
Failed Tag rewrites retain the completed source prefix and exact Undo. Their Tag and Notes projections now match source files. A failed or cancelled Note read cannot publish more rename writes. Startup and terminal receipts resume interrupted projection repair. Repair reads only saved candidates, in batches of 64 with at most eight concurrent reads. GET Tags remains an Index-only read.
Changed files:
crates/calternal-tags/src/rewrite.rs: source-backed repair, durable repair flags, safe SQLx class/code diagnostics, three regressions.crates/calternal-tags/src/lib.rs: startup recovery and owned terminal-receipt repair.tests/adversarial/tag-rewrite-failure-1186.mjs: focused real-server fault, source counts, mounted UI counts, hostile requests, foreign User checks and exact Undo.bench/tag-rewrite-1186.py: 20 steady terminal reads and a 16-request burst, at most eight readers; separate latency/CPU/RSS sample.contracts/perf/{exceptions,adoption-1058,ratchet}.json: exact refresh of two existing Notes consumer classifications. The exception total remains 22,532. No rule changed.Item results
notes.slice(1)and could report at most9 untouched bodies. The excluded tenth Note received 20 baseline PUT markers plus 20 busy PUT markers, deliberately sent by that foreign User; its old Tag remained. After the frontmatter separator, its body equals the original fixture body plus those 40 submitted markers in order, byte-for-byte. In both controlled runs with those writes removed, all 10 foreign bodies are exact. The new Rust and real-server Undo regressions also compare all 10 foreign Notes. Foreign receipt and Undo requests return 404.UX gaps closed
The failure view shows actual old/new counts. Failed Note reads stop applying rename writes. Undo restores exact bytes. No new UI styles or controls: existing TagRow, Tags page/sidebar and shared failure Toast show the corrected API state.
Six production-build captures use Mac platform emulation:390,820,1440px, light and dark, without a page reload concealing stale rows. Files:
artifacts/tagfix3-failure-captures/failure-{390,820,1440}-{light,dark}.png. Visual review belongs to the orchestrator. The Forgejo CLI exposes no attachment operation, so captures remain in this worktree for attachment.Decisions
Expected repair cost: O(saved candidate bytes + Tag rows), ceil(N/64) batches, eight concurrent reads. It never scans unrelated Home sources. Steady Tag reads retain their existing Index query cost.
Gates
cargo fmt --check: exit 0, no output.cargo clippy -p calternal-tags --all-targets -- -D warnings:cargo test -p calternal-tags:cargo clippy -p calternal-server --all-targets -- -D warnings:cargo test -p calternal-server: exit 101; one SLOW-only existing timing assertion failed. No assertion changed.cd apps/web && bun run check: exit 0.cd apps/web && bun run test -- --maxWorkers=2: exit 0.scripts/perf-lint test: exit 0.Focused real-server #1186 regression: PASS.
tagperf4 started on job/tagperf-1186, base
e1672b919c. Scope: full-quota Undo on 128 Notes and three interleaved origin/dev/candidate performance pairs at 1,000 and 5,000 Notes. No UI code changes. Prior quota evidence reports 500 on Note read and Undo with unchanged sources; current admission reserves remaining intent bytes before publication. Will test both initial exhaustion and quota reduction after a durable prefix.tagperf4 finding: Tags maps calternal_fs::Error::QuotaExceeded to HTTP 500 and records only "tag filesystem operation failed" in worker errors (crates/calternal-tags/src/lib.rs). The job changes this to HTTP 507 with "Home storage quota reached; free space and retry" for admission and queue diagnostics. The new 128-Note real-server probe reached a 64-Note committed prefix against the shared origin/dev binary. At exact Home quota, Undo returned 200 then failed after a partial inverse; this is baseline evidence, not a verdict on the reviewed branch. The regression now checks whole source versions and source-backed Tag counts, and requires byte-exact Undo after quota restoration. Reviewed-server compilation and focused unit tests are running. No UI code changed.
Performance setup: copied origin/dev
cc1af3c12release to the perf VM; reused fresh disposable copies of the existing 1,000/5,000-Note fixtures. Added an independent User and a 4 Hz Note-write sampler, and direct CDP input with separate sidebar/Tags-page paint clocks. Initial run hit the old browser harness 30-second cap and is retained as a failed setup attempt. Corrected run holds perf-run. macOS reservation is occupied (holder start 2026-10-08T22:01:55Z, stated 60 minutes); no foreign reservation was removed.tagperf4 progress: head
8c42a48f0; origin/devcc1af3c12merged ina77e71920. Full-quota real-server regression PASS: 128 Notes, 64-Note durable prefix, exact Home quota, Undo 507 with clear storage message, source-backed counts 64/64, both prefixes readable, then 128/128 byte-exact Undo after quota restoration. Three focused Rust quota tests passed. The shared fixture refactor also passed the existing real-server failure probe: foreign_exact=10 and undo_exact=128.Post-merge web gates, verbatim:
Merge decisions: retain both defer-initial-focus and restore-focus surface props; retain dev's quiet programmatic focus rule (#1391) with the existing explicit quiet-focus options type. Its one old default-focus expectation now follows #1391's false policy; this is a merge resolution of that explicit behavior change. The upgrade receipt count combines #1186 and dev's #1422: 26 new receipts, not either side's 25. Tags migration 0007 is still free on origin/dev (last deployed Tags migration is 0006). Exact performance pins refreshed with the existing generator; no rule changed; count remains 22,532.
Performance: release candidate is building locally; final per-crate Rust gates are started. Corrected baseline 1,000-Note sample is running with perf-run on the perf VM. Setup errors are retained and excluded: old browser cap; wrong Note-write endpoint (405); second User Note not yet indexed. Corrected functional preflight proves both mounted views and conditional Note PUT 200; local durations were discarded. Mac reservation remains occupied and has not been removed. No push, deploy or UI feature/style edit.
During #1186 tagperf4 measurement, origin/dev
cc1af3c12release reached 1,024 open descriptors on a fresh disposable Home (1,000 Notes, sixteen 1 Hz Tag readers and one independent-User conditional Note-body writer). The worker stopped at 381/1,000 after three attempts. One independent write returned 500. The private server log contains threeToo many open files/os error 24occurrences. The public receipt reported a generic filesystem failure. Storage was 889,992 bytes against a 1 GB quota; disk free space was 24 GB.This is not a SLOW-only finding. Sources remain on disk; full source consistency was not verified in this diagnostic run. Candidate behavior is not yet measured. Reproduction is
bench/tag-rewrite-1186-paired.sh baseline 1000 1with the explicitulimit -n 65536line removed, under perf-run. Fixtures are disposable; credentials are private and excluded from evidence.The valid A/B comparison will use a service-like descriptor limit of 65,536 for both servers. It records peak/average descriptors, and stops immediately on failed receipts. The diagnostic profile is excluded from latency comparisons.
Head
174ea93f9. Merged origin/devcc1af3c12once. All requested final gates pass. Verbatim summaries:cargo fmt --checkemitted no output and exited 0. Tags and server Clippy/tests each exited 0. The full-quota real-server probe also passed against the merged release build: 64/128 durable prefix; Undo 507 withHome storage quota reached; free space and retry; refused Undo changed no files; after raising quota, Undo restored all 128 byte-exact.The default SSH descriptor-limit failure is filed as #1497; the private log confirms
os error 24three times. Both comparison builds now have the same explicit 65,536 descriptor limit. The first 1,000-Note baseline remains active; three interleaved pairs at each size are queued under separate perf-run reservations. macOS GPU confirmation remains unavailable because the shared Mac reservation is occupied.First paired result committed at
c91caf1c7; baselinecc1af3c12and candidate merged Rust sourcea77e71920, identical frozene1672b919production SPA.The candidate's first sample meets the 500 ms target in both views. Neither read nor write route returned an error. The candidate terminal receipt and every source Note's final Tag bytes were verified. Both builds use a 65,536 descriptor budget; peak descriptors were baseline 3,543 / candidate 303. The baseline did not complete in the 900-second cap; its result is a lower bound, not a completion latency. UI clock: trusted CDP Enter to first rAF with the new name. Linux headless Chromium with macOS platform emulation, not confirmed real Mac GPU timing. HTTP/1.1 request queue time baseline 3.20 ms / candidate 16.90 ms.
Numbers and method live in
docs/perf/2026-10-09-tagperf4-1186.md, rawdocs/perf/runs/tag-rewrite-1186-tagperf4.json, and scopedmetrics.tag_rename_1186_tagperf4indocs/perf/baseline.json. The Index check occurs after completion and is explicitly not claimed as earliest API visibility.Remaining ten measurements are queued. Another job now holds the shared perf reservation; no unlocked measurements run. All final gates and merged-release full-quota Undo verification already pass.
Head
41f51c176. The initial 5-second UI observer was enough to assess the 500 ms target, but could only retain a lower bound for a slow baseline. The observer now continues independently for the receipt window, with a content-free/paintssnapshot. Receipt polling and read/write measurement stop at the terminal receipt; a separate two-second post-completion UI allowance covers the normal 500 ms progress poll. The first pair and the already-running second baseline keep their original 5-second UI lower bounds; no collected result is rewritten as an exact time.The updated browser controller passed its local functional preflight (both real views; actual conditional other-User write). Local durations are discarded. The next candidate VM phase will exercise the separate snapshot. No production UI code changed. Error-mapping function comments were reviewed and their storage/retry invariants added in
9b2d0b411; formatting passes. Rust behavior remains the already-gated merged release source.The second baseline is active under perf-run; remaining phases remain interleaved on fresh fixtures. Mac reservation remains occupied. All requested gates and the merged-release full-quota Undo probe pass, as recorded above.
The #1186 tagperf4 A/B profile found higher GET /api/v1/tags p95 during the candidate rewrite. Both builds run on perf-test-69-63 under perf-run, with the same frozen
e1672b919production SPA, fresh 1,000-Note Homes, sixteen 1 Hz Tag readers, and one separate-User conditional Note-body writer (250 ms delay after each successful write).Baseline is origin/dev
cc1af3c12; candidate Rust source isa77e71920(quota error fix plus merged dev). All requested code gates pass. Both servers have a 65,536 descriptor budget. Neither read nor write route returned an error in these pairs.Median per-run p95: baseline 47.58 ms, candidate 84.20 ms (+76.97%). The route-p95 regression threshold in bench/compare.py is 10%. These are medians of per-run p95, not a pooled request percentile.
Interpretation limit: candidate request windows are about 26 seconds; baseline windows are about 15 minutes. Startup background work overlaps both, but the short candidate windows give startup work more weight. This observation does not isolate a steady-state route regression or its cause. It is still the requested during-rewrite measurement and must not be hidden. Candidate other-User write p95 improves in all three pairs, and every candidate UI clock meets 500 ms.
Raw profiles and the scoped baseline are in docs/perf/runs/tag-rewrite-1186-tagperf4.json and docs/perf/baseline.json; method and table are in docs/perf/2026-10-09-tagperf4-1186.md. The 5,000-Note pairs are running; their results will be added. Performance findings do not block a merge under the owner rule.
The first tagperf4 5,000-Note candidate sample shows a cross-User write stall. Tags page/sidebar names appear at 195.40 ms, but POST /api/v1/tags/rewrites accepts only after 37,101.40 ms. One separate-User conditional Note-body PUT exceeds its 30-second transport cap (30,027.68 ms, status -1). The writer then stops because its ETag outcome is unknown. Five writes were attempted; four returned 200 and one timed out. Do not call the timeout a successful write p95.
The forward receipt completes at 128,188.45 ms, every source Note has its expected final Tag, and Tag reads return no errors (p95 189.66 ms). Server peak descriptors are 306; this is not the earlier 1,024-descriptor failure. load5 start/end is 4.16 / 5.23.
Candidate Rust source
a77e71920, binary SHA-256 05cb9d89046ddc5ad5a410c9623c1b986a173add05239118235534a12139bdfd. The run uses perf-run on perf-test-69-63 and a fresh disposable fixture with a second real User/Note. Frozen SPAe1672b919. Caller start_rewrite holds the namespace/User locks through acceptance (crates/calternal-tags/src/lib.rs:3052). project_accepted joins json_each witnesses with tags before staging memberships (rewrite.rs); query-plan cost is a lead, not a measured cause. The observation does not isolate lock wait from database work or startup work.The profile now allows 120 seconds for an independent write so it can record a slow success and continue the ETag chain. It separately reports successful-write p95, attempt maximum, counts and errors. It never resubmits an unknown timed-out write. The original sample is retained as a diagnostic; a corrected full pair is needed for successful other-User p95. No production algorithm changes are made by this measurement update.
Head
4997fb926: real macOS arm64 confirmation now passes at both sizes. Headful Chromium reports Apple Paravirtual Metal, GPU compositing enabled and rasterization enabled. Trusted CDP Enter to the first frame containing the new name in BOTH sidebar and Tags page: 1,000 Notes 214.80 ms; 5,000 Notes 306.80 ms. HTTP/1.1 request queue 0.80/0.60 ms. These use the local candidate release through a NetBird SSH reverse tunnel, so they are separate rendering confirmation, not substituted into the perf-VM backend pairs. Both local macvm.lock flock and remote /tmp/mac-bench.lock were held; own downloads are removed. No trust settings or foreign accounts changed. Evidence:docs/perf/runs/tag-rewrite-1186-tagperf4-mac.json.Ten of twelve interleaved perf-VM profiles are collected. The third 5,000-Note baseline and candidate wait for the shared perf reservation. Second candidate completes in 137.39 s, UI 100.40 ms, read p95 211.48 ms. Its other-User writer completed four requests then returned 503 after a 35.54 s stall; successful-write p95 125.98 ms only describes those four successes. Added evidence to #1501. The first 5,000-Note candidate had a 30 s timeout, so its successful-write p95 remains unavailable; it is not mislabeled as 30,027 ms successful latency.
Head
e1f7e492524e50323e7d4d105b9c819ad21d5130onjob/tagperf-1186. No pushes, deploys, issue closes or merge into dev were performed.Built: full-quota Undo returns 507 with
Home storage quota reached; free space and retry, preserves source bytes and journals, and can be retried after space is freed. The new Rust regression and real-server probe cover a 64-Note durable prefix out of 128. Refused Undo changes no Note or Tag count; after raising quota, Undo restores all 128 Notes byte-exact. The merged release build passes this probe. Existing focused publication/foreign-User failure probes also pass.The paired profile measures trusted CDP Enter to first rAF containing the new Tag in the sidebar and Tags page, background receipt completion, sixteen bounded Tag readers, and a separate User conditional Note-body writer. The writer waits 250 ms after each response and reuses its ETag. CPU, RSS, descriptors, HTTP protocol, queue time and load5 are retained. Fresh fixtures and identical
e1672b919production SPA assets isolate server builds. origin/dev is pinned atcc1af3c12; candidate Rust behavior is froma77e71920. Later Rust changes are doc comments only.Performance measurements run on perf-test-69-63 under separate perf-run reservations. The candidate binary SHA-256 is
05cb9d89046ddc5ad5a410c9623c1b986a173add05239118235534a12139bdfd; baseline is6c25a4023cebe0e6baf1230270af5d864c9931b8bda9eec9d4bca77178357fb2. Builds run on the build host, not the perf VM. These are unthrottled Linux headless Chromium timings at 1440 × 900 with macOS platform emulation. Separate reserved headful macOS Apple Metal checks with the candidate embedded SPA showed both views at 214.80 ms for 1,000 Notes and 306.80 ms for 5,000 Notes. Their server ran locally through a NetBird SSH tunnel, so they are rendering confirmations rather than perf-VM backend pairs. HTTP/1.1 queue time was 0.80/0.60 ms. GPU compositing and rasterization were enabled; own downloads/processes and both reservations were cleaned up.Write attempt p95 includes failed requests; a timeout is a client wait cap, not a successful write or completed server latency. The writer stops on an error; successful percentiles cover only requests before that stop. A
>value is a measured lower bound, not a completed latency. The initial pair and second baseline used a five-second UI observation window. Later profiles keep the observer active through the 900-second receipt window. Index verification occurs after the terminal receipt and is not claimed as earliest API visibility. Server measurement ends before the separate two-second final UI poll allowance. No capped or failed sample is turned into an exact completion time.Expected cost: O(candidate source bytes), one Home quota walk per worker attempt, and ceil(N / 64) durable source batches with eight file-IO workers and one Index transaction per batch. This job changes storage error reporting and the profile; it does not change the worker algorithm.
Files:
crates/calternal-tags/src/lib.rs,crates/calternal-tags/src/rewrite.rs.tests/adversarial/tag-rewrite-quota-1186.mjs,tag-rewrite-fixture-1186.mjs,tag-rewrite-failure-1186.mjs.bench/tag-rewrite-1186.py,tag-rewrite-1186-browser.mjs,tag-rewrite-1186-fixture.py,tag-rewrite-1186-paired.sh.docs/perf/2026-10-09-tagperf4-1186.md,docs/perf/runs/tag-rewrite-1186-tagperf4.json,tag-rewrite-1186-tagperf4-mac.json, scopedmetrics.tag_rename_1186_tagperf4indocs/perf/baseline.json.Gates (verbatim summaries; all exit 0):
cargo fmt --checkemits no output and exits 0. It also passes after the final Rust doc-comment addition. The commands use CARGO_BUILD_JOBS=4, CARGO_INCREMENTAL=0, CARGO_PROFILE_DEV_DEBUG=line-tables-only and the worktree TMPDIR.cargo clippy -p calternal-tags --all-targets -- -D warningscargo test -p calternal-tags -- --test-threads=4cargo clippy -p calternal-server --all-targets -- -D warningscargo test -p calternal-server -- --test-threads=4cd apps/web && bun run checkcd apps/web && bun run test --maxWorkers=2Known gaps:
UX gaps closed: full-quota refusal has a clear API message and keeps all Note bytes consistent; retry can restore every Note exactly. UX gaps left: the existing Undo toast does not state the storage cause. No visible controls or styles were added.
Decisions:
For the merge round:
ADVERSARIAL_SERVER_BIN=<combined-server> tests/adversarial/run-split.sh: run the combined-branch XUser/authz/hostile-input matrices. This job runs its focused quota and publication regressions only.TAG_REWRITE_HEADLESS=0 node bench/tag-rewrite-1186-browser.mjswith the matching SPA, private disposable installation credential and tunneled server. Confirm the UI clock on real macOS GPU with trusted CDP Enter. Keep downloads under the job directory and remove them after the run.No new dependencies or migrations were added. Tags migration 0007 was free on the fetched origin/dev before final gates.
All six candidate name-appearance samples meet 500 ms in both views: 115.00–331.90 ms at 1,000 Notes and 100.40–435.20 ms at 5,000 Notes. All six completed receipts pass source-byte verification. Five baseline receipts reach the 900-second cap; one completes in 869.06 seconds. The 1,000-Note median per-run Tag-read p95 is 84.20 versus 47.58 ms (+76.97%, #1499). At 5,000 Notes it is 211.48 versus 240.36 ms. All twelve profiles have zero Tag-read errors. The independent-write stall/error in #1501 remains unresolved; meeting the name-appearance target does not resolve it.
Resource and write-failure evidence:
These values cover the measured rewrite window. Incomplete samples stop at
the receipt cap; their CPU is not the full operation cost. RSS uses MiB.
Independent-write failures
The writer stops on an error. It does not replay a write with an unknown
outcome. Successful p95 covers only the requests before that stop.
The following attempt p95 includes the failed request. A transport timeout
is a cap, not a successful response or a completed server latency.
Cleanup:
cargo cleancompleted withRemoved 27726 files, 17.1GiB total. The local production build directory was deleted. Own Mac downloads and processes were removed, and both Mac locks were released. Private perf-VM fixtures and public profiles remain in the job directory for reproduction; each measured server and controller exited with its reservation. No secret was displayed.tagfix5 starts on job/tagperf-1186, base/head
e1f7e49252. Read #1501, #1499 and tagperf4 final evidence. Trace namespace lock, per-User writer lock and SQLite acceptance projection before fixing cross-User stalls. Preserve FULL acceptance and all publication/Undo recovery tests. No pushes or deployment.Measured #1501 cause in the Rust test build: the former acceptance query holds the FULL authority SQLite write transaction while a different writer obtains its ordinary pool connection in 0.098 ms, then waits 5006.733 ms in BEGIN IMMEDIATE and returns SQLite BUSY. The diagnostic requests no User/namespace mutex, so SQLite write-lock contention alone is sufficient. Notes projection uses this same BEGIN IMMEDIATE path and bounded BUSY retries (crates/plugins/notes/src/store.rs), which explains repeated five-second waits and eventual 503. The namespace lock is global but a plain conditional Note-body write does not acquire it; its Notes mutex is per User. The current fix removes the acceptance namespace lock, saves intent only, stages 64 witnesses per background transaction, and forces witness-first owner+path indexed probes. The 5,000-Note admission regression passes while the namespace lock is held. Full safety gates and real-server/paired evidence are in progress.
Head after the required origin/dev merge:
ef625e246c. Real-server #1501 regression passed on 2,000 Notes with two real Users: acceptance 156.92 ms, 20/20 successful conditional writes, other-User p95 46.11 ms and max 69.37 ms; the forward receipt completed. The former-query Rust test build isolated writer-pool checkout (0.098 ms) from SQLite BEGIN IMMEDIATE BUSY wait (5006.733 ms), while the authority projection took 37783.513 ms. No User or namespace mutex was requested by this diagnostic writer. Tags safety suite: 69 passed, 0 failed, one time-boxed diagnostic ignored by default; the diagnostic was run separately and passed. Web: 305 test files / 2218 tests passed; check has zero errors, three existing warnings. Final merged Rust gates and reserved 5,000-Note A/B samples remain in progress. Merge decisions: combine optional parent proof capture with dev directory proof pins; retain Tags 0007 plus dev Calendar/Mail/Share migration frontiers (34 pending receipts), preserve both perf records, refresh only exact live perf scopes (22260) without changing rules. No new migration or dependency.The final release binary passed the real-server two-User regression under a reserved perf-run session on perf-test-69-63 (load5 4.01). User A renamed a Tag on 2,000 Notes while User B made 20 conditional Note-body PUTs. All 20 succeeded. Acceptance: 149.601 ms; other-User write p95: 311.465 ms; maximum: 330.594 ms. The test enforces an independent 1-second cap for every write and verifies completed receipt and final bytes. No timeout assertion was weakened.
Two 5,000-Note candidate samples now completed: acceptance 246.8 / 393.8 ms; other-User write maxima 511.36 / 445.66 ms; durable completion 109.17 / 120.65 s. The third paired sample is running. Tag-read p95 is mixed (196.00 / 234.42 ms against origin/dev 215.81 / 203.31 ms), so #1499 is not marked resolved; a matched 1,000-Note pair is queued.
The headful real-macOS production Tags view showed the new Tag on page and sidebar 340.6 ms after trusted CDP Enter. HTTP/1.1 queue was 0.5 ms. This uses a remote browser with a local-server tunnel; server response timing includes the shared build host. Mac job directory and reservation lock are verified removed.
Final lock review found a receipt-retry lock inversion: start_rewrite retained the requesting User writer mutex while calling rewrite_status; a saved failed/orphan receipt can run repair_accepted, which acquires that same mutex. Admission now releases the guard before either saved-receipt branch. A focused orphan-retry regression passed and checks failed status, stable receipt identity, source-backed names, Undo and exact bytes. Final crate checks are running.
The first parallel suite then exposed interference in this job's 5,000-Note timing fixture: it shared the process-wide User mutex with other fixtures. The test now uses its own User/Home. Its one-second timeout and all assertions are unchanged; no existing product expectation was weakened. The final isolated fixture and suite are being checked.
tagfix5 / #1186 / #1501 — final report
Head:
4c4734791con job/tagperf-1186. Start:e1f7e49252. Merged origin/dev once at9dc65437e8before gates. No push, deploy or merge into dev/main.Built
Files changed by this job
Cause
A test-build diagnostic measured writer-pool checkout 0.098 ms, then BEGIN IMMEDIATE wait 5,006.733 ms with SQLITE_BUSY, while the former authority projection held its write transaction for 37,783.513 ms. The competing writer requested neither namespace nor User lock. The normal Note-body route uses a User-keyed mutex and retries SQLite busy writes. The blocking resource was SQLite's writer, not pool checkout or a cross-User mutex.
Performance (three 5,000-Note pairs on perf-test-69-63)
Frozen baseline: origin/dev
9dc65437e; frozen forward-path candidate source:9f24ac50a; production SPA:e1672b919. Every measured run held perf-run's single shared lock. The later6b000c795retry-lock fix does not change the measured new-intent forward path. Raw records preserve hashes, CPU/RSS, actual run order and load5 in docs/perf/runs/tag-rewrite-1186-tagfix5.json.All candidate samples completed and verified every source. Their 309/327/303 independent writes had zero errors. No capped baseline is represented as completed latency. Expected cost: accepted witness rows times <=2 exact membership-name seeks per projection table, bounded transactions of <=64 source paths, candidate source bytes plus one Home quota walk per worker attempt. Candidate CPU: 232.99/259.90/238.29 s; average RSS: 373946317/387788114/371558625 bytes; peak: 411766784/422440960/405184512 bytes. Baseline CPU: 1400.15/1416.29/1386.69 s across its longer windows; raw record includes all RSS and descriptor values.
#1499 / UX gap left: the matched 1,000-Note pair still shows a Tag-read tail regression: p95 47.36 -> 60.81 ms (+28.4%), p50 22.12 -> 20.47 ms. Candidate completed in 24.249 s; baseline was incomplete at 847/1000 after 900 s. Terminal candidate ordinary-read p95 was 29.04 ms. The reader-pool recursive prefix grouping still does work per request; shorter startup-overlapped windows weight initial bursts more heavily. CPU/query and window weighting are supported explanations, not isolated attribution. #1499 remains open, with its numbers posted. This is a performance gap, not a claimed resolution.
Safety and UX gaps closed
The 71-test Tags suite covers subprocess SIGKILL windows, retry, failed-prefix repair, concurrent source edits, byte-exact Undo and quota. The new overlapping namespace replay test passed. Final review also fixed an admission/repair self-deadlock on saved receipt retries: release the User mutex before terminal repair. Its regression verifies stable receipt identity, failure, source-backed projection, Undo and unchanged source bytes. The new 5,000-Note timing fixture uses a separate User to avoid unrelated parallel fixture mutex waits; its one-second bound is unchanged. The real-server quota probe passed at a 64/128 prefix: refused Undo returned 507 without changing files; raising quota allowed exact Undo. The real-server failure probe passed with 64 old/64 new Notes, exact foreign bytes (10 Notes), cross-User receipt/Undo 404 and exact Undo of 128 Notes. Malformed receipt and rename probes returned 4xx. The separate two-User probe passed under perf-run: acceptance 149.601 ms, 20/20 writes succeeded, p95 311.465 ms, max 330.594 ms, load5 4.01. Final receipt and other-User bytes were checked.
No visible control or CSS was added. Existing TagRow and ItemActionMenu remain the UI controls. Headful macOS Chromium 155.0.8059.39 showed page/sidebar Tag projection at 340.6 ms after trusted CDP Enter; HTTP/1.1 queue 0.5 ms. Observed response 790.1 ms includes the tunnel and shared build host. This confirms rendering, not the reserved-server acceptance bound. Mac browser, download directory and /tmp/mac-bench.lock were removed and verified.
Gates (verbatim summaries)
cargo fmt --check: exit 0, no output.cargo clippy -p <crate> --all-targets -- -D warningsandcargo test -p <crate>for calternal-fs, calternal-tags and calternal-server.Final server unit command:
cargo test -p calternal-server -- --test-threads=4(274 passed). Final integration command after exact pin refresh:cargo test -p calternal-server --test perf_guards --test private_index_permissions(both passed). The first retry-check server run had a startup/backfill timeout; its failing group passed alone, then all server units passed. That run also exposed a stale performance exception fingerprint after the retry-body change. Only the existing livestart_rewrite:mutationhash was refreshed in exceptions/adoption; no rule, limit or ratchet changed. The final integration checks andbun run checkboth passed with 22,260 scoped exceptions. The web test command passed all 305 files / 2,218 tests. These corrected failures are retained in artifacts.All Rust commands used CARGO_PROFILE_DEV_DEBUG=line-tables-only, CARGO_INCREMENTAL=0 and CARGO_BUILD_JOBS=4. Web gates were
cd apps/web && bun run checkandbun run test --maxWorkers=2. The ignored diagnostic was run separately and passed. Only the documented projection staging boundary changed two existing test setups; their assertions were retained. Existing test expectations were not weakened.Decisions
Known gaps / UX gaps left
9f24ac50arelease binary; the subsequent saved-receipt mutex-release fix is covered by focused/full Rust checks and leaves that measured forward path unchanged.For the merge round
bash tests/adversarial/run.sh— full combined authz/robustness/XUser coverage.CALTERNAL_SERVER_BIN=<merge binary> CALTERNAL_E2E_ASSET_OVERRIDE=1 bun tests/adversarial/tag-rewrite-cross-user-1501.mjs— repeat the strict User-isolation contract on the combined build.cd apps/web && bun run test:e2e(use the configured shared-server harness) — full combined UI behaviour; the focused probes and full web unit suite passed here.Cleanup
cargo cleanfirst removed 28,022 files / 17.3 GiB. After the late retry checks it removed 18,096 files / 12.3 GiB. apps/web/build was deleted again after its temporary restoration for RustEmbed. Worktree changes are committed. The own perf-VM run directory, binaries and disposable data were also removed.Diagnostic disclosure
A disposable test session cookie appeared in a local transport-error trace. That disposable Instance was destroyed, so the session is invalid. The local trace was redacted and the new regression now hides transport headers. No live owner credential was read or printed.
Deployed to calternal.cloud in merge round 36 (build
dbd621434, live 2026-10-10 ~14:40 IST). Closing.