WIP: feat(whiteboard): file and sync foundation (slice 1) #1015
Draft
kayg
wants to merge 35 commits from
feat/whiteboard-s1 into dev
pull from: feat/whiteboard-s1
merge into: kayg:dev
kayg:main
kayg:feat/style-sheet-fixes
kayg:storage/wal-checkpoint-off-save-1051
kayg:t3/paged-search-reconcile-final
kayg:feat/pass8
kayg:review/calendar-2
kayg:fix/shared-row-swipes
kayg:feat/contrast
kayg:dev
kayg:feat/collections-db
kayg:fix/instant-keys-1056
kayg:feat/money-round
kayg:perf/stalls-1054
kayg:wip/tiering-v3-cold4
kayg:wip/tiering-v3-cold5
kayg:port/rows-actions
kayg:port/rows-drop
kayg:port/hidden-blocks
kayg:port/rows
kayg:port/port-tables
kayg:port/port-tables-2
kayg:t3/mail-1011-liveness
kayg:port/devices
kayg:port/port-attachments
kayg:port/port-attachments-2
kayg:port/port-attachments-3
kayg:docs/design-consistency
kayg:docs/engineering-standards
kayg:fix/rusqlite-0.41-rustsec-2026-0459
kayg:feat/iphone-fixes
kayg:shared/restore-and-stale-918-919
kayg:fix/phone-top-band-contrast
kayg:feat/notes-approve
kayg:perf/soak-max-gate
kayg:feat/files-s1-identity
kayg:fix/lifecycle-event-id
kayg:feat/quickfix
kayg:wip/tiering-v3-cold
kayg:perf/web-mockup-frame-fixes
kayg:port/contacts-merge
kayg:port/contacts-edit
kayg:test/shared-room-no-deleted-text
kayg:perf/first-paint-credits
kayg:fix/shared-history-after-grant
kayg:fix/phone-swipe-regressions
kayg:feat/contrast-r1
kayg:review/sharing-pr3-review
kayg:feat/tiering-v3-s2-tags
kayg:feat/folder-drop
kayg:fix/deskpills-lazy-share
kayg:feat/sharing-s1-pr3
kayg:tmp/money-round-before
kayg:fix/phone-pane-backdrop-roots
kayg:fix/palette-preload-chips
kayg:fix/invite-defaults
kayg:port/tasks-matrix
kayg:fix/restore-green-gates
kayg:fix/sharing-fast-path-hardening
kayg:t3/photos-s1
kayg:feat/tiering-v3-s1-namespace
kayg:notes-archive-hide
kayg:feat/tasks-actions
kayg:t3/photos-plan-slice-one
kayg:t3/paged-search-reconcile
kayg:t3/smooth-pane-transitions
kayg:t3/index-position-startup-scan
kayg:fix/private-staging-759b-r2
kayg:feat/dav-transport
kayg:feat/imap-notes-fetch
kayg:feat/imap-notes-projection
kayg:feat/imap-notes-readonly
kayg:feat/imap-notes-auth
kayg:feat/imap-notes-server-foundation
kayg:docs/undo-block-ids-plan
kayg:fix/undo-768
kayg:proto/block-identity-v7d
kayg:issue/carddav-read-perf-fix-r2
kayg:issue/carddav-read-r2
kayg:docs/imap-766-plan-v2
kayg:docs/imap-notes-plan
kayg:docs/quota-plan-2
kayg:fix/parallel-test-flakes
kayg:feat/contacts-companion-pure
kayg:docs/calendar-backend-v2-plan
kayg:feat/calendar-ical-converter
kayg:docs/tasks-writes-v2-plan
kayg:docs/carddav-writes-v2-plan
kayg:docs/contacts-import-v2-plan
kayg:issue/610-pm-midnight
kayg:feat/calendar-v2-s1-containment
kayg:docs/dav-recorder-v2-plan
kayg:plan/previews-865
kayg:plan/save-log-durable-entry
kayg:fix/e2e-data-on-ram
kayg:feat/appwindow3
kayg:feat/appwindow2
kayg:feat/appwindow
kayg:feat/money-p1
kayg:feat/keys-sheet
kayg:review/calendar-2-themes
kayg:feat/smooth-cursor
kayg:fix/float-style
kayg:review/calendar-2-float
kayg:release/2026-11-06-hotfix
kayg:archive/port/rows-drop-code
kayg:archive/port/rows-actions
kayg:archive/port/rows
kayg:scratch/tasks-894-ui-gates
kayg:review/calendar-2-night-wip
kayg:release/2026-11-05
kayg:archive/feat/tiering-v3-s1-namespace
kayg:archive/flaky/rows-drop-fixed
kayg:archive/flaky/rows-actions
kayg:archive/feat/tiering-v3-reader
kayg:archive/feat/tiering-v3-roots
kayg:archive/flaky/rows
kayg:sim/bm15-final
kayg:sim/bm15-fix
kayg:sim/bm15-bis-932
kayg:sim/bm15-bis-909
kayg:sim/bm15
kayg:sim/bm15-bis-887
kayg:perf/tiering-option-b
kayg:port/style-3
kayg:port/style-2
kayg:port/style
kayg:fix/sw-lazy-precache
kayg:fix/vim-w-waits-for-save
kayg:fix/signout-test-races
kayg:fp-scratch/all
kayg:sim/bm15-first-paint
kayg:archive/bm15/rows-drop
kayg:archive/bm15/rows-actions
kayg:fix/palette-snippet-contrast
kayg:archive/bm15/rows
kayg:archive/bm15/hidden
kayg:archive/plan/save-log-durable-entry
kayg:mock/money-fix2
kayg:archive/fix/e2e-data-on-ram
kayg:mock/appearance-all
kayg:mock/pill-press
kayg:archive/docs/design-consistency
kayg:mock/auto-swipes
kayg:mock/mail-actions
kayg:archive/feat/mail-p1
kayg:mock/money-static
kayg:archive/review/standards-917
kayg:archive/docs/engineering-standards
kayg:perf/tiering-761-fix
kayg:mock/type-audit
kayg:mock/third-pane
kayg:feat/contacts-import-v2-s1
kayg:perf/executor-hot-path
kayg:archive/port/hidden-blocks
kayg:archive/port/devices
kayg:scratch/executor-on-894
kayg:scratch/executor-spans2
kayg:scratch/executor-spans
kayg:train/2026-11-03-bm14c
kayg:archive/port/rows-drop
kayg:feat/tiering-761-d-scale
kayg:feat/tiering-761-c-index
kayg:feat/tiering-761-b-reader
kayg:archive/review/sharing-pr3-review-9fec3d1f
kayg:train/2026-11-03-bm14b
kayg:perf/ports-lazy-budgets
kayg:feat/tiering-761-a-migration
kayg:train/2026-11-03-bm14
kayg:train/2026-11-03-bm12
kayg:archive/review/sharing-pr3-review
kayg:archive/feat/sharing-s1-pr3
kayg:train/2026-11-03-bm11
kayg:archive/feat/imap-notes-fetch
kayg:train/2026-11-03-bm10
kayg:archive/review/sharing-pr3-review-code
kayg:archive/plan/previews-865
kayg:train/2026-11-02-bm9
kayg:archive/port/port-attachments-3
kayg:archive/port/contacts-merge
kayg:fix/motion-audit-859
kayg:train/2026-11-02-bm8
kayg:archive/scratch/bm8-prep
kayg:archive/port/port-pickers
kayg:archive/port/port-tables-2
kayg:archive/port/port-tables
kayg:archive/feat/sharing-s1-pr3-code
kayg:archive/scratch/bm7-fixed
kayg:train/2026-11-02-bm7
kayg:archive/fix/parallel-test-flakes-code-minipc01
kayg:train/2026-11-02-bm6
kayg:docs/imap-766-readonly-slice
kayg:feat/dav-recorder-v3
kayg:research/788-diagnosis
kayg:archive/fix/parallel-test-flakes
kayg:archive/perf/pr792-cold-index-edit
kayg:docs/sharing-slice-1
kayg:archive/docs/imap-766-plan-v2
kayg:feat/dav-recorder-v2
kayg:archive/docs/dav-recorder-v2-plan
kayg:spike/imap-766-s0-cases
kayg:archive/fix/undo-768
kayg:feat/dav-recorder
kayg:archive/docs/contacts-import-v2-plan
kayg:archive/feat/calendar-ical-converter
kayg:feat/contacts-import
kayg:perf/cold-growth-on-764
kayg:perf/cold-growth-on-tiering
kayg:archive/docs/tasks-writes-v2-plan
kayg:archive/docs/calendar-backend-v2-plan
kayg:archive/feat/contacts-companion-pure
kayg:feat/tasks-set-status
kayg:feat/tasks-move-reorder
kayg:archive/docs/carddav-writes-v2-plan
kayg:archive/feat/calendar-v2-s1-containment
kayg:feat/tasks-delete-promote-duplicate
kayg:archive/feat/dav-transport
kayg:archive/fix/carddav-rebuild-r1
kayg:archive/fix/carddav-retention-r1
kayg:feat/carddav-writes
kayg:perf/quota-on-tiering
kayg:perf/quota-simple
kayg:perf/cold-growth-on-quota-stack
kayg:feat/calendar-identity
kayg:feat/calendar-event-parser
kayg:feat/calendar-props-maps
kayg:port/glass-when-ring
kayg:feat/tiering-761-s1
kayg:wip/10by32-01-impl-759b-scratch-20261030
kayg:wip/6by32-01-bm3-webkit-pause-20261030
kayg:wip/10by32-01-bm3-chromium-pause-20261030
kayg:wip/6by32-01-tier-761-s1-pause-20261030
kayg:spike/imap-766-s0
kayg:wip/6by32-02-calternal-pause-20261030
kayg:wip/8by64-01-review-688-pause-20261030
kayg:wip/6by32-01-verify-744-pause-20261030
kayg:wip/6by32-01-verify-742-pause-20261030
kayg:fix/private-staging-759b
kayg:wip/6by32-01-review-748-pause-20261030
kayg:wip/6by32-01-review-733c-pause-20261030
kayg:wip/6by32-01-review-733b-pause-20261030
kayg:wip/6by32-01-perf-idle-8-pause-20261030
kayg:wip/6by32-01-perf767-base-pause-20261030
kayg:wip/6by32-01-perf767b-767-pause-20261030
kayg:wip/6by32-01-perf767b-764-pause-20261030
kayg:wip/6by32-01-perf767-767-pause-20261030
kayg:wip/6by32-01-perf767-764-pause-20261030
kayg:wip/6by32-01-lists-b-pause-20261030
kayg:wip/6by32-01-ids-verify5-pause-20261030
kayg:wip/6by32-01-ids-verify4-pause-20261030
kayg:review/calendar-month
kayg:wip/10by32-02-undo-768-20261030
kayg:test/ids-verify3
kayg:wip/10by32-02-bm3-chromium-20261030
kayg:wip/10by32-01-review-753-20261030
kayg:wip/10by32-01-perf-idle-2-20261030
kayg:wip/10by32-01-bm2-webkit2-20261030
kayg:plan/759b-staging
kayg:train/2026-10-30-bm2
kayg:review/758b-tests
kayg:review/758-tests
kayg:review/764d-tests
kayg:review/767b-tests
kayg:review/preview-2026-10-29
kayg:review/767-tests
kayg:docs/tiering-731-plan
kayg:wip/c6b02-when2
kayg:wip/c6b02-tasks-create-fix5
kayg:wip/c6b02-settings-frost-mock
kayg:wip/c6b02-settings-frost-base
kayg:wip/c6b02-settings-frost
kayg:wip/c6b02-ring
kayg:wip/c6b02-review-733d
kayg:wip/c6b02-bm1-full-a
kayg:wip/compute02-when-field
kayg:wip/compute02-webkit-lists-repro
kayg:wip/compute02-train-bl2-dev
kayg:wip/compute02-dev-green-pw164
kayg:docs/deploy-plan
kayg:review/764c-tests
kayg:review/764b-tests
kayg:review/748g-tests
kayg:review/764-tests
kayg:review/759b-tests
kayg:fix/storage-owner-liveness-642
kayg:fix/storage-fix-7
kayg:wip/compute02-storage-fix-7
kayg:review/759-tests
kayg:feat/tiering-731
kayg:wip/tiering-731-first-attempt
kayg:wip/compute02-storage-fix-1
kayg:review/754g-tests
kayg:perf/idle-honest-2
kayg:review/754f-tests
kayg:review/754e-tests
kayg:review/755-tests
kayg:review/754d-tests
kayg:review/754c-tests
kayg:review/754b-tests
kayg:review/754-tests
kayg:fix/storage-private-tmp-642-dev
kayg:wip/compute02-verify-750
kayg:test/ids-verify5
kayg:test/ids-verify4
kayg:fix/storage-exact-file-quarantine-642
kayg:wip/compute02-verify-740
kayg:perf/one-flush-save
kayg:review/calendar-static
kayg:wip/compute02-verify-737
kayg:review/indexing-ring
kayg:review/when-field-2
kayg:wip/compute02-review-733
kayg:proto/block-identity-2-review
kayg:proto/block-identity-review
kayg:wip/c6b02-tc-design
kayg:review/when-field
kayg:issue/tasks-create-ids
kayg:issue/tasks-create
kayg:review/combined
kayg:wip/compute02-review-combined
kayg:review/task-polish
kayg:review/top-buttons
kayg:review/q1-q5
kayg:train/2026-10-26-bl2
kayg:archive/wt-398h
kayg:archive/train-bm-proptest-seed
kayg:archive/integ325-293
kayg:archive/integ325-ci
kayg:archive/client-auth-review-baseline
kayg:archive/wt-sim-4853
kayg:archive/wt-sim-4811
kayg:archive/wt-448m
kayg:archive/wt-398a-allocator
kayg:issue/calendar-adr
kayg:archive/old/train/2026-10-23bk2
kayg:archive/old/train/2026-10-23bk
kayg:issue/469-mockup-9a
kayg:issue/smart-tasks-mockup
kayg:issue/469-menus
kayg:issue/652-signout-flake
kayg:issue/652-history-fix7
kayg:issue/652-history-fix6
kayg:archive/old/issue/spring-check-perf
kayg:issue/spring-check-perf
kayg:issue/659-rename-fast
kayg:archive/old/train/2026-10-21ar
kayg:issue/search-hardening-3
kayg:issue/652-history-fix5
kayg:issue/660-port-sheets-glass
kayg:issue/652-history-fix4
kayg:issue/652-history-fix3
kayg:issue/652-history-fix2
kayg:issue/652-history-flake
kayg:train/2026-10-21an
kayg:issue/settings-admin-port
kayg:issue/search-port
kayg:train/2026-10-20am
kayg:issue/storage-split-fix2
kayg:issue/storage-split
kayg:archive/old/issue/folder-ids-fix
kayg:train/2026-10-20al
kayg:archive/old/issue/folder-ids
kayg:train/2026-10-20ak
kayg:issue/tables-mockup
kayg:train/2026-10-19aj
kayg:train/2026-10-19ai
kayg:issue/469-merge-fixes
kayg:issue/sidebar-band
kayg:archive/old/issue/608-settings-spec
kayg:train/2026-10-19ah
kayg:issue/swipe-offscreen
kayg:train/2026-10-19ag
kayg:archive/old/issue/590-nlp-adr
kayg:archive/old/issue/587-event-after-write-2
kayg:train/2026-10-19af
kayg:archive/old/issue/587-event-after-write
kayg:issue/469-pill-room-c
kayg:issue/469-pill-room
kayg:train/2026-10-19ae
kayg:issue/469-narrow-handle
kayg:issue/397-ios-swipe-2
kayg:archive/old/issue/adrs-photos-files-tasks
kayg:issue/469-desk-fixes
kayg:archive/old/issue/auto-update-adr
kayg:issue/469-filter-gap
kayg:issue/469-port-1b
kayg:issue/442-opacity-flake
kayg:archive/397-ios-swipe-2
kayg:issue/327-web-fast-3
kayg:archive/old/issue/469-port-1
kayg:issue/469-port-1
kayg:issue/327-web-fast-2
kayg:archive/old/issue/327-web-fast
kayg:archive/old/issue/425-stt-bench-vq1
kayg:archive/old/issue/445-no-bleed
kayg:archive/old/issue/400-swipe-mockup-2
kayg:issue/426-client-review
kayg:issue/426-client-2
kayg:issue/426-client
kayg:archive/old/issue/476-safe-area-lab
kayg:archive/445-top-light-2
kayg:archive/old/issue/445-top-light
kayg:issue/471-blocks-mockup
kayg:archive/old/issue/448-links-app-2
kayg:archive/old/issue/448-links-app
kayg:archive/old/issue/398-cold-links
kayg:issue/434-442-small-2
kayg:issue/434-442-small
kayg:archive/old/issue/398-unload
kayg:archive/old/issue/445-bottom-band
kayg:issue/445-bottom-band
kayg:issue/351-rem-3
kayg:archive/312-views-mockup
kayg:issue/351-rem-2
kayg:issue/351-rem
kayg:archive/old/issue/327-first-note
kayg:issue/395-width-phone
kayg:archive/old/issue/327-typing
kayg:issue/396-ios-edges
kayg:issue/397-ios-swipe
kayg:archive/398-allocator
kayg:archive/old/issue/327-notes-index
kayg:issue/345-347-contrast-empty-2
kayg:archive/old/issue/44-arenas
kayg:issue/44-arenas
kayg:archive/integ325
kayg:archive/old/issue/327-perf-harness
kayg:archive/old/issue/44-thp
kayg:issue/44-thp
kayg:archive/old/issue/285-sticky-pills
kayg:archive/old/issue/44-trim-3
kayg:issue/44-trim-3
kayg:archive/old/issue/165-cards
kayg:archive/old/issue/165-picker-2
kayg:archive/old/issue/212-multi-select
No reviewers
Labels
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
1 participant
Notifications
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!1015
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/whiteboard-s1"
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?
Plan
Implement Whiteboard slice 1 as a read-only-on-open
.excalidraw.mdformat plug-in and a structured room contract on Notes' existing Yrs 0.28 sync path. Plain JSON stays byte-preserving for unknown fields and sections; compressed legacy files stay byte-identical until a real edit, which writes uncompressed JSON and retains decoded unknown data. Element IDs are stable eight-character Obsidian-compatible IDs. There is no board UI and no feature flag in this slice.Limits and complexity
elements, keyed by stable element ID, using the existing Notes route and room writer. Local view state remains local.Failure table
rejects_large_or_malformed_updates_before_applyrevoked_updates_and_frames_are_refusedrate_limited_operation_stays_in_outboxdevyet; see open #1010legacy_attachment_migration_is_recoverable_at_each_boundaryremains pendingFirst-PR gates
The slice includes the no-write open tests, plain/compressed round trips, stable-ID and text/link projections, admission limits, Y.Map convergence and reconciliation, authorized save/debounce, revoke fencing, offline retry, rate-limit retry, board/item permission isolation, and the 2,000-element, 300-reference, and 10-client fixtures. The approved bundle gate requires zero first-paint Whiteboard JS/CSS and measured lazy editor budgets with
initial: false; Notes save/sync requires ABAB ×5 at one perf epoch with a dev-vs-dev control. Gate results and measured tables will be posted in PR comments.The legacy attachment migration test is the one dependency gap: current
devhas no stable Files item identity contract. This PR is WIP while the shared Files identity API and required Notes perf comparison are pending. It is not ready for merge.feat(whiteboard): file and sync foundation (slice 1)to WIP: feat(whiteboard): file and sync foundation (slice 1)Slice 1 evidence: bundle, package research, and focused gates
Bundle spike
Measured on dev-01 from the exact PR head with the existing bundle harness:
nix develop -c bash -c '~/bin/slot bash perf/web.sh --bundle-only --gate'All sizes below are KiB Brotli.
WhiteboardEditorlazy entryThe budget file has 97 measured Whiteboard JavaScript allowances and one CSS allowance, each
initial: false. The existingweb.bundle.total_js_brotliallowance remains 488.3 KiB; there is no guessed Whiteboard total.Excalidraw package search
Brave search for “@excalidraw/excalidraw tree shaking package exports” surfaced the package documentation describing an ESM bundle and tree-shakable dependencies. Current npm metadata reports
@excalidraw/excalidraw0.18.1, MIT, root runtime exports plus./index.css; wildcard exports are types only, and the package does not declaresideEffects. The official integration guide uses the root package import and supports lazy loading; it documents no smaller runtime subpath. This slice therefore isolates the root import behind the lazy editor boundary and measures the actual bundle.Sources: npm latest metadata, Excalidraw integration guide, Brave search.
Focused gates
cargo fmt --all -- --checkcargo test -p calternal-notes --locked -j4bun run lintbun run checkbun run testlegacy_attachment_migration_is_recoverable_at_each_boundarydevhas no stable Files item identity API; see #1010. No parallel identity layer was added.calternal-perfon perf-01 with both perf locksThe upstream Obsidian fixture provenance and AGPL-3.0 license, matching this repository's root license, are recorded in
crates/notes/tests/fixtures/whiteboard/README.md.Bundle follow-up: module attribution and slice 2 split
Module rows below are Brotli Q11 source-map attribution from the baseline build. Aggregate sizes use the existing bundle harness on dev-01.
chunk-EIO257PC.js@mermaid-js/parsercorechunk-K2UTITRG.jsindex.jschunk-4HAMMTFAchunk-DU6HZSFFchunk-SHT3W25Yimage-blob-reduce3.0.1layout-base2.0.1chunk-LNGE3PJUSplit experiment
I reran
perf/web.sh --bundle-only --gatewith a temporary measurement-config change that lets Excalidraw's internal chunks split instead of forcing the whole package intoWhiteboardEditor. No product code or budget caps changed.WhiteboardEditorJS entryThe split route's static JS path is 263.729 KiB including its 0.528 KiB runtime import. The full closure includes every reachable dynamic chunk; it is not the set fetched on editor open. All 55 locale-related chunks (54 language packs, including English, plus percentages) are dynamic: 353.200 KiB total, with English at 0.287 KiB. Mermaid, file-access adapters, and the font-subsetting worker are also dynamic imports. The subset worker/shared chunks are 0.226 / 0.136 KiB.
The package has two resolved
roughjsversions (4.6.4 for Excalidraw and 4.6.6 under Mermaid) and twolayout-baseversions (1.0.2 and 2.0.1). ELK is absent from the lockfile. D3 and Mermaid dependencies are on-demand, not in the editor entry.Package and font notes for slice 2
The current npm release is
@excalidraw/excalidraw@0.18.1(published 2026-04-20). Its exports expose the root runtime entry and./index.css; wildcard exports are types only, and there is nosideEffectsdeclaration, so there is no supported smaller runtime subpath for consumer imports. The lock resolves@excalidraw/mermaid-to-excalidraw@2.2.2.Upstream has since merged lazy Mermaid loading (#12274) and per-diagram Mermaid chunks (#12481), which uses mermaid-to-excalidraw 3.1.0. Those changes post-date the published 0.18.1 package. The integration guide uses the root package import.
Excalidraw's font manager checks the scene's used families and loads only missing font faces. The package contains 234 WOFF2 files (12,800.703 KiB Brotli total), but the split output emits only the four Assistant UI faces (79.199 KiB Brotli); these files are separate assets, outside the JS/CSS closure. The seven existing Google Sans Flex / Maple Mono assets also appear in the normal app output (482.207 KiB Brotli), so they are shared app fonts. Slice 2 should serve the package's selected font files from a same-origin path and request only the family/style in use.
The existing measured Whiteboard budget lines remain unchanged and
initial: false; no aggregate Whiteboard total was guessed or added. The split experiment is measurement evidence, not a new budget proposal.Sources: npm 0.18.1 metadata, integration guide.
Latest-head bundle follow-up for slice 2
Measured on dev-01 at
40d588eeewithnix develop -c bash -c '~/bin/slot bash perf/web.sh --bundle-only --gate'. Sizes are KiB Brotli.The editor open path is 821.991 KiB smaller (75.7%). The full optional closure grows 121.150 KiB because the split emits more independently compressed chunks; it counts every dynamic feature, not a normal English board open. The app-only observed total is 473.060 KiB against the existing 488.3 KiB allowance. The budget gate passes. Each Whiteboard chunk budget is measured and
initial: false; there is no Whiteboard aggregate allowance.For slice 2, keep Mermaid behind its on-demand import (or drop the integration if it is not needed): the parser core is 110.530 KiB and Cytoscape is 109.907 KiB, both on demand; D3 dependencies are also on demand and ELK is absent from the lockfile. Locale output is 55 dynamic chunks / 353.200 KiB, with English at 0.287 KiB, so only English is needed on a default-language open and a selected locale can load when requested. The Excalidraw font manager loads missing families when the scene uses them. The package contains 234 WOFF2 files (12,800.703 KiB total); this build emits four Assistant UI faces (79.199 KiB) as separate assets, not JS/CSS. The font subset worker and its shared chunk are 0.226 / 0.136 KiB and dynamic.
The top-15 Brotli module table and duplicate
roughjs/layout-basenotes remain in the earlier bundle comment. The npm registry still reports 0.18.1 as latest, MIT, with only the root runtime and CSS runtime exports (wildcards are types; nosideEffectsdeclaration). Upstream Mermaid lazy-loading changes #12274 and #12481 post-date 0.18.1. See the earlier comment for the web-search and integration-guide sources.Slice 2's measured default-language open path is 264.016 KiB JavaScript (263.729 KiB static editor path plus the disjoint 0.287 KiB English locale chunk) and 18.010 KiB CSS. Mermaid, other locale packs, and scene-font files remain on demand; this is a measured path, not an aggregate budget.
The 0.18.1 export map also has no separate laser or collaboration runtime subpath. The top-15 source-map table attributes the Excalidraw modules, but cannot split those features out as consumer-selectable entries; dropping them would require an upstream build option or excluding the feature from v1.
Notes hot-path ABAB ×5
Measured on perf-02 on 2026-11-08, 16:52–17:09 IST. The before/after boot ID stayed
94fef04b-c6e4-4d3d-966d-9135d6f2dda1, with CPUs0-3online and pinned. The run used a fresh 10k Home per report, seed 1, and the samecalternal-perfharness for dev and PR binaries.Binary hashes: dev
calternal7c66ecd5b294523fbc56855f37d387ee8eb915709fbfe4b142c343a08e20f2c2; PRcalternaldaac9ecd8bdbdcb20aca4521b91b74a3eab092e6dfe14c143ebe3b20d31a794d; harnesscalternal-perfe2deb2e1bc2495c96a8d957a733e7e70cc0852867300cf4a279d0f322fb5a60e.Sequence: five dev controls, five
A-B-A-Brounds (A=dev,B=PR), then five dev controls. All 30 reports exited successfully and contained all three metrics. Each report had 200sync.round_tripandsync.save_acksamples, and 30sync.durable_writesamples.Values are medians of each report’s p50/p95. Sizes are milliseconds.
B−Aanddev post−precompare p95.sync.round_tripsync.save_acksync.durable_writeThe dev pre/post controls remained close on round-trip and save acknowledgement. The PR medians show lower p50s on all three paths, lower p95s on save acknowledgement and durable write, and a
0.008 msround-trip p95 increase (within the run-to-run spread). No material Notes hot-path regression appeared in this ABAB run.Gate status update
The earlier focused-gates table marked Notes hot-path ABAB ×5 pending. It completed on 2026-11-08 at the same epoch with five dev controls before and after and five A-B-A-B rounds; the full table, hashes, and run details are in comment #86506.
At latest head
40d588eee, Whiteboard first paint remains 0 KiB JS / 0 KiB CSS. The English default open path measures 264.016 KiB JS / 18.010 KiB CSS; the full optional closure measures 2,036.322 KiB across 156 JS chunks. Lazy budgets use measured per-chunk lines withinitial: false; no aggregate Whiteboard total was added. The top 15 module table and slice 2 split experiment are in comment #86444.The
legacy_attachment_migration_is_recoverable_at_each_boundarygate remains pending on the stable Files identity API from #1010.View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.Merge
Merge the changes and update on Forgejo.Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.