Tabs: reduce warm Calendar to Files input-to-paint latency #1233
Open
opened 2026-10-06 21:43:51 +00:00 by kayg
·
100 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#1233
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?
Performance follow-up to #1124, round 2. Warm Calendar→Files Tab restore remains slow on the shared perf VM, full HDD scope, Chromium 4× CPU throttle, macOS platform. Five measured switches restore the already-loaded Files root with the same URL and four-row identity before and after; the departing Calendar is data-ready. Browser click→second painted frame p50 / p95 / max 747.5 / 995.5 / 995.5 ms. Automation click/readiness clock is 991.91 / 1300.40 / 1300.40 ms and must not replace the browser input clock. Individual browser samples: 906.8, 747.5, 654.2, 514.4, 995.5 ms.
Fixture: 5000 Files elsewhere in Home, 240 asserted Logs, 121 asserted provider Events. Profile runs through perf-run and records load. First separate API root snapshot had three rows while the completed UI had four; fixture Home setup can race that snapshot. Benchmark readiness now uses the actual completed accessible Files label, records API counts, and strictly asserts restored destination identity. Do not reuse earlier warm clocks that omitted destination preparation or departing Calendar readiness.
Investigate warm route activation, Calendar teardown and cache invalidation with a separate marked trace. The existing Files first-page cache returns its cached snapshot immediately and only revalidates after 2 seconds; its TTL alone does not prove the critical path waits on a request. No warm source flamegraph was captured in this final single-condition phase, so root cause is open. Cost should depend on the four visible rows and bounded mount/teardown, not a full-Home scan. Evidence: docs/perf/runs/2026-10-06-1124-round2-warm-tabs.json and bench/interaction-1124.mjs. SLOW-only finding; no crash or data loss found.
Starting tabswitch-1233 on branch job/tabswitch-1233, based on
3601719b80(origin/dev). I am reading the existing interaction profile, then I will measure the full Tab switch matrix and post the trace-backed baseline before changing app behavior.Code inspection confirms that Settings and Search are not Tab Bar destinations in this checkout. registers the actual mode routes (including Calendar, Tasks, Notes, Files, Photos, Mail, Money, Analytics and Ask); Settings is routed under , and Search is a shared surface. The baseline will exercise the real enabled Tab Bar entries with actual tab clicks and report Settings/Search separately as outside the Tab-switch matrix. No app behavior has changed yet. The measurement harness is committed as
1e37c8f87; bun test v1.4.2 (744846f84) passed 6 tests with 0 failures.Correction to my previous progress comment: the shell stripped inline code spans from the paths and test command. The checked-in navigation registry at apps/web/src/lib/navigation.ts provides the actual Tab Bar destinations: Calendar, Tasks, Notes, Files, Photos, Mail, Analytics, Money, and Ask. Settings is reached through /settings routes, and Search is a shared surface. The baseline will exercise every enabled Tab Bar destination with real clicks; I will list Settings and Search as out of scope for a Tab-switch pair matrix. No app behavior has changed yet. The measurement harness is committed as
1e37c8f87. The focused command bun test bench/tab-switch.test.mjs passed 6 tests with 0 failures.The full benchmark fixture did not reach a first Tab pair during a 49 minute 45 second leased setup. The remote server was still processing the 100,000-File and 50,000-Photo fixture (server RSS about 854 MB; Home DB data about 903 MB at the last check). I stopped the server before the one-hour perf-run cap and confirmed the lease is free. No timing sample was collected from this attempt.
I added a bounded medium fixture for the matrix: 5,000 Files, 5,000 Photos, the existing 5,000 Notes, 2,000 Tasks, 20,000 transactions and three Calendar years. This matches the 5,000-File scale stated in the prior #1124 baseline and leaves enough lease time for five samples per ordered pair. The focused harness suite now passes 7 tests with 0 failures. I will continue with this fixture; app behavior is unchanged.
The reused benchmark harness still awaits
waitForLinkNavigationFixtureunconditionally, even when invoked with--no-linknav. That gate indexes the #639 search/tag/note fixture, which is outside this issue's Tab-switch matrix. In the current 5k-Files run, the server had been indexing for over 12 minutes without reaching the first switch sample. I am checking whether this gate is holding setup; if confirmed, I will skip it only for--no-linknavruns.The
filesfixture reachedfixture readyafter about 15 minutes and exposed an instrumentation defect before the first matrix sample:readDestinationIdentityfailed withCalendar first visit paints real content identity. Its selector only covered Agenda/Month-style.itemrows; the current default week view uses the shared TimeGrid.block .b-titlerows. The failed run savedartifacts/tabswitch-1233/baseline/chromium-1440-light-failure.png. I am adding selectors for the rendered Calendar views and a focused selector test, then I will retry the baseline.The app's real Tab Bar exposes
role=tabentries for mode routes. In the fixture, the available entries were Calendar, Tasks, Notes, Files, Photos, Mail and Ask; Analytics and Money were absent because their optional plugins were off. The Settings action is a route, and Search is a shared overlay; neither is a Tab Bar item or has a Tab selection identity. I enabled Money through the existing User plugin setting for the next run. I will measure all enabled mode Tabs and report Settings/Search as outside the Tab-switch surface instead of fabricating Tab entries.The content-wait diagnostic showed that the Calendar route is present and has 140 matching grid title nodes, but every title node is inside the shared grid's
aria-hiddenvisual layer. The accessible row is the parent.block[aria-label]button. I will key Calendar identity from that real control label, while retaining Month/Agenda rows; this avoids counting hidden decorative text.The local 100-item smoke confirmed the Calendar route content was present:
/calendar/week/2026-10-05had 140 grid title nodes and 4,248 visible text characters. Those title nodes are underaria-hidden="true"; the actual accessible buttons expose the content labels. The harness now selects.calendar .block[aria-label], preserves Month/Agenda rows, and the focused harness suite passes (10 tests). Code change:924a55a9b. The retry is waiting for the single-tenant perf lease.The supplied prior-reference path
docs/perf/2026-10-06-1124-round2.mdand its2026-10-06-1124-round2-warm-tabs.jsonartifact are not present in this checkout. The checked-indocs/perf/2026-10-06-1124.mdstates that the earlier warm Tab profile failed before it produced valid JSON. I will preserve the issue-provided 747/995 ms Calendar→Files figures as the historical reference and report the first complete matrix measured in this job separately.The corrected identity selector passes a local fallback run with the same 5k-Files/366-Log fixture. Its single diagnostic pair sample confirms instrumentation: Files→Calendar recorded 291.2 ms and Calendar→Files 361.4 ms locally, with route-root teardown/remount and 4/2 critical-path requests. These are local debug values without HDD emulation and are not the baseline; the perf VM is now free for the qualifying matrix.
The full baseline reached fixture readiness on the perf VM with 8 available Tabs and all server probes returning 200. It then stopped before the first visit because the harness's
setThemeContextwrite toPUT /api/v1/appearancetimed out after 30 seconds; the payload was 32 bytes. No switch sample was recorded, and the benchmark cleanup released its lease. This is setup overhead, not a measured Tab result. I am checking whether the request path is blocked by the emulated server before retrying.The retry with
--no-linknavstill needed about 16 minutes to reach fixture readiness, close to the prior 15-minute run. Skipping the unrelated #639 readiness poll is correct for a Tab-only profile, but it did not materially change the total setup delay; I do not attribute the indexing duration to that gate.The timeout came from the shared
setThemeContexthelper using Playwright's default 30-second API request limit with no caller override. I added an optionalrequestTimeoutMsparameter (30 seconds by default) and set it to 120 seconds only for this perf profile. This write prepares the test User's theme before navigation and is outside the measured switch interval. The focused suite passes:bun test bench/tab-switch.test.mjs— 11 pass, 0 fail, 37 assertions. Commit:3be77fc79.The requested
bench/interaction-1124.mjsfile is absent in this checkout. I extended the existingbench/tab-switch.mjsharness used by the warm route profile, rather than creating a second benchmark harness. The change keeps its real server fixture, Tab clicks and trace tooling while adding #1233's identity and frame metrics.Baseline restart: the earlier perf-VM profile reached fixture readiness, then timed out while applying the benchmark-only appearance theme before any Tab-switch sample. I extended the shared e2e theme helper with an optional setup request timeout and enabled 120 seconds for this profile; all existing callers retain the 30-second default. The focused harness suite passes (11 tests). Restarting the same 5-sample, 8-Tab profile under a fresh 60-minute perf-run lease. No application behavior has changed.
Tab storm profile status (#1338)
Branch
job/tabstorm-1338; heada7691f609. The profile is inbench/tab-storm.mjs; the method and status are indocs/perf/2026-10-07-1338-tabstorm.md.No storm measurements were captured. At 10:38 UTC,
perf-run statusshowedtabswitch-1233holding the perf VM lock from 10:33:15 UTC with a 60 minute reservation, through 11:33:15 UTC. That was past this job's 11:25 UTC limit. Earlier setup-only attempts stopped at Photos Index readiness. The final queued attempt was stopped before lock acquisition. The directory-wide Photos readiness change remains unverified end to end. No storm, warm-pair run, CSV, Chrome trace, heap snapshot, or measured cause exists. No performance-cause issue was filed because no budget failure was measured.Post-merge web gates:
One
AttachmentDeck.svelteempty CSS ruleset warning was reported bybun run check; both commands exited 0. The historical 316 ms / 594 ms profile is not Tab storm data. Numeric choices are documented in the report: idle means at most 5% main-thread busy at the one-second sample, and a server climb means three strictly increasing post-storm CPU or RSS samples.Baseline finding: the 5,000-File seed completed and all eight enabled mode routes loaded, but no switch samples were collected because the harness rejected Ask's real empty state. The saved DOM diagnostics show
/ask, selected Ask Tab,.ask-page, 0 matches for the current row selector, 0 headings, and 56 visible text characters.TurnHistory.svelterenders its settled empty state as.turn-history .note, which the identity selector omitted. This is a benchmark identity bug, not an application loading failure. Failure screenshot and incomplete JSON are in the worktree underartifacts/tabswitch-1233/baselineandtarget/tmp; I will add the settled empty-state identity and rerun.The first seeded run (fixture ready in about 14 minutes) stopped before pair sampling because the Ask empty-state selector was missing. I added
.turn-history:not([aria-busy="true"]) .noteso the benchmark waits for settled real Ask content while excluding its loading state, and added a focused test.bun test bench/tab-switch.test.mjspasses: 12 pass, 0 fail, 38 expect() calls. Restarting the unchanged 5-sample matrix under a fresh 60-minuteperf-runlease.Second baseline finding: the corrected Ask identity passes its direct first visit; the checkpoint JSON records all eight first-load samples, including Ask at 2,485 ms. The run then stopped during warm-up before the pair matrix.
readDestinationIdentitytimed out waiting for the selectedtab-<id>state afterselectMode; the saved page shows the Tasks view selected. This failure path did not include the requested Tab id or current Tab DOM state, so I will add those diagnostics before the next run. No warm-pair sample was collected.Diagnostic finding (local fallback, not a perf-VM baseline): with the same 5,000-File fixture and the Mac Chromium profile, one warm Calendar→Tasks sample took 417 ms to the second painted frame, with one request before that frame and 124.1 ms attributed to old-view teardown/new-view mount. Tasks→Calendar took 523.6 ms, with five requests and 290.4 ms teardown/mount. This supports the route remount hypothesis but is not used as a performance result because the local profile has no HDD emulation and only one sample per direction. The local JSON is in
target/tmp/tabswitch-1233-local-debug-2.json.Warm-up finding: a local, one-sample, all-mode run completed first visits for all eight enabled Tabs, then timed out switching to Ask from
/tasks. Timeout diagnostics showtab-airemainedaria-selected=falseandtab-tasksremained selected; the direct Ask first visit passed. This is distinct from the Ask empty-state selector issue and blocks the warm-pair matrix from reaching Ask. I added same-origin resource path/status andaria-disabledfields to this timeout report so the next focused run can tell whether the click is blocked or the client navigation fails. The run has no performance value (local fallback, no HDD emulation); its incomplete JSON is intarget/tmp/tabswitch-1233-local-full-debug.json.Perf VM setup evidence for the current #1233 baseline run: HDD emulation qualified under the
perf-runlease. At queue depth 1: 124.57 IOPS, p50 7.96 ms, p99 8.36 ms, lock-held load average [1.85, 1.27, 1.26]. At queue depth 16: 200.79 IOPS, p50 95.94 ms, p99 125.30 ms, load average [1.53, 1.24, 1.25]. This is storage-profile qualification, not Tab-switch latency. The 5,000-file fixture is still being seeded and indexed.Preliminary qualifying HDD warm-switch evidence (matrix still running; five samples per ordered pair not complete): Tasks→Money 376.3 ms, Mail→Notes 365.9 ms, Mail→Calendar 781.3 ms from the real click to the second painted frame. All three show a detached old route root and an inserted new route root; Calendar's teardown and mount markers both occurred at 494.2 ms. These are not final p50/p95 values. The full pair table and worst-pair Chrome traces will determine the fix.
The first full matrix attempt is incomplete and is not baseline data. It completed three warm samples, then Money→Ask timed out in
targetMounted: the real click returned, but the route did not match/askwithin 120 s. Its saved failure screenshot shows the Tasks route selected. The harness did not save pathname/Tab-selection state at this exact wait, so I am adding that diagnostic and will reproduce the narrow pair before proceeding to app changes.Narrow local smoke reproduced Money→Ask route failure (diagnostic only; no latency numbers used): after the click,
pathnamewas/tasks,tab-aiwasaria-selected=false, andtab-taskswas selected. The last same-origin route resources were Tasks workspace CSS/module and/api/v1/notes/tasksplus/api/v1/notes/tasks/views; no request or loaded view identified Ask. The first route selection was provisional and did not commit. The updated harness now writes this path/Tab/resource state beside a timeout screenshot.I tightened the existing measurement harness in commits
6635203b5andcfa69370e. Warm samples now follow closed Tab visit routes, so one real click starts each pair sample; the focused test checks every directed pair appears once per run and routes remain continuous. Content identity now requires a row or the target Tab's own empty-state label. This fixes the harness accepting a generic heading while another route remains mounted. Focused result:14 pass, 0 fail, 55 expect() calls. The next qualifying run will restart the complete matrix on the perf VM.The next baseline attempt stopped during Calendar first visit before any switch samples. Its identity selector found 75 Calendar nodes, but the Playwright-serialized page function referenced a module-scope helper that is unavailable after serialization. I added an isolated serialization test and made the browser callback self-contained in commit
fcbd23a4d. Focused result:15 pass, 0 fail, 57 expect() calls. This run is discarded; no switch values were recorded.Related follow-up: #1356: Tabs: release detached Calendar page views after Tab switches. The local #1338 storm snapshots retain detached Calendar page contexts and agenda rows after Tab switches. Perf-VM confirmation is queued; I will post its measurements when complete.
Status: incomplete; work stopped after the shared four-hour job cap had elapsed (the job wrapper showed more than six hours at stop).
Built and committed a benchmark-only improvement in
bench/tab-switch.mjs,bench/tab-switch.test.mjs,bench/tab-switch-trace.py, andapps/web/e2e/harness.mjs. The harness now uses a closed warm route schedule, checks Tab-specific real content from a self-contained Playwright predicate, preserves slow samples, and attributes trace work to the switch stages. HEAD:fcbd23a4dfb45bd5a4aafa3eb9d4f3c33852513d.Phase 1 did not finish. The corrected local smoke was stopped while the fixture server was generating and indexing seeded Home; it produced no latency sample or identity result. Earlier exploratory values (Tasks→Money 376.3 ms, Mail→Notes 365.9 ms, Mail→Calendar 781.3 ms) used the older harness and are not a baseline. The full pair matrix, worst-three traces, baseline document, and complete issue table were not produced.
Phases 2 and 3 did not start. No app behavior changed. There is no warm-switch regression test, before/after profile, heap/RSS result, or complete screenshot set.
Verification evidence recorded before stopping:
node --check bench/tab-switch.mjspassed.git diff --checkexited 0 with no output. The final web build,bun run check, focused Vitest, Rust gates, and merge-round suites were not run. Cleanup output:Decisions made where the brief and current app differed: the live Tab Bar has Calendar, Tasks, Notes, Files, Photos, Mail, Money, and Ask; Settings and Search are routes/actions rather than Tabs, and Analytics is not enabled for this User. I used the existing
bench/tab-switch.mjsharness becausebench/interaction-1124.mjsis absent from this checkout.Known gaps: all measurement, trace, app fix, regression, screenshots, and final gates remain. The current branch has three atomic benchmark commits; the worktree is clean. This is not ready for merge.
Starting tabswitch2 on
job/tabswitch-1233. Previous headfcbd23a4d; merged origin/dev once, current head2ead7c546e83ab59b50fe4121f8818af821bbbc9. Investigating route remounts and active-only lifetimes for #1233. Local release measurements will record host load; no Photos indexing or Mail sync wait. No push or deploy.Code evidence for #1233: root layout rendered one router-owned child. The loading branch also removed that child. Calendar registers a 30-second interval and Files change listeners for its mount lifetime; TimeGrid, AgendaList and FileCollection register observers. The fix adds a three-Tab mounted LRU, frozen committed route context and active-only work lifetimes. Shared additions in packages/ui are required so observers follow the same activity owner. Warm pointer preloads now skip retained Tabs.
Focused boundary regression:
Test Files 1 passed (1);Tests 2 passed (2). Svelte diagnostics after the first slice:svelte-check found 0 errors and 1 warning in 1 file(unchanged AttachmentDeck CSS).Local baseline attempt 1 was incomplete: all Notes/Files/Tasks/Logs seeded, then the shared release server rejected Budget creation with starter Categories (400). No timing samples were counted. Retrying the minimal Budget request, within the 45-minute baseline limit.
Decision: retain read workspaces; keep live editors and Money import sheets router-owned until their write/flush lifetime can pause safely. This is a known scope gap, not a claimed full-Tab adoption.
Implementation is committed in
20559cac2. Three recent audited workspace trees now stay mounted behind a shared active context. SvelteKit still commits URLs, history, and deep links. Hidden trees are hidden, inert, and aria-hidden. Calendar clocks, list observers, workspace event listeners, and portaled overlays pause while hidden. Access changes clear retained trees. The storm-profile branch is merged atb5aa7e056.The baseline time-box ended after cold Files (1172.7 ms) and Notes (693.5 ms). Tasks did not meet the content selector within two minutes. No warm baseline is available; these partial numbers will not be presented as a complete before/after comparison. The production implementation build passed. Focused host/boundary tests passed: 2 files, 5 tests. A final watcher audit found that TaskIndex kept its Notes watcher alive after its workspace hid; its active-consumer lifetime now cancels that subscription and its queued read, with a focused regression test passing.
Decision: retain the five requested read workspaces first. Live Note/Canvas editors, import recovery, Photos, Mail, and AI keep their current router lifetime until their background/write lifetimes are audited. This scope limit is documented in DESIGN §59 rule 6 and remains a gap against retention of every Tab.
Review findings for #1233, branch job/tabswitch-1233, head
c11f6445d:Current local host uptime: 17:13:08 up 4 days 7:55; load average 65.61, 56.40, 54.43. This is a busy-host local measurement, not the perf VM.
Focused regression tests and a production build are running. No Rust change, push, deploy or merge into dev.
Tab storm latency from #1338
This profile used the production build, one Chromium page with macOS platform emulation, 1440×900 desktop, a 15 second 390 px touch phase in each 120-second storm, and nine warmed destinations. It measured both 4× CPU throttle and native on the perf VM through
perf-run.The supplementary warm-pair sweep timed out at Calendar→Files after two samples per condition. It therefore does not complete the 72 ordered source-target pairs and must not be treated as a full warm-path result.
Final storm selection
These are final-input-to-second-paint timings inside the storms. The stricter final-content-within-100-ms assertion failed in all six storms. The selected Tab's own seeded content appeared by the next one-second sample; the profile did not observe a different Tab's content after target paint.
The perf-VM lock load at start was
0.03 1.18 2.60for CPU4 and6.04 5.28 4.08for native. The corresponding one-minute load p50/p95/max values were 5.75/6.50/6.79 and 5.10/5.71/5.82. The native host started loaded.Condition-level CPU and long-task p50/p95/max across 359 one-second samples:
The repeated full Task reads are tracked in #1376; File/Photos image request concurrency in #1377; detached Calendar and Mail trees in #1356 and #1375. Server RSS growth and unexpected Composer dialogs are tracked in #1378 and #1380. Full tables and committed raw rows are in
docs/perf/2026-10-07-1338-tabstorm.mdanddocs/perf/runs/2026-10-07-1338-tabstorm*on the job branch.Progress at
b39394e05: the three-entry workspace LRU and its sidebar follower are implemented. Warm DOM identity, hidden inert/aria-hidden boundaries, route snapshot stability, active-only document title and activity cleanup have focused regression tests (3 files, 15 tests passed). The final production build passed:Compressed 921 static variants; saved 21523892 bytes.The first complete 40-sample run exposed a second remount: the mode sidebar still replaced its explorer tree on every switch. Files→Notes and Tasks→Notes each started
/api/v1/notesand/api/v1/files/entriesduring the measured frame window. Commit9935fb743makes the sidebar follow the workspace's existing three-entry LRU, with no separate cache. Commitb39394e05fences hidden sidebar reads and old folder workers, and avoids repeating a settled Money entry check.Earlier complete warm timings did not meet 100 ms (p95 2022–5388 ms on this shared host). Those are pre-sidebar-fix results, not a passing claim. A final paired original-router/retained-build measurement, screenshots and the imported #1338 storm profile are next. The original #1338 web build and server were removed by that job's cleanup; a private copy of the running merge-round release server is now used for both web versions. Its SHA-256 is
8dac09660d5dbeebaab69d0b4699a56e5385bfc04e0a82db62d77c93d16fa2f6. The baseline uses its embedded production router; the after run uses this branch's production web assets.Scope decision: Calendar, Files, Notes, Tasks and Money workspaces are audited for retention. Editors, import routes and Photos/Mail/Ask keep their existing router-owned lifetime. This is a known gap, not an assertion that every Tab is retained. No Rust source changed; no push or deploy.
Partial delivery — NOT READY FOR MERGE
The four-hour limit is reached. The app now has retained Tab workspaces, rather than only benchmark fixtures. The required final performance and browser proof is incomplete. Do not merge this branch on this report.
Branch: job/tabswitch-1233. Head:
a469644be1. Initial origin/dev merge:2ead7c546. Final fetch and merge at 16:21 was already up to date. Authorized job/tabstorm-1338 merge:b5aa7e056. No push or deploy. No Rust changes or new dependencies.What was built
TabHost keeps the last three audited Tab workspaces mounted. TAB_VIEW_LIMIT is the sole bound. SvelteKit remains the route source of truth. Each retained workspace has a stable page snapshot, so inactive workspaces do not react to another Tab's URL. A warm navigation reuses its workspace DOM. LRU eviction unmounts the oldest workspace. The sidebar follows the same retained-view owner and pauses when physically hidden.
RetainedTab hides inactive content with hidden, inert, aria-hidden and content-visibility. It restores focus and scroll on return. The shared viewActivity context stops timers, observers, stream consumers, requests and portal handlers on hide. Hidden changes coalesce into one refresh on resume. First loading does not wait for motion. Session end and access loss clear the retained views.
Calendar, Files, Notes, Tasks and Money use the boundary on audited read routes. Photos, Mail, Ask, editors and imports remain router-owned. Shared Calendar, Files, Menu, FloatingSurface, PopoverSurface, OverlaySurface, Inspector and TagFilterChips primitives own their lifecycle changes. Existing AppSidebar, SidebarLinks, NotesExplorer, FilesSidebar, TasksSidebar and MoneySidebar controls are reused; no local restyling was added.
Notes folder reads use four workers with cancellation epochs. TaskIndex has an active-consumer reference count. Header ownership now compares the stored reactive proxy, and releases only the owner's header on hide or unmount. Focused tests caught and verified that fix.
DESIGN §59 rule 6 documents the boundary. Tests cover DOM reuse, hidden accessibility state, route snapshots, back/forward, deep links, access loss, sidebar lifetime and header ownership. The performance scanner now proves an immutable literal array slice bound. Exact exception entries were refreshed without raising a budget.
Expected warm cost: at most three cache entries plus the destination's existing layout and paint. A clean retained workspace does not remount or await a data fetch. A dirty workspace schedules one bounded refresh after paint. These cost claims still need final production measurements.
Gate output, verbatim
Final production build, exit 0 (final-build-9.log):
Last complete successful check predates the final header/test-fixture changes (final-check-5.log):
The next check found two new test-fixture PageChrome.onaction type errors. Both were fixed in
a469644be. Final-check-7 reached the following output, but its type-check stage was stopped at the time cap. It is NOT a completed final check:Full bun run test --maxWorkers=2:
All four failures were
Error: Test timed out in 5000ms.Each failing file was rerun alone. Existing expectations were not changed.VersionHistory rerun still fails:
SystemGroup rerun:
KeyboardShortcutsCard rerun:
Select rerun:
Focused retained boundary/header regression rerun:
cargo fmt --check exited 0 with no output. No Rust crate changed, so crate clippy/test were not run. cargo clean completed:
Measurements and known gaps
No valid final <=100 ms result exists. No final cold-load <=10% comparison exists. No final <=25% heap result exists.
The earlier pre-sidebar stage used 200 Notes, 500 Files, four Tasks, four events and one account. Forty warm DOM identity/inert checks passed. Five retained-Tab heap passes were 17,325,756 / 17,172,500 / 17,402,040 / 17,444,996 / 17,498,488 bytes (+1% first to last). This is intermediate evidence, not proof for HEAD.
Intermediate warm p50 / p95=max in ms, five samples each:
These runs exposed sidebar remount reads and header lifecycle work, which were then fixed. They do not meet the budget. The host load was about 65; exact uptime and raw traces are in the reports. The baseline switch_mode 316/594 ms metric uses a different interaction and is not a direct paired baseline.
A final 200/500 fixture did not finish in the available time. A reduced two-Note/two-File comparison completed 40 native baseline samples but only one after sample. I rebuilt the served assets during this attempt, which invalidated its after samples. The browser also reported
effect_update_depth_exceeded. The latest header fix passed focused tests, but the production loop is NOT proved resolved. This is a blocking runtime gap, not a SLOW-only finding.The first local storm run served the shared server's embedded web assets. CDP showed zero retained boundaries. Its three storms are invalid as after evidence. I corrected bench/tab-storm.mjs to route this worktree's production assets in local mode. The corrected storm was not run before the cap. Invalid data is in artifacts/tabswitch-1233/storm-embedded-web; the imported #1338 baseline files were restored. The copied local server SHA256 is 8dac09660d5dbeebaab69d0b4699a56e5385bfc04e0a82db62d77c93d16fa2f6; its matching source revision is not established.
UX gaps closed
Hidden views and portals leave the keyboard/accessibility tree. Focus and scroll survive retained switches. Hidden work stops, interrupted first reads resume, stale folder workers cannot publish after a rapid hide/show, and inactive views cannot own the visible title/header. Access loss clears cached views. Keyboard and pointer keep the shared motion rules.
UX gaps left
The final production runtime loop needs diagnosis and proof. Photos/Mail/Ask and write routes are not retained. Final pointer/touch/keyboard and screen-reader walks, exact deep-link browser checks, and phone/tablet screenshots are missing. The attached ten images are explicitly the PRE-SIDEBAR 1440 px stage, light and dark, with macOS emulation. They are not final visual evidence. No valid final 390/820/1440 set exists. Visual quality remains for the orchestrator to judge.
Decisions
Reuse the existing +page workspace components through a route-to-workspace host, rather than duplicate their UI. Retain one audited workspace per mode, and replace it when the workspace route class changes. Set the single LRU bound to three. Keep write routes router-owned until their persistence contracts are audited. Use the same owner for sidebar retention. Defer known signed-in warm-route background checks until after paint; keep cold, unknown and access-loss checks immediate. These implementation choices are recorded in module comments and DESIGN §59.
For the next verification / merge round
First diagnose the production effect-update loop. Freeze the production assets for the whole browser run. Use a server build with known matching source/API provenance.
Run the final gates in order:
Rerun the VersionHistory failing file alone without changing its expectation. From the worktree root, with CALTERNAL_SERVER_BIN set to a known matching release server:
Use the existing TAB_RETENTION_BASELINE_BUILD option for a paired immutable production baseline. Keep the normal 200-Note/500-File fixture, collect all eight directions with five samples each, both Calendar/Files traces, cold loads and five heap passes. Capture all five Tabs at 390/820/1440, light/dark, macOS emulated.
Then run the corrected local storm driver with TAB_STORM_SERVER_BINARY set to the matching release server:
It must use the worktree assets, show retained boundaries, bound heap growth, stop aborted work, and land on the final Tab. Full e2e/adversarial merge-round suites remain with the orchestrator. No API changed here.
Files
Changed files since the initial origin/dev merge (includes the authorized storm branch and its baseline documents):
Attached intermediate screenshots
Starting tabswitch3 on job/tabswitch-1233 at
a469644be1. Predecessor report read in full. Reproducing the blocking production effect loop first, then freezing assets for measurements. No push or deployment.Finding at
a469644be: a fresh immutable production build completed 15 cold rotation switches, then the small real-API fixture completed 40 warm retained switches and five heap passes with zero page errors. All warm destination identities remained mounted. The reported effect-depth loop is not reproduced on this head; no speculative loop guard added. Prior failed run changed assets mid-run. Focused TabHost/RetainedTab/VersionHistory suite passes; adding explicit benchmark page-error failures and separating trace collection from budget samples. Found retained focus used plain focus(); adopting the existing quiet-focus helper.Progress: focus fix committed in
91fc6200c; benchmark validity/provenance fixes are atomic commits through8ab21f6a3. Required origin/dev fetch and merge was already up to date. Final bun run check completed: svelte-check found 0 errors and 1 warning in 1 file; perf-lint PASS, 0 violations, 22544 scoped exceptions. cargo fmt --check passed silently. Full bun run test --maxWorkers=2 is still running. Perf VM is now seeding 200 Notes / 500 Files under perf-run; initial load 0.27 / 0.69 / 0.96. Earlier attempts failed before measurements because Chromium could not create shared memory under the staged temp directory; moved TMPDIR to writable HDD temp.Perf VM first completed timing pass: all 40 warm samples retained DOM identity and had zero page errors. Native warm p95 ranged 247.9–396.6 ms, above the 100 ms budget. Five post-GC heap passes were 21943992 / 22056392 / 22332112 / 22389088 / 22438360 bytes (+2.3% first to last). Marked main-thread traces attributed 51.3/57.3 ms to Svelte flush callbacks, 18.8/25.7 ms to layout and 18.0/17.1 ms to style recalculation for Calendar/Files. Warm Notes returns issued fresh Notes reads. Fixed state-only history updates invalidating URL/data consumers in
bd9ea9697; the new regression fails on the old implementation (2 publications instead of 1) and passes after the fix. Commit4a5fcf835prevents a queued restore from stealing the next keyboard Tab focus. First screenshot probe picked an offscreen Calendar buffer date and panned the URL; corrected it to the visible current date. Final paired run is active under perf-run; start load 0.00 / 0.04 / 0.53. Initial full web suite passed 290 files / 2051 tests; rerunning after the new runtime fixes.Quiet-VM finding after the route-field fix (
bd9ea9697, focus fix4a5fcf835): 40 paired baseline + 40 retained warm switches, five GC passes each, and zero production page errors. Both use the same release server at origin/dev0419170fe; retained web assets were immutable throughout the run. All retained DOM identity/inert assertions pass. Warm Notes returns now make zero API requests (ten measured returns). The history-state regression fails on the old source and passes on the new source.Warm p95 (baseline → retained, ms): Files→Calendar 351.9→249.3; Calendar→Files 397.4→283.8; Notes→Files 314.0→222.3; Files→Notes 367.6→205.3; Tasks→Notes 242.7→202.4; Notes→Tasks 198.4→235.7; Money→Tasks 192.2→188.0; Tasks→Money 214.2→236.8. Every retained p95 still misses 100 ms. After heap grows 2.7% across five passes; absolute retained heap is 60.8% above baseline at pass five. This is NOT READY FOR MERGE.
Two paired measurement iterations are complete. A separate screenshot-only run now saves the exact failing focus/scroll/URL witness before asserting; the VM storm is running with corrected assets and three retained boundaries required. The optional 72-pair storm sweep is explicitly omitted because this job already ran the required eight-direction paired profile; the three storms per condition remain enabled.
The latest full web test run had three 5 s timeouts in tagFilterChips, SelectionBar and Composer (287 files/2050 tests passed). The unchanged three files pass a focused rerun:
Test Files 3 passed (3)/Tests 43 passed (43). A final full run is active; no assertion or timeout was changed. Heade123c9571.tabswitch3 final report — NOT READY FOR MERGE
Branch:
job/tabswitch-1233; base:a469644be1e557730554ae68838dc23aabdf52a5; head:6eb9aa0444dd95de3962e754a93ec4788470d358. Required origin/dev merge was already up to date at0419170fe456b58614befcb12d9c9d255118f1c0. No push, deploy, merge into dev/main, or issue close.Built: field-stable retained route snapshots and facade; quiet focus restoration without stealing the next keyboard input; preservation of native keyboard focus order; pre-mutation scroll capture. Regressions for private history state and scroll fail against old source and pass now. Bench fixes verify actual assets, reject page errors, preserve evidence, and capture real production views. Every measured warm switch (40/40) has zero API reads.
Files changed in this continuation:
The full report follows. It contains gate output verbatim, all eight paired directions, cold loads, five heap passes, trace costs, provenance, decisions, UX gaps closed/left and exact remaining verification commands. No measurements continued after the 90-minute measurement limit at 22:37 CEST. The original production loop did not reproduce at the supplied head; its root cause remains unattributed. This is not a claim that an exact loop regression was fixed.
Retained Tab follow-up — #1233
Status
This follow-up is not ready for merge. The production runtime loop reported
by the previous job did not occur with a fresh, fixed production build.
The warm switch budget is still not met. Storm acceptance remains incomplete. The final screenshot witnesses pass,
but visual approval belongs to the orchestrator.
Changes and cost
Keep equal URL, params, data and route fields stable when private history
state changes. Each route field has its own derived signal. A history state
update still reaches its consumers. It does not start a cached Notes read.
The sidebar uses the same committed snapshot as its workspace.
Use the existing quiet-focus helper for retained focus. A queued restore does
not take focus from the next keyboard Tab. No new visible control or local
style was added. The existing Tab Bar, workspace controls and shared focus
policy remain the UI owners.
The expected cache update cost is at most three entries, plus a shallow
comparison of route fields. A warm return keeps its DOM tree. Lists retain
their existing row limits. Test fixtures are written with four workers.
The regression test changes private history state without changing URL or
data. It fails against the old source (two publications instead of one) and
passes with the new field-stable facade. Focus tests cover quiet restoration
and the next keyboard input. A later phone probe found that hiding DOM
clamps the shared feed before ordinary effect cleanup saves its scroll. A
pre-effect now saves it before DOM mutation. Its regression fails on the
old cleanup and passes with the pre-effect and reactive boundary binding.
Remembered native controls also keep their default keyboard focus order;
only a fallback heading receives
tabindex=-1. No existing assertion ortimeout was changed.
Production input
The baseline is a separate production web build of
origin/devat0419170fe456b58614befcb12d9c9d255118f1c0. Both builds use the same sharedrelease server from that revision. Its SHA-256 is
42993fbd7660d35b1af91ab3a48d539666e0e67e5ae9d27c05a2f639d0680eaf.The final measured runner source is
5f1a49633fde6209672463900e96d464049ff4d4.The after web build ID is
2b149f9b07e6ddb702df6fd5d1f7bf3ab4db43cc.That build started with the app changes later committed in
bd9ea9697and4a5fcf835; its assets were fixed throughout the run. A build ID is not thesame as the complete source revision in this case.
The real API fixture has 200 Notes, 500 Files, four Tasks, three Logs, four
Events and one synthetic test account. The browser is Chromium, 1440 × 900,
with macOS platform emulation. The perf VM has no GPU. Both builds use the
same software renderer. No server or web build ran on the VM.
Each run holds
perf-run calternaland records load inside the lock.The final lock began at load 0.00 / 0.04 / 0.53. The runner recorded
0.44 / 0.14 / 0.56 at browser setup. Timing begins at the captured Tab click
and ends two animation frames after real destination content is visible.
Traces are separate from the five samples in each direction. No slow sample
was removed. With five samples, nearest-rank p95 equals maximum.
Paired warm switches
All times are milliseconds. Every direction has five samples per build.
All after p95 results exceed DESIGN §59's 100 ms warm budget. Most directions
improved against the paired baseline; Notes → Tasks and Tasks → Money have
higher p95. Do not describe this result as a budget pass.
The historical
switch_modebaseline indocs/perf/baseline.jsonis 316 msp50 and 594 ms p95. It has a different timing boundary. Use the paired table
above for the direct comparison.
Cold loads and heap
Cold results are single first visits, not distributions.
After heap grows 2.7% from pass one to five. It is 60.8% larger than the
baseline at pass five. Stable growth does not remove the absolute memory
cost of retaining three trees. All 40 warm identity checks and hidden-tree
inert checks pass. All 40 measured warm switches make zero API requests after the route-field
fix, including all ten returns to Notes.
Traces and incomplete attempts
The final Calendar trace spans 199.5 ms. Renderer main-thread tasks use
47.5 ms of that window. Svelte microtask callbacks are the largest script
cost (12.6 and 9.6 ms); layout uses 10.5 ms and style updates 8.4 ms.
The Files trace spans 195.3 ms. Renderer main-thread tasks use 62.0 ms;
Svelte callbacks take 22.3 and 7.1 ms, layout 14.5 ms and style updates
18.5 ms. These event durations overlap: do not add inclusive totals.
The remaining wall time includes frame scheduling and compositor work.
The requested CPU-profile category produced no sample stacks, so these are
trace event costs, not source-level CPU attribution.
The first valid VM pair used the earlier focus-only app build. Its after
p95 range was 247.9–396.6 ms. It had no page errors, 40 warm samples and five
heap passes. The second pair above follows the route-field fix. Both runs
failed later at the first screenshot focus witness; their timing reports
and traces were preserved. No third paired timing run was made.
Three early browser starts failed before sampling because Chromium could
not use temporary shared-memory files under
/root. A writable job-ownedtemporary directory outside
/rootfixed the start failure. These attemptsare not latency samples.
A fresh build at the supplied
a469644behead, a small fixture productionprobe and both full VM pairs report no
effect_update_depth_exceeded.The previous job rebuilt assets while its page was open. This follow-up
keeps assets fixed and rejects every page error. The exact previous loop
cannot be attributed without a reproduction; no guard was added to hide it.
Storm verification
The VM follow-up reached the first storm after its setup passed. It saved
14 per-second rows, then stopped before a post-GC sample: an unexpected
Composer hid the Tab Bar while the profile sought Money. The failure
screenshot shows the real Composer. This matches the keyboard scenario
already tracked in #1380,
which was also present in #1338. The summary has zero completed conditions,
zero post-GC rows and no page errors. Startup endpoint counts are 88 Tasks
reads, seven saved-view reads and three visibility reads, all HTTP 200, with
zero failed requests. A previous corrected VM start stopped at Tasks
loading before a storm; no claim of a runtime loop follows from that timeout.
The final VM lock load was 5.54 / 3.16 / 1.97. These partial rows do not prove
bounded growth, cancellation, one-second idle or correct final Tab.
The corrected local run proved three retained
workspace boundaries with this worktree's assets. It then timed out during
startup on the loaded host, before any completed storm sample. An earlier
local attempt timed out looking for the Money Tab during the first storm.
Those runs do not prove bounded heap, DOM, request cancellation or idle.
Partial failures are now saved in the output summary instead of discarded.
The first VM storm attempt copied the web build but used embedded server
assets. Its retained-boundary assertion rejected it before sampling. Remote
asset routing now uses the same production harness as local runs, with the
app port forwarded for its server boot-policy read. The invalid attempt is
preserved separately. The corrected VM run uses a separate output and stage
directory and the shared release server. A final bounded attempt keeps trusted Enter targeted at its Tab through
Locator.press, instead of an extra controller round trip after focus.It does not claim to fix the application issue #1380. Its result must still
record unexpected overlays and all failed budgets.
The optional 72-pair sweep is
omitted: this follow-up has the required separate eight-direction paired
profile. The three 120-second storms per condition remain enabled.
Final bounded storm attempt
The final corrected VM attempt used
Locator.pressand fixed productionassets. Its 1,200-second controller limit ended with exit 143. It wrote a
first-storm heap snapshot and reached a later storm phase, but did not save
a completed condition summary. The remote session and lock state could no
longer be verified when the controller stalled. These observations are not
accepted benchmark rows. No claim of concurrent valid measurement follows
from a stale phase file. The runner now saves every completed storm before
heap capture and cleanup. That evidence-save change was not measured again.
The measurement time box ended at 22:37 CEST. No further run was made.
The #1338 baseline reports first-to-third storm heap growth of 22.3%, DOM
growth of 112.3% and RSS growth of 58.8%. This job has no completed after
condition to compare with those values. The required heap and DOM bound of
25%, abandoned-request cancellation, one-second idle and final Tab checks
remain unproved. SLOW-only local startup results are not product failures.
Screenshots and gates
Final production build ID:
900d093f02b8b1139829ec36e18952d1183070c7.All five retained Tabs have switch-away-and-back witnesses at 390, 820 and
1440 px, in light and dark, with macOS emulation. The 200-Note/500-File set
has 30 passing DOM identity, URL, focus and scroll witnesses, including
160 px of phone Calendar scroll. Its images were superseded because capture
animation disabling and an update notice made them unsuitable for review.
The clean attached set has 30 images from the same real production API with
two Notes and two Files, four Tasks, three Logs and four Events. Scroll-driven
animations remain active; real Events are in view; the update notice is
closed through its UI; the pointer is off controls. All 30 witnesses pass,
with no page errors. Pointer focus has no painted outline. Four extra
1440-px light captures show the assigned Calendar, Files, Notes and Tasks
opening shortcuts without a focus ring. Money is seventh in the default
order and has no first-five shortcut. No new shortcut was added. A diagnostic
attempt to use a seventh shortcut timed out after the complete pointer set;
the runner now records an unassigned shortcut instead. A matching baseline
visual set and Money shortcut proof are not supplied. The orchestrator must
review the attached images; this job does not approve its own visual quality.
Commands ran in
apps/web. Final gate output excerpts are verbatim:The warning is the unchanged empty
.attachment-row:focusruleset inpackages/ui/src/components/calendar/AttachmentDeck.svelte. VersionHistory isunchanged against origin/dev and passes; no timeout or expectation changed.
cargo fmt --checkexited zero with no output. No Rust code changed.Both bench scripts pass
node --check. The production build passed:The required single origin/dev merge returned
Already up to date.beforefinal gates. Local web build output and the baseline worktree were removed.
Cargo cleanup output:
UX gaps closed
Private history state no longer causes a warm Notes read. All 40 measured
warm switches have zero API requests. Restored native controls keep keyboard
focus order. A queued restore does not steal the next keyboard Tab focus.
Phone scroll is saved before the shared feed is clamped. Pointer restoration
uses the shared quiet-focus helper. Existing Tab Bar and workspace controls
remain the visible controls; no shared primitive was restyled.
Decisions and gaps
No UI design was changed. Field-level derived signals implement DESIGN §59's
stable-field requirement. The snapshot still publishes shallow history state.
The optional storm pair sweep is separate from the required paired profile;
its omission is explicit. The evidence-save change preserves partial results
without changing acceptance budgets. These are implementation choices, not
new product decisions.
Photos, Mail, Ask, editors and imports keep the predecessor's route-owned
lifetime. The paired measurements precede the final native-focus and scroll
fixes; those fixes have focused regression tests, but no third paired timing
run. The original reported production loop could not be reproduced at the
supplied head and therefore has no attributed root cause or exact loop
regression. The 100 ms budget and storm acceptance remain open. The unexpected
Composer remains tracked by #1380. The final fifth heap is 60.8% above the
paired baseline; five after passes alone do not prove storm bounds.
For the next verification round
Use the fixed production assets and shared release server. Run
bun bench/tab-storm.mjslocally and throughperf-run calternalon the VM.It must complete all conditions and prove heap/DOM growth at most 25%,
abandoned requests aborted, idle within one second and correct final Tab.
Resolve or account for #1380 without silently removing a scenario.
Run
bun bench/tab-retention-1233.mjswith the 200-Note/500-File fixture andpaired origin/dev assets after a measured fix for the remaining warm costs.
It must retain all eight directions, five samples and five heap passes.
Do not treat the current timing table as a budget pass. Reproduce any claimed
production loop on fixed assets before assigning its cause.
Attached production captures
These 30 switch-return captures use the clean real API fixture described above, not placeholders. The four extra images show assigned opening shortcuts. The large 200/500 fixture has a separate complete 30-witness pass. Review artifacts stay uncommitted. The orchestrator owns visual approval. No matching baseline visual set was captured.
Opening shortcuts: Calendar, Files, Notes, Tasks
Raw logs and JSON remain in this worktree under
artifacts/. Final app full-suite output isartifacts/1233-test-scroll-final.log; VM paired rows areartifacts/tabswitch-1233/perf-vm-final/report.json; clean capture witnesses areartifacts/tabswitch-1233/clean-captures/. Cargo and web build cleanup completed.Starting tabswitch4 on
job/tabswitch-1233, base/head6eb9aa044. Read the retained-Tab follow-up and #1233 report. Accepted heap result stays closed unless the storm finds growth. I will attribute input-to-paint wall time, bypass full navigation for retained warm Tabs, preserve history/deep links/access clearing, fix capture witnesses, and run the paired profile and required local/VM storms. No push or deploy.Finding at
c6b3843b3: marked production warm switches on the locked perf VM isolate the delay. Calendar → Files: handler 0.0 ms, beforeNavigate 0.4 ms, onNavigate 68.2 ms, retained un-hide committed 91.1 ms, visible probe 114.3 ms, next rAF 165.7 ms, second rAF 212.0 ms. Notes → Tasks: handler 0.0 ms, beforeNavigate 0.6 ms, onNavigate 67.3 ms, retained un-hide committed 104.1 ms, visible probe 123.4 ms, next rAF 165.2 ms, second rAF 224.3 ms. Both destination routes have no load function; there is no View Transition or shared-motion await on this path. The Kit load/commit pipeline takes the first ~68 ms; DOM commit adds ~23–37 ms, and the probe’s two extra frame callbacks add ~98–101 ms. The before profile completes 40 warm samples, four traces and five heap passes with zero page errors. Raw artifacts are under artifacts/tabswitch4/waterfall-before.The shallow fix is committed (
d963f01a6) with 20 passing focused tests. Required origin/dev integration is resolving both retained lifetimes and upstream UI/Status changes atef0aa12b12. No new visible controls or styles.Head
88b5cdc01. The production shallow-history probe exposedeffect_update_depth_exceeded: deep Svelte snapshot state wrapped the private history marker in a proxy, while SvelteKit kept the same marker raw. The snapshot comparison then retriggered itself. Commit108aed2a0keeps committed snapshots in raw immutable arrays and scopes each marker to its loaded route. The failing production capture isproxy-repro-before.log; the fixed production probe completed 36 pointer switches with no page errors (proxy-repro-after.log). The focused suite passes 21 tests, including a raw Kit Page/marker identity regression.bun run checknow reportssvelte-check found 0 errors and 4 warnings in 2 files. The exact full test gate and paired VM run are in progress. No heap expansion work was added.Head
7547fba23plus the tested scroll fix (22 focused tests pass). The paired VM run completed all 40 baseline and 40 shallow samples with zero page errors; Back, Forward, reload and access clearing passed. The unchanged input-to-second-callback endpoint is still above 100 ms in seven directions (five samples per direction). Calendar→Files samples: 103.9, 160.8, 184.0, 211.6, 253.1 ms; Notes→Tasks: 86.1, 110.4, 99.3, 123.9, 114.7 ms. Separate compositor traces identify the formerly unattributed gap: the softwareDisplay::DrawAndSwapcosts 90.8–98.2 ms per draw for Files (root render pass id 1, 77 quads);LayerTreeHost::WaitForCommitCompletionblocks for 188.9 ms. Tasks draws cost 39.1–42.1 ms, with a 196.6 ms commit wait. These traced durations include trace overhead and are not substituted for untraced samples. No load/navigation hooks run on shallow switches.The capture step now proves initial focus and restored pointer focus without a ring. It then found a separate product scroll regression (Files expected 160, actual 0). The fix saves departing feed state before shallow history changes the DOM and cancels the prior route reset, with a regression test. I am rebuilding for final paired captures and the required local then VM storms. The full gate before this last scroll fix passed:
Test Files 296 passed (296)andTests 2125 passed (2125); final gates are running again for the changed source. Latency acceptance remains open.Correction to the sample count above: all eight directions have p95 above 100 ms using the existing nearest-rank protocol for five samples. Notes→Files has a 120.8 ms maximum (p95), although three of its five samples are below 100 ms. The final table will show every direction.
Head
75a6be179. The first local three-storm run finished with no page errors, but the final Photos witness became false at one second. Code inspection found a concrete last-intent defect: a click on the already selected Tab returned while another cold goto was pending. Commit7dd769465fixes that guard.The VM completed its first 120 second 4× CPU storm, then stalled in storm two for over 20 minutes with the renderer saturated. Its current URL was
/tasks; a second post-GC row never arrived. I stopped the invalid session and preserved the first storm plus the stalled-run metadata. The eviction fallback called goto inside a tracked effect. goto and its synchronous beforeNavigate callbacks read/write router signals, so the effect could cancel and restart its own recovery before it committed. Commit75a6be179makes recovery untracked, permits one attempt per missing target, defers to a newer cold load, and sends failures through the existing route error UI. It also supersedes older cold loads after shallow Back/Forward. There are 25 passing focused regressions; the exact full gates are running for this source. A fresh local then VM storm round is required and in progress.The VM request witness also resolves a misleading budget result: the two requests open at one second were
/api/v1/files/eventsand/api/v1/notes/events, both shared session streams. The raw #1338 counters and budgets remain unchanged. They must not be interpreted as uncancelled per-Tab reads. The local heap rose 39.2% and DOM 85.4% from storm one to three; snapshot root counts showed no detached Calendar panels, unlike the previous #1356 signature. This does not prove bounded storm memory yet. The final report will include the complete fresh round, and will remain NOT READY if the required budgets or scenarios remain unresolved.tabswitch4 finding at
87069cb66(product75a6be179): all three CPU4 VM storms completed without a page error, correct final Tab at 1 s in all three. First-to-third heap +6.4%, DOM -3.9%, renderer RSS +4.3%; idle failed all three. One attached Calendar panel and zero detached panels in both snapshots.Native setup then failed its existing Calendar Settings marker: the changed forwarded origin had no remembered Settings location, so Cmd+, opened the real Account default. The captured Settings Account screen is evidence that this was a fixture mistake. The profile now visits its exact Calendar Settings deep link before timing and can select one named condition to preserve completed CPU4 results. No product behavior, content assertion, timing limit or budget changed. Native is running again with the same fixture generator, release server and production web build.
tabswitch4 measured finding at
cfc9c9ba6(product75a6be179): the final paired VM recheck completes 40 baseline + 40 after samples, five per direction, using the same baseline web build0419170fe4and release-server SHA256 42993fbd7660d35b1af91ab3a48d539666e0e67e5ae9d27c05a2f639d0680eaf. All 40 warm targets retain their DOM identity and skip navigation hooks. Real Back/Forward/reload/access-clear probes pass; zero page errors. Warm p95 is 118.5–184.1 ms, so none meets 100 ms. Synchronous reveal p95 is 14.5–47.0 ms. Final traced Calendar→Files and Notes→Tasks name software Display::DrawAndSwap (51.3/59.4 ms max) and LayerTreeHost::WaitForCommitCompletion (187.5/178.5 ms max); they no longer show a route-pipeline wait. Trace overhead is kept separate from the budget samples.All required storms are complete: three local + three CPU4 VM + three native VM. CPU4 first→third heap +6.4%, DOM -3.9%, renderer RSS +4.3%; native heap +25.3%, DOM +25.1%, renderer RSS +46.4%; local heap +24.6%, DOM +61.7%. There are no page errors. CPU4 and native snapshots each keep one attached Calendar panel and zero detached Calendar panels. Inspector request records also grow, but that does not prove bounded memory. The raw memory budgets fail.
Native final Mail readiness fails the bounded post-stop poll. Its cause is not yet established: the third heap has no attached Composer or Search surface. This is a correctness gap recorded here; an earlier paint marker is not proof that the final Tab remains correct. Idle passes only native storm two; all other idle checks fail. Prior-view requests at the one-second sample are shared event streams, including two Files streams in native; ordinary reads have finished or aborted. The original counters and assertions were not relaxed. The extra readiness poll starts after the idle sample and can wait one further second, so a positive result does not prove an exact one-second deadline.
The local focus witness passes all 30 width/theme cases plus four available Mac opening-shortcut checks. A late build notice made those images unclean; a fresh VM capture now dismisses that notice before the final pointer/shortcut action and asserts its absence. Clean captures are in progress. Current status remains NOT READY: latency target, storm memory/idle, and native final readiness are unresolved.
tabswitch4 final report — NOT READY
Branch:
job/tabswitch-1233. Head:d6f5b46972f509b211a69b0a936dce79d43457d1. Product source measured:75a6be179. Start:6eb9aa044. The authorized one-time merge oforigin/devis9c740886b. No push, deploy or issue closure.Built
Warm retained Tabs reveal synchronously in the input handler through
flushSync, then use SvelteKit shallow history. Cold destinations keep normal navigation. A validated Page facade keeps the sidebar, shell and retained trees on the selected URL. Back/Forward, reload, access-loss clearing, retained scroll/focus, pending cold navigation cancellation and one-attempt recovery of evicted history entries have focused regressions. No shared motion duration changes. No new visible control or local styling.Warm work is a lookup over at most three snapshots, one history update and one synchronous reactive commit. All 40 final paired warm samples retain target DOM identity and skip the navigation hooks. The real production Back, Forward, reload and access-clear probes pass. The focused suite passes 25 tests.
Files:
apps/web/src/lib/navigation/{retainedNavigation.ts,tabContext.svelte.ts,RetainedTab.svelte,TabHost.svelte,TabHost.svelte.test.ts},apps/web/src/lib/components/app-sidebar.svelte,apps/web/src/routes/+layout.svelte,apps/web/src/app.d.ts;bench/{tab-retention-1233.mjs,tab-storm.mjs}; shared capture helpers inapps/web/e2e/{animation-trace.mjs,harness.mjs,linkcards-1151.mjs}; exact existing perf-pin refreshes underscripts/perf_guards;docs/perf/2026-10-08-1233-shallow-tabs.mdand its raw scalar runs underdocs/perf/runs/. Lockfiles and dependencies are unchanged.Attribution and paired measurement
The before/after waterfalls for Calendar → Files and Notes → Tasks are in the committed report. Before:
goto→onNavigatetook about 67–68 ms, then the retained tree committed at 91–104 ms. After: no navigation hook or route load runs. No View Transition, motion wait, timer/tick chain, font or image decode was found on this path. Remaining traced wall time is software root-render-pass composition and commit wait: maximumDisplay::DrawAndSwap51.3/59.4 ms andLayerTreeHost::WaitForCommitCompletion187.5/178.5 ms. Trace overhead is separate from the untraced numbers below. Document Paint is not element-specific Paint; the unchanged benchmark endpoint includes visibility polling and two later animation callbacks.Same paired baseline
0419170fe456b58614befcb12d9c9d255118f1c0, same release server, fixture and protocol; five samples per direction. Measured underperf-run calternal tabswitch4-recovery-paired 25, lock load 4.55 / 4.15 / 3.86. Product source75a6be179is included in the web build whose ID is7dd76946566bc17d929a87160666d50ab78ccff6(build started before that product commit).None meets 100 ms p95. Next cost: software composition and commit scheduling. The accepted three-tree absolute heap result is not reopened; final paired heap pass 1→5 grows 3.2%. Storm growth below remains unresolved.
Required storms: completed locally and on the VM
Three consecutive 120 s local storms and six VM storms (three CPU4 plus three native) completed on the same product and large #1338 fixture. All original budgets remain. VM sessions used
perf-run calternal tabstorm-1338 35; lock-start loads were 5.50 / 5.47 / 4.22 (CPU4) and 2.67 / 2.71 / 3.45 (native). No page errors occurred.#1338 local comparison was +22.3% heap and +112.3% DOM. Different final views do not isolate a leak. Native renderer RSS grows 46.4%; CPU4 RSS grows 4.3%. Thus bounded memory/DOM is not proved. Heap artifacts remain available for investigation. At one second ordinary prior-view reads have finished or aborted; shared SSE streams remain, including two Files streams in the native ledger. Ownership needs investigation. Known #1380 Composer events are recorded and dismissed by the harness; no product fix is claimed. Native Mail readiness cause is unknown; final native heap has no attached Composer/search overlay.
The added readiness poll begins after the one-second idle sample and waits up to one more second. A passing poll does not prove the exact one-second deadline. The legacy
final_paint_within_1sflag checks marker existence, so numeric durations remain authoritative. CPU4 endpoints are 386.6, 1615.1, 1109.3 ms; native endpoints are 120.8, 255.4, 168.0 ms. Original failing limits are retained. The supplementary all-pairs warm pass is skipped because the requested eight-direction paired protocol was measured separately; it is not a passing budget claim.Gates — verbatim
bun run check— exit 0:Four unused-selector warnings are in Mail/Money. Existing exact pins were refreshed; no ratchet raised.
bun run test --maxWorkers=2— exit 0:cargo fmt --check— exit 0, no output. No Rust product changes; no Rust crate build needed. Bench/capture JavaScript syntax checks pass. Existing test expectations were not weakened. Final touched module comments were re-read.cargo cleanoutput:Local and job-owned VM web/build output is removed. Ignored screenshots, traces and heaps remain local for review.
UX gaps closed / left
Closed: synchronous warm reveal, exact shallow URL/history, access clearing, retained scroll/focus, cancellation of stale cold loads, bounded history recovery and authentic capture focus. The existing Tab Bar, sidebar,
RequestState,focusQuietlyandprovideViewActivityare reused.Left: warm p95 target, storm memory/DOM growth, idle failures, native final Mail readiness, prior-view shared SSE ownership, known #1380 focus retargeting. Enlarged Task rows show the existing checkbox below the title cap-height center in both baseline and target: tracked by the existing #1385 consistency sweep. No Task style changed. Claude visual review remains pending.
Decisions
Clean screenshot evidence
94 original-size images: five Tabs × three widths × two themes × baseline/target/pointer, plus four available opening shortcuts. Both builds emulate macOS. All 30 pointer witnesses and four shortcut witnesses pass with no painted outline. Files/Notes preserve a 160 px feed offset. Money is outside the default first five shortcuts; no new chord was invented. Every capture asserts no update notice. Only
tabswitch4-clean-attachments below are valid final visual evidence. Enlarged icon/label crops were inspected; original images are unchanged.B = paired baseline, T = target, P = immediately after pointer switch.
Opening shortcut witnesses: calendar-1440-light-shortcut, files-1440-light-shortcut, notes-1440-light-shortcut, tasks-1440-light-shortcut.
For the merge round
cd apps/web && bun run test:e2eagainst matching production assets: combined shell, deep links, Back/Forward, access loss and keyboard/touch focus. The required local and VM storms were completed in this job; they are not deferred.NOT READY
Starting independent verification for #1233.
Branch:
job/tabswitch-1233atd6f5b46972f509b211a69b0a936dce79d43457d1.Comparison baseline:
origin/devatd395b6e25da20d8c67b8b9fc1a593b813939c8a7.Observed one browser-test failure while verifying #1233. With the production web build from
d6f5b4697and the shared release server atd395b6e25,bun e2e/deeplinks.mjsseeded a Note with 40 paragraphs and## Milestones, then opened/n/<note-id>#milestonescold. The heading element mounted, but the existingheadingInViewassertion inapps/web/e2e/deeplinks.mjs:773timed out after 15 seconds. The suite stopped before Files and later cases. I am comparing this against origin/dev to determine whether #1233 introduced the failure.Follow-up: the same
/n/<note-id>#milestones15-secondheadingInViewtimeout reproduced on the exactorigin/devproduction web build (d395b6e25) with the same shared release server and fixture. This is an inherited §33 failure, not introduced by #1233. The existingapps/web/e2e/deeplinks.mjsassertion is the failing regression test.Observed a second browser-test failure in the branch continuation run. The seeded
deeplink-brief.txtfile opened in Quick Look at/f/<item-id>, but a cold page at/f/<item-id>?open=sharedid not show the expectedShare deeplink-brief.txtdialog within 30 seconds (apps/web/e2e/deeplinks.mjs, file/share case). The run stopped here; zero CSP reports across 17 pages. I am comparing it with the origin/dev production build before attribution.Correction to my two earlier browser comments: I omitted
CALTERNAL_E2E_ASSET_OVERRIDE=1.routeCurrentBuild()installs the production bundle route only when this variable is set. Both runs therefore used the shared release binary's embedded frontend atd395b6e25; they did not compare the worktree build with the baseline build. The Note anchor and File Share dialog timeouts are baseline-only observations, not valid #1233 branch findings. I am rerunning both builds with the override enabled.Corrected comparison with
CALTERNAL_E2E_ASSET_OVERRIDE=1: the production bundle fromd6f5b4697and the exactorigin/devbundle atd395b6e25both fail the same existingheadingInViewassertion inapps/web/e2e/deeplinks.mjsafter cold/n/<note-id>#milestones. This confirms an inherited §33 failure, not a #1233 regression. The initial no-override runs were invalid comparisons, as described in my prior correction.Valid branch-bundle deep-link failures found; baseline comparison is in progress.
Using the production build from
d6f5b4697with CALTERNAL_E2E_ASSET_OVERRIDE=1 and the shared release server, the existing File Share case in a temporary continuation of apps/web/e2e/deeplinks.mjs opened /f/, then cold-loaded /f/?open=share. The accessible dialog “Share deeplink-brief.txt” did not appear within 30 seconds. The continuation then opened /p/; the Quick Look title “deeplink-photo.jpg” did not appear within 30 seconds. It stopped at that title assertion. The continuation only catches the already-reproduced Note anchor timeouts so later existing deep-link cases can run. I am checking the same bundle override against origin/dev before attributing either result to this branch.Comparison update: the
/f/<file-id>?open=sharetimeout is inherited. With CALTERNAL_E2E_ASSET_OVERRIDE=1 on bothd6f5b4697and origin/devd395b6e25, the existing File Share deep-link case did not show its accessible dialog within 30 seconds. This is the same seeded real file and shared release server. I am still checking the Photo case and its locator against the rendered DOM before attributing it.Baseline continuation finding (branch comparison pending): with the origin/dev production build and CALTERNAL_E2E_ASSET_OVERRIDE=1, apps/web/e2e/deeplinks.mjs stopped at the Search result action assertion (line 941). After the saved result appeared and was hovered,
.results-column > .sw-action-barhad no visible Actions button within 30 seconds. This prevented the remaining saved-search and Settings cases from running. I will compare the same route ond6f5b4697before attributing it.Photo comparison correction: the first Photo timeout used the existing e2e locator
.ql-title h2. That selector does not match the shared Quick Look markup (.ql-name[role="heading"][aria-level="2"]). Using the accessible heading, the branch build shows “deeplink-photo.jpg” and remains at/p/<item-id>. I classify this as a stale test locator, not a #1233 navigation failure. The original locator also timed out on origin/dev.Branch observation with the production build
d6f5b4697: a cold/photos/videosroute rendered the Photos view and selected Photos. Clicking Photos → Files → Photos returned to/photos, not/photos/videos. The reproduction is in the temporary focused route runner;TabHost.svelte's retained workspace allowlist does not include the Photos route. I will compare this exact flow on origin/dev before attributing it to #1233.Branch observation with the production build
d6f5b4697: cold/n/<note-id>#anchor-targetrenders the Note. Clicking Notes → Tasks → Notes returns to/notes; it loses the item route and block fragment. This occurs because/n/[id]is excluded from the retained workspace routes. I will check the same interaction against origin/dev. The user verification asks for exact warm deep-link restoration; DESIGN §59 says Note editors keep router-owned lifetime, so I am recording this as a behavior gap for owner review rather than changing editor retention during this verification job.Warm-route comparison update (production builds with the correct asset override):
/calendar/week/2026-10-05,/tasks, and/filesrespectively./filesand/files/recent, reload after that navigation, and branch Copy link from Recent matches/files/recent./photos/videosto/photos,/n/<id>#anchorto/notes, and/tag/<tag>to the prior Calendar week route after switching away and back. The Note editor remains router-owned under DESIGN §59; these are reported scope gaps, not new regressions.Independent macOS Chrome measurements
I measured the branch (
d6f5b4697) against the production web build atorigin/dev(d395b6e25) on the macOS test VM in real Chrome 154. The local fronts used the shared release server atREV=d395b6e25. CUA pressed the visible mode buttons. Each direction has 10 samples; branch and baseline were alternated. The browser clock starts at the click event and ends after the selected Tab and URL match and two animation frames pass.The Linux perf VM result in the issue was 747.5 ms p50 / 995.5 ms p95 for Calendar → Files. The wait is also present on macOS Chrome: branch Calendar → Files is 658.4 / 740.3 ms, compared with 135.2 / 172.3 ms on origin/dev. This exceeds the 100 ms warm-switch budget in DESIGN §59. Mac load average was 2.67 before and 3.87 after the run.
Rapid warm-switch regression
I added
apps/web/e2e/navrev-rapid-tabs-1233.mjs. It opens real Calendar and Files workspaces, warms both, checks that selecting the current Tab does not add history, then sends 20 browser pointer/click event sequences at a 90 ms cadence and asserts the final exact URL and a 2 s limit. On the branch the 20 inputs took 2129.3 ms and the final Calendar URL was correct, so the 2 s assertion failed. On origin/dev the same test passed in 1792.6 ms, ending at/calendar/week/2026-10-04.Safari limitation
Safari did not accept the local test certificate.
security add-trusted-certreturnedSecTrustSettingsSetTrustSettings: The authorization was denied since no user interaction was possible.I did not enter credentials or change the Mac profile. Safari timings remain unverified until the local test certificate is trusted or its normal browser interstitial is approved on the VM.Correction to the rapid-switch note:
apps/web/e2e/navrev-rapid-tabs-1233.mjsdispatches synthetic DOMclickevents on the real Tab buttons at 90 ms intervals. It does not use CUA or physical pointer input. This isolates the production click handlers from WebDriver round-trip time. In the matched run, origin/dev completed in 1792.6 ms and the branch took 2129.3 ms; both ended on the expected Calendar URL and passed the no-duplicate-history check. A later branch-only repeat during heavier shared-host load took 3859.7 ms. Treat the extra repeat as load-sensitive; the interleaved macOS Chrome samples remain the stable branch-versus-baseline measurement.Independent verification: #1233
job/tabswitch-1233atd6f5b46972f509b211a69b0a936dce79d43457d1withorigin/devatd395b6e25da20d8c67b8b9fc1a593b813939c8a7.9ebb86d299da5a1f2c9ee75cc2f95222abe678c9./mnt/hdd/targets/shared-server/CURRENT(REV=d395b6e25).Deep links and retained navigation
Shared failures on branch and baseline
/n/<id>#milestones: the heading mounted, but the existingheadingInViewassertion timed out after 15 seconds atapps/web/e2e/deeplinks.mjs:773. This reproduced with both production builds./f/<id>?open=share: the Share dialog did not open within 30 seconds on either build..ql-name[role="heading"][aria-level="2"]; the seeded photo name and/p/<id>URL were visible.Branch and baseline comparison
/tasks, and returned Files Recent to/files. Copy link after the baseline Files return therefore did not match the Recent view./photos, the Note block route to/notes, and a Tag link to the previously retained Calendar route after switching away and back. Those views are outside the current retained-workspace allowlist; they are gaps shared with baseline.Rapid switching
apps/web/e2e/navrev-rapid-tabs-1233.mjs. It uses a production browser, real Files data, 20 browser-dispatched click events spaced 90 ms apart, and checks the final Tab/URL. It also checks that clicking the already-selected Tab does not add history. The browser events are synthetic DOM clicks, which avoids charging each input for a separate WebDriver round trip.macOS Chrome warm-switch measurements
Actual Mac Chrome, ten interleaved samples per direction. Metric: input event to selected Tab and URL match plus two animation frames.
The long Calendar → Files delay is also present in Mac Chrome (branch 658.4/740.3 ms), close to the Linux issue measurement of 747.5/995.5 ms. This input-to-paint metric shows the delay on macOS; it does not isolate compositor time from application and browser work. Mac load averages were 2.67 before and 3.87 after the sample set.
Safari was not measured. The Mac rejected adding the local test certificate without user interaction:
SecTrustSettingsSetTrustSettings: The authorization was denied since no user interaction was possible.No credentials were entered.Session and Share access
Merge and performance contract
origin/devonce and resolved the Tasks source conflicts by retaining the branch's retained-Tab behavior and the newer Tasks bounded-read and exact-count comments fromorigin/dev.scripts/perf-lint --adopt-7cpath. Output:Adopted 9653 exact #1058 sites; ordinary future ratchet remains activeandperf-lint: PASS; 0 violations; 22544 scoped exceptions.Post-merge checks
The Rust formatter, Money crate Clippy, Money crate tests, and web check exited 0.
cargo fmt --check produced no output.
cargo clippy -p calternal-plugin-money --all-targets -- -D warnings ended with:
cargo test -p calternal-plugin-money ended with these summaries:
cd apps/web && bun run check exited 0. Relevant output:
cargo clean output:
The full cd apps/web && bun run test suite is deferred to the merge round under the owner verification policy. The focused rapid-switch production-browser regression ran on both builds and intentionally fails the branch's 2-second budget. The full e2e matrix was not run.
Decisions
Final revision
44c6453ad2.Follow-up to the #1233 verification report: the deleted-item check is now complete.
On the merged branch production build with the shared release server, I created a real File, saved its stable /f/ link, moved it to Trash, emptied Trash, and confirmed the Files API returned 404. Opening the original /f/ then showed “This item is not available”. The focused diagnostic passed; its temporary test file was not committed.
Additional verification limits for #1233: the Back/Forward checks confirmed route and content restoration, but did not separately measure scroll offsets. The 20-switch test checked the final Tab/URL and that clicking the selected Tab adds no history entry; it did not enumerate the full history stack created during the burst. These limits are now recorded in artifacts/navrev-findings.md.
Orchestrator decision: the shallow-routing branch (job/tabswitch-1233) is not merged. The independent review (navrev) measured real Chrome on the macOS test VM: Calendar → Files p50/p95 658/740 ms on the branch vs 135/172 ms on origin/dev
d395b6e25. The perf VM's software compositing made the branch look faster there. On the owner's platform, dev is already close to the 100 ms target. Next step for this issue, if pursued: measure on the Mac first (real GPU) and only keep changes that win there. Deep-link and warm-restore gaps found during the review are filed as #1459 and #1460.Starting #1233 on branch
job/tabcomp-perf, based on5a2c02c1300dd2f591b177395e0d8c94fc2f8df9(origin/devat start). I will inspect the prior #1233 attempt and its measurements, measure the requested paths on Linux only, trace the slowest interactions, retain only changes that meet the interleaved p50/p95 rule, and run the requested gates.Finding: the build host load was 13.64/13.65/10.74 (1m/5m/15m), above the permitted local 5-minute load of 6. The existing profile runs Chromium on the build host. On the perf VM, SSH to its own loopback and 10.69.69.63 both returned
connection refused, so the remote harness cannot self-SSH. I added a perf-VM mode to run the browser and server together underperf-run, retaining the existing HDD fixture and sampling load inside the lock. Focused benchmark tests pass; I am validating the staged run next.Finding: the first smoke run failed the existing HDD qualification before collecting any Tab sample. QD1 measured 82.417216 IOPS against the harness's unchanged 100–250 IOPS range. The mapped ext4 device was mounted with the configured 8 ms read/write delay. The post-run load average (1.15/0.70/0.31) is not contemporaneous with the failed sample. I kept the gate intact and added in-lock load and IOPS output before one controlled retry.
Update: one controlled retry passed the unchanged HDD qualification while
perf-runheld the VM lock. QD1 was 108.3167 IOPS, p50 8.02816 ms, with 5-minute load 1.04; QD16 was 200.638638 IOPS with load 1.02. The smoke run has not reached Tab sampling yet; the in-lock Files index count rose from 321 to 401 in the latest checks, with Photos still at zero.Finding: the aborted smoke runner requested only
calendar,filesbut still seeded and waited for 100 Photos. The user fixture had 100 JPEG files whilephotos_mediastayed at 0; the harness waited on that unrelated count. It also waited for a Search/Tag LinkNav fixture that a switch-only run never opens. Commit034f33d4bnow seeds Photos only when requested, keeps the Journal readiness check, and skips LinkNav readiness for switch-only runs. Focused tests pass (10 tests, 33 assertions).The 1440 px Chromium smoke now completes on perf-test-69-63 under
perf-run. Its reduced fixture was 1 year / 30 items per day / 100 Files / 20 Notes / 20 Tasks, with Photos omitted for Calendar→Files. HDD qualification passed in-lock: QD1 124.89 IOPS, p50 7.96 ms, p99 8.85 ms; QD16 200.92 IOPS, p50 100.14 ms, p99 105.38 ms. Load was 1.89 / 3.33 / 2.85 at QD1 and 1.77 / 3.23 / 2.82 at QD16.Trusted CDP Calendar→Files smoke input-to-second-ready-frame was 363.9 ms warm and 507.7 ms cold (one sample each, not the requested baseline). The warm path exceeds DESIGN §59's 100 ms Tab budget. Earlier smoke readiness waited for Photos even when Photos was not in the requested Tabs, and waited for LinkNav data in switch-only runs; I changed the profile to omit those unrelated setup operations. I will verify full Home indexing and the complete matrix before treating any result as a baseline.
The first full Home run did not reach a Tab sample. It seeded the requested 3-year Home (32,910 Journal entries, 100,000 Files, 5,000 Notes, 2,000 Tasks, 20,000 transactions), and the preflight Calendar API returned HTTP 200 with 267,496 bytes in 44.69 ms. The first Calendar route then failed the benchmark's visible-loading check after 120,000 ms (
.tg/loading UI did not settle); the run produced zero timing samples and released the perf-run lock. This is a full-fixture readiness failure, not a latency result. I will add bounded, content-free diagnostics before deciding whether the issue is an app load or a benchmark readiness assumption.Full Home baseline evidence from
tabcomp-1233-baseline-readiness3(perf VM, load average observed under lock: 3.20 / 4.18 / 3.95). The fixture contained 1,097 daily-note days, 32,910 log entries, 100,000 files, 5,000 Notes, 2,000 Tasks and 20,000 transactions.Seven trusted 1440 px light samples completed before the next cold cell failed: warm Calendar→Files 338.6 ms; cold Notes→Tasks 428.2 ms; warm Notes→Tasks 224.7 ms; cold Mail→Calendar 8,889.8 ms with 3 overlapping long tasks; warm Mail→Calendar 1,554.7 ms with 5 overlapping long tasks; cold Files→Notes 305.9 ms; warm Files→Notes 436.1 ms. All exceed the 100 ms warm Tab-switch budget where applicable. The following cold Tasks→Mail sample did not produce a second ready frame, so the profile correctly ended incomplete. The captured response log included 502/503 statuses during server restart; I am reproducing the failure against the actual sample page before deciding whether these are startup load effects or a user-visible failure.
The failed report previously captured the outer page after the cold sample page closed. I added focused, content-free diagnostics so the next run records the actual sample clock, route readiness and response statuses. No app behavior changed.
The 1440 px full-Home profile on harness commit
6611b690ad0ffd4029bcf6a12d72a02dc6705e27and server builddbd621434d0a1133f16230cca5c6a83af0d8aed3completed fixture setup and then failed on the first Calendar visit:waitForFunction: Timeout 120000ms exceeded.The run recorded zero first-load rows and zero switch samples, so it is incomplete.The seeded Home was 1,097 daily Notes, 32,910 Log entries, 100,000 Files, 5,000 Notes, 2,000 Tasks, 20,000 transactions and 30 recurring CalDAV Events across 1,097 days. The HDD qualification passed (QD1 124.6 IOPS; QD16 200.7 IOPS). All four server preflight reads returned 200 in 8.6–36.6 ms, including Calendar range at 36.6 ms (
Server-Timingtotal 9.753 ms, DB 2.446 ms, parse 2.750 ms). The Calendar UI readiness timeout is therefore separate from the sampled API response latency. The run had failure diagnostics disabled, so it did not preserve the rendered route state. The prior partial profile still has seven trusted switch samples; no additional switch data was produced here.390 px partial baseline (perf VM under
perf-runlock, server sourcedbd621434d0a1133f16230cca5c6a83af0d8aed3; load average before setup 2.75/4.57/4.40; HDD QD1 124.56 IOPS, QD16 200.65 IOPS):8713ec3c0; the rerun will confirm this diagnosis.The 502/503 entries in this run overlapped the intentional cold server restart. I am not treating those as product failures.
Composer baseline attempt (perf VM
perf-runlock, HDD fixture ready) did not reach action samples. The harness raisedReferenceError: overlapsInterval is not definedinside browserpage.evaluate; the function exists only in the Node process. It saved 1440 px first visits: Tasks 3,161 ms and Mail 1,881 ms (p50=p95=1 sample; lock-held load 1m average 5.19). I am moving that long-task filter to Node, where the existing tested interval helper is available, then I will rerun. These are harness timings, not Composer results.The corrected Composer profile completed on the perf VM against the full Home fixture (7 samples per action and width; source server
dbd621434d0a1133f16230cca5c6a83af0d8aed3). Results are trusted input to two ready frames, with warm/cold Tab profiles still pending:The §59 action budget is 150 ms. Search exceeds it at both widths; desktop FAB, Mod+N and close also exceed it. The p50 server CPU delta for Search was 570 ms at 1440 and 460 ms at 390; the captured resource path is primarily
/api/v1/calendar/preferences, with occasional concurrent/api/v1/notes/taskspage reads. The raw profile is committed as2102c6ed6. I will trace Search and the slowest Tab paths before selecting a product change.Calendar first-visit finding (not yet root-caused): the full Tab profile timed out after 120 s on the direct Calendar visit before collecting switch samples. The route was
/calendar/week/2026-10-05; TimeGrid reportedreadyandloadingtogether, with no visible loading UI. During the wait the browser recorded 24/api/v1/calendar/rangeand 24/api/v1/calendar/itemsresponses, all HTTP 200. Response bodies alternated between empty/300-byte and full payloads (up to 443,480 bytes); the grid never left loading. The diagnostic currently drops query strings, so I cannot yet tell whether the range changes or the cache is repeatedly invalidated. I am adding URL-level evidence before deciding if this is app behavior or the fixture/benchmark setup. No product fix is made from this evidence alone.Perf VM finding (10 Oct): the one-sample paired-profile smoke acquired the perf-run lock and stopped before fixture reset.
prepareVm()could not copy the origin/dev server to/mnt/hdd/targets/release-shared/release/calternal-server-tabswitch-549because the file was busy. With the lock free after exit,/run/calternal-tabswitch-549/server.pidreferred to no live PID, but a server process from 14:50 local remained incalternal-hdd-emu-2334748.scopeon/srv/hdd-emu/tabswitch-549. This leaves the fixture unsafe to reset until the stale scope is stopped. I am checking and fixing the runner cleanup before retrying; no measured samples were produced.Paired-run harness smoke completed on 10 Oct under
perf-runwith the #549 HDD profile and origin/dev server. It produced 4 Tab samples and 8 Composer samples (1 sample per build/path), with bothbaselineandcandidatevariants on Tasks→Mail and all four Composer actions. Fixture size was 100 Files and 20 Tasks; the one-sample timings are wiring evidence only and are excluded from the seven-pair decision. HDD qualification passed: QD1 124.6 IOPS / 7.96 ms p50; QD16 200.5 IOPS / 95.94 ms p50. The benchmark server stopped and the perf lock is free. A stale server scope from an earlier profile was stopped under its ownperf-run; cleanup now checks the recorded executable and uses a per-job PID file.#1233 progress: the full 100,000-file fixture completed, but the first Calendar visit timed out at 120 seconds before any timing samples were collected.
The sanitized page state was
/calendar/week/2026-10-05; the TimeGrid hadready=trueandloading=true, with no visible loading element. The browser recorded 23/api/v1/calendar/range, 30/api/v1/calendar/items, and 23/api/v1/notes/tasks/daycalls across two repeated date windows. All recorded API responses were HTTP 200. The same Calendar range request ran 22 times from about 2.9 s to 59.5 s after navigation, with a median duration of 2.1 s. No switch or Composer samples were produced.The request burst ended after about 60 seconds. This suggests that the benchmark opened Calendar while full-Home indexing was still publishing changes; that cause is not confirmed yet. I am adding a bounded Files-event quiet preflight and will rerun the Calendar readiness check before changing product code.
#1233 progress: the full Home’s Files event stream emitted 63 changes, then stayed open and quiet for 5 seconds after 144.834 seconds. I added this benchmark-only preflight and reran the full fixture under
perf-run calternal tabcomp1233quietmatrix 60; the fixture and read probe completed, but a fresh 1440px Calendar first visit still timed out at the existing 120-second paint-ready wait. The run produced no latency samples. This means active Files events are not the sole reason the prior Calendar profile stalled. I will capture the post-quiet DOM and API diagnostics once before making any Calendar code changes. The perf lock was released when the run exited.#1233 progress: the 100,000-file full fixture did not reach a quiet Files event stream within 600 seconds. The timeout state was open SSE, 200 change events, and only 2.3 seconds since the latest event. The Files index row count was still growing, so this is startup reconciliation work, not a stable warm Home. The harness also left its setup Chromium open on this timeout and held the lock until I stopped that job-owned browser. I found the existing public
/healthzstartup phase, which reportsfiles-home-reconciliationand laterfiles-content-type-backfill. I’m switching the benchmark gate to that content-free status and addingfinallycleanup for the setup Browser; this will wait for the actual Home scan instead of guessing from event silence.Progress: the 60-minute perf-run A/B attempt started at 2026-10-10 17:16 CEST on perf-test-69-63 with the lock held. The staged candidate build is
e63681f869and the origin/dev baseline isdbd621434d. At 14 minutes,/healthzstill reportsstate=migrating,phase=notes-upgrade-backfills; the server is using about 70% CPU and no latency samples exist yet. The new readiness gate correctly prevents recording startup-contaminated samples. I will report the final run result after this bounded attempt.A fresh 60-minute
perf-runwith the full 100,000-file profile and the new/healthzreadiness gate exited before sampling. At the gate's 25-minute timeout,/healthzstill returnedstate=migrating,phase=notes-upgrade-backfills; no latency samples were recorded. The VM lock is free and the benchmark's server teardown completed. This is earlier than Files reconciliation, so the quiet-event gate was not the only startup issue. The run did not produce enough evidence to identify a user-path root cause or keep a performance change.Result
Head:
e63681f8698f155a018994bb07c20a2e41cbd89e.No product performance change remains. The two Composer changes were reverted because the valid paired p50/p95 decision rule was not met. The current web app has no product-code diff from
origin/dev.Benchmark evidence
The candidate production build was
e63681f8698f155a018994bb07c20a2e41cbd89e; theorigin/devbaseline wasdbd621434d0a1133f16230cca5c6a83af0d8aed3. I ran the requested full Home profile onperf-test-69-63throughperf-run calternal tabcomp1233finalmatrix 60, with the perf lock held. Load average inside the lock at start was0.08 / 1.20 / 2.59. HDD qualification passed at QD1124.466 IOPS, p507.963 ms, p998.978 ms, and QD16200.906 IOPS, p50100.139 ms, p99104.333 ms.The profile requested seven warm and cold samples for all five Tab pairs at 1440 px and 390 px, plus seven samples each for Composer FAB, shortcut, Search and close. It stopped before timing because after 25 minutes
/healthzstill returnedstate=migrating,phase=notes-upgrade-backfills. The runner exited 2, recorded no latency samples, and released the lock. The separate #1540 issue now includes this earlier startup phase as well as the Files-index readiness evidence.An earlier incomplete origin/dev run recorded one 1440 px light sample per cell before failing: Calendar→Files warm 338.6 ms; Notes→Tasks cold/warm 428.2/224.7 ms; Mail→Calendar cold/warm 8,889.8/1,554.7 ms; Files→Notes cold/warm 305.9/436.1 ms. This is diagnostic only, not a seven-sample-per-path baseline. It found no candidate comparison. No current p50/p95 or three-path trace analysis is available, so no root cause for the slow Tab paths is claimed.
Changes
The retained changes add trusted CDP input helpers and tests, paired Tab/Composer profiling, request and long-task capture, unique benchmark PID files, and safe cleanup of the setup browser/context. The startup preflight now polls public
/healthzevery five seconds and acceptsstate=okorphase=tag-reconciliation; it no longer guesses readiness from a quiet Files event stream. The committed Composer baseline profile remains underdocs/perf/runs/.Files:
bench/cdp-input.mjs,bench/cdp-input.test.mjs,bench/notifications-read-1387-cdp.mjs,bench/tab-switch.mjs,bench/tab-switch.test.mjs, anddocs/perf/runs/tabcomp-1233-composer-baseline-2026-10-10.json.Verification
bun run checkexited 0. Relevant output:Focused benchmark tests:
Focused Composer Vitest:
node --check bench/tab-switch.mjs && git diff --checkexited 0 with no output. No Rust crate changed, so Rust gates were not run.cargo cleanoutput:Removed 6521 files, 202.5MiB total. The web build output was removed.Decisions and remaining gaps
/healthzphase because the prior quiet-event gate accepted a still-indexing Files fixture. The five-second poll is setup-only and bounded to 25 minutes.cd apps/web && bun run test -- --maxWorkers=2to verify the complete web suite on the combined branch.Starting #1233 on branch
job/tabswitch2, based one63681f8698f155a018994bb07c20a2e41cbd89e(job/tabcomp-perf). I have read the current #1233/#1540 evidence and DESIGN §59. I will first make the full seeded Home and Index reach/healthzready once, stop the server cleanly, snapshot both, and verify a restored restart is ready within 60 seconds. Then I will measure the requested cells on the perf VM underperf-runwith the origin/dev release server and trusted CDP clock, trace the slowest paths, and keep product changes only if the paired acceptance rule passes.Preflight finding: the perf VM still had a #549 Tab benchmark server in
calternal-hdd-emu-2349061.scope, serving/srv/hdd-emu/tabswitch-549; its executable was/mnt/hdd/targets/release-shared/release/calternal-server-tabswitch-549. The harness correctly refused to reset the marked Home while the server PID was live. I stopped the recorded server with SIGTERM insideperf-run calternal tabswitch2-stale-server-stop 1; it exited cleanly. Load average inside that lock was4.09 1.61 2.05. No latency sample was collected in this preflight.Perf-run
tabswitch2-fixture-100kstarted under the VM lock. The server reached/readyz, then the benchmark stopped before fixture seeding at its HDD qualification guard. QD1 measured 76.595 IOPS, p50 11.075584 ms and p99 51.642368 ms at load average 2.07 / 0.79 / 1.15; the cgroup reported7:0 rbps=157286400 wbps=157286400 riops=200 wiops=200. The current guard requires at least 100 IOPS and a 7.5–10.5 ms p50.lsblkmaps the delayed254:0device to backing loop7:0.No fixture was seeded and no Tab sample was collected. I am preserving the strict default guard and investigating a report-only run mode so the actual VM measurements remain visible without calling this device qualified.
The strict HDD guard remains the default. I committed an opt-in
TAB_SWITCH_HDD_QUALIFICATION_MODE=record-onlydiagnostic mode in0b7442f46; it records the same IOPS and latency bounds, marks each qualification sample as passed or out-of-spec, and includes the mode in the report. The focused benchmark and harness tests pass: 37 passed, 2 skipped. I am continuing the fixture run with this explicit mode so no out-of-spec environment is reported as qualified.The 100k fixture run seeded the Home, then the restarted server stayed in
/readyzphasenotes-upgrade-backfillsfor about 30 minutes. The runner was atwaitForStartupFilesReadyand collected no samples; I stopped the server/browser and recorded the evidence plus a correction on #1540. I am switching to the requested documented smaller profile:--smoke --files 10000(10k Files, reduced non-Files fixture counts), with the same 60-second clean-restart/healthzgate.I found why the 10k smoke attempt remained in post-readiness photo indexing: the Home contained 10k Files but 50,000 Photos.
tab-switch-seed.pydefaults to 50k, whileseedHomeincorrectly omitted--photoswhen smoke requested 100. I fixed the argument selection and added a regression test in8494f33a5; focused tests pass (38 passed, 2 skipped). The current attempt is not a valid reduced fixture, so I am stopping it and will retry with the corrected 100-photo count.The invalid smoke attempt’s stack confirmed the wait location:
waitForPhotoIndex(bench/tab-switch.mjs:1780) after the server had reached/healthz state=ok. It was still waiting after 52 minutes with the unintended 50k Photos fixture. I stopped the server/browser;perf-run statusis free and no benchmark processes remain. The next attempt uses the committed generator argument fix.Result
Head:
555c4d8aa659e5bfcebfdf8b98a350b7c9deda4c(merge oforigin/devatac7fda1a8c49e902e1b246bea9d167d64e92d58fintojob/tabswitch2). No push or deploy.The benchmark now snapshots the Home and database after one successful reconciliation, restores that snapshot for cold samples, checks
/healthz state=okwithin 60 seconds, returns to the requested source Tab after restart, and measures trusted CDP input through the destination's full-paint boundary. Request timing is scoped to that interval; failed requests keep only a safe path and browser error code.No product performance change was retained. The warm trace identifies client-side Calendar activation work, and a cold trace also shows DB-backed Calendar reads. A small candidate fix with the required five interleaved A/B pairs was not available, so the acceptance rule was not met. Follow-ups: #1557 (client render) and #1560 (cold Calendar DB reads). I updated #1540 with the readiness evidence.
Measurements
The warm profile ran on
perf-test-69-63throughperf-run, Chromium with macOS platform emulation, 1440 px, light theme, seven samples per directed cell. It used the pinned origin/dev release serverdbd621434d0a1133f16230cca5c6a83af0d8aed3(SHA-2561c096b0b642bc5c7b740e0ad01c80ea3794e6aabdabc3cd6a527afe24c3ba4ca) and the 10,000-file fixture with 100 Photos, 20 Notes, 20 Tasks, 100 Transactions, 366 Daily notes and 10,980 Log entries. Load average inside the lock before setup:3.05 / 2.48 / 2.16.All measured warm p50 values exceed the DESIGN §59 100 ms budget. Mail → AI and AI → Mail were not measured.
The 10,000-file cache-dropped cold restart did not reach
/healthz state=okwithin 60 seconds, so it produced no cold sample. I used a separately settled 100-file snapshot for seven cold Mail → Calendar samples. Readiness took 38.704–49.695 s (p50 48.142 s); input-to-full-paint p50 / p95 was 2,223.8 / 5,122.1 ms. The initial 100-file fixture seed took 1,236,269 ms to become ready. This reduced fixture is not representative of a full Home.Mail → Calendar finding: The seven-sample warm matrix had 0.17 ms p50 server timing. Its marked trace shows a 644.377 ms Svelte runtime
FunctionCalland five long tasks, max 669 ms; the trace's observed server request took about 0.098 ms. This points to client-side Calendar activation/render work as the warm bottleneck, not slow server work or fixture startup. The one-sample cold trace took 2,408.8 ms; it also shows client long tasks up to 926.447 ms and Calendar reads with 85–269 ms of DB time each. The trace shows no evidence of Mail sync lock contention. Warm trace and request waterfall:artifacts/tab-switch-1233-mail-calendar/. Cold trace and waterfall:artifacts/tab-switch-1233-cold100-recheck/in the worktree. The two other slowest warm cells (Files → Calendar and Calendar → Files) were not traced.Files
Compared with
origin/dev:apps/web/e2e/harness.mjs,apps/web/e2e/harness.test.mjs,bench/cdp-input.mjs,bench/cdp-input.test.mjs,bench/notifications-read-1387-cdp.mjs,bench/tab-switch.mjs,bench/tab-switch.test.mjs, anddocs/perf/runs/tabcomp-1233-composer-baseline-2026-10-10.json.Gates
cd apps/web && bun run check(afterbun install --frozen-lockfile; no lockfile changes):cd apps/web && bun run test -- --maxWorkers=2:bun test bench/tab-switch.test.mjs bench/cdp-input.test.mjs:node --check bench/tab-switch.mjsandgit diff --check origin/dev...HEADboth exited 0 with no output. No Rust code changed, so Rust format, clippy and test gates were not run.cargo cleanoutput:The web build and the remote job snapshot/build directory were removed.
perf-run statusreportsfree.Known gaps and decisions
notes-upgrade-backfillsbeyond the setup window. The 10,000-file cache-dropped restart also missed the 60-second readiness gate. I used a 100-file fixture only for cold Mail → Calendar so the server was ready before each sample.