docs/plans/2026-04-21-slate-v2-full-core-editing-coverage-plan.md
Close the remaining high-value proof lanes after the huge-doc runtime architecture landed.
This is not coverage-percent work. The target is architecture-safety coverage: public core invariants, renderer-facing dirtiness, browser editing behavior, and contributor-facing example parity.
Phase 6: example parity open/mixed rows.
complete Core runtime identity and dirtiness matrixcomplete Partial/rich shell-backed paste browser proofcomplete Non-Chromium/mobile IME and selection proofcomplete Undo/redo/delete/backspace after DOM-owned synccomplete Large-doc runtime with voids, inlines, tables, shadow DOMin_progress Example parity open/mixed rowspending Full current-vs-legacy core helper-family compareEditor.getPathByRuntimeId(editor, runtimeId) and instance
editor.getPathByRuntimeId(runtimeId).bun test ./packages/slate/test/surface-contract.ts --bail 1bun test ./packages/slate/test/snapshot-contract.ts --bail 1bun test ./packages/slate/test/transaction-contract.ts --bail 1bun test ./packages/slate/test/query-contract.ts --bail 1bun run bench:slate:6038:localbun run bench:core:normalization:compare:localbun run bench:core:observation:compare:localbun run bench:core:huge-document:compare:localbunx turbo build --filter=./packages/slatebunx turbo typecheck --filter=./packages/slatebunx turbo build --filter=./packages/slate --forcebunx turbo typecheck --filter=./packages/slate --forcebun run lint:fixbun run lintrich editor surface to large-document-runtime.tsx with an
app-owned HTML insertData override and mark rendering proof.Editable shell-backed selection tracking so browser-handle/model
selections spanning unmounted content are treated as shell-backed without
relying only on Ctrl+A.bunx playwright test ./playwright/integration/examples/large-document-runtime.test.ts --project=chromiumbun test ./packages/slate-react/test/large-doc-and-scroll.tsx --bail 1bun test ./packages/slate-react/test/projections-and-selection-contract.tsx --bail 1bun test ./packages/slate-dom/test/clipboard-boundary.ts --bail 1bun run bench:react:rerender-breadth:localbun run bench:react:huge-document-overlays:localREACT_HUGE_COMPARE_BLOCKS=5000 REACT_HUGE_COMPARE_ITERATIONS=5 REACT_HUGE_COMPARE_TYPE_OPS=10 bun run bench:react:huge-document:legacy-compare:localbunx turbo build --filter=./packages/slate-dom --filter=./packages/slate-react --forcebunx turbo typecheck --filter=./packages/slate-dom --filter=./packages/slate-react --forcebun run lint:fixbun run lintmiddleBlockPromoteThenTypeMs.bunx playwright test ./playwright/integration/examples/large-document-runtime.test.ts --project=firefox --project=webkithistoryUndo short-circuitinput diff commitkeydown fallbacktoContainText assertions for this phase.bunx playwright test ./playwright/integration/examples/large-document-runtime.test.ts --project=chromiumbunx playwright test ./playwright/integration/examples/large-document-runtime.test.ts --project=firefox --project=webkitbun run lint:fixbun run lintbunx turbo build --filter=./packages/slate-dom --filter=./packages/slate-react --forcebunx turbo typecheck --filter=./packages/slate-dom --filter=./packages/slate-react --forcegetText() and insertText() so the proof can
distinguish model writes from DOM-only contenteditable mutation.undo() and proved model-owned inserted text undoes
back out of both the model and DOM in Chromium.ControlOrMeta+Z physical shortcut remains green when the
inserted model state is real.input, native keydown, and MutationObserver stayed unreliable in
the static example path.bunx playwright test ./playwright/integration/examples/large-document-runtime.test.ts --project=chromiumbunx playwright test ./playwright/integration/examples/large-document-runtime.test.ts --project=firefox --project=webkitbunx playwright test ./playwright/integration/examples/large-document-runtime.test.ts --project=chromium -g "undoes"bun run lint:fixbun run lintbunx turbo build --filter=./packages/slate-dom --filter=./packages/slate-react --forcebunx turbo typecheck --filter=./packages/slate-dom --filter=./packages/slate-react --forcegetText()insertText(text)undo()redo()deleteBackward()deleteForward()bunx playwright test ./playwright/integration/examples/large-document-runtime.test.ts --project=chromiumbunx playwright test ./playwright/integration/examples/large-document-runtime.test.ts --project=firefox --project=webkitREACT_HUGE_COMPARE_BLOCKS=5000 REACT_HUGE_COMPARE_ITERATIONS=5 REACT_HUGE_COMPARE_TYPE_OPS=10 bun run bench:react:huge-document:legacy-compare:localbun run lint:fixbun run lintbunx turbo build --filter=./packages/slate-dom --filter=./packages/slate-react --forcebunx turbo typecheck --filter=./packages/slate-dom --filter=./packages/slate-react --force17.30ms on middleBlockPromoteThenTypeMs
in the latest sample.large-document-runtime.test.ts.bunx playwright test ./playwright/integration/examples/large-document-runtime.test.ts --project=chromiumbunx playwright test ./playwright/integration/examples/large-document-runtime.test.ts --project=firefox --project=webkitbunx playwright test ./playwright/integration/examples/large-document-runtime.test.ts --project=chromium --project=firefox --project=webkit -g "inline content|void content|table content|Shadow DOM"bun run lint:fixbun run lintbunx turbo build --filter=./packages/slate-dom --filter=./packages/slate-react --forcebunx turbo typecheck --filter=./packages/slate-dom --filter=./packages/slate-react --forcehuge-document, because it still
presents legacy chunking while the replacement runtime lives in
large-document-runtime.huge-document row.
huge-document as explicit cut for replacement
parity instead of trying to rewrite it into the v2 runtime.large-document-runtime
browser rows plus bench:react:huge-document-overlays:local and the
5000-block legacy compare gatehuge-document would blur legacy comparison truth
instead of improving coveragedocs/slate-v2/ledgers/example-parity-matrix.mddocs/slate-v2/true-slate-rc-proof-ledger.mddocs/slate-v2/release-readiness-decision.mdpaste-html mixed row, because source is close but one formatting proof
remains incomplete.paste-html row.
bunx playwright test ./playwright/integration/examples/paste-html.test.ts --project=chromium.paste-html recovered.richtext, because source is close but multi-block transform rows remain
red/incomplete.richtext row.
bunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium.insertText instead of losing the first
character through sequential keypress timingrichtext recovered.bun run lint:fixbun run lintbunx turbo build --filter=./packages/slate-dom --filter=./packages/slate-react --forcebunx turbo typecheck --filter=./packages/slate-dom --filter=./packages/slate-react --forceeditable-voidsimageseditable-voids row.
bunx playwright test ./playwright/integration/examples/editable-voids.test.ts --project=chromiumbunx playwright test ./playwright/integration/examples/large-document-runtime.test.ts --project=chromiumeditable-voids recovered.imagesimages row.
bunx playwright test ./playwright/integration/examples/images.test.ts --project=chromiumimages recovered.code-highlightingmarkdown-previewmarkdown-shortcutsscroll-into-viewshadow-domstylingtablesimages ledger sync.
images is recovered, no mixed rows remain, but eight open example
rows and the full current-vs-legacy core helper-family compare are still
active owners.bun run lintbun completion-check must keep failing while status is pendingcode-highlighting, markdown-*, and tables rows.custom-placeholder row.
site/examples/ts/custom-placeholder.tsx.bunx playwright test ./playwright/integration/examples/placeholder.test.ts --project=chromiumcustom-placeholder recovered.code-highlightingmarkdown-previewmarkdown-shortcutsscroll-into-viewshadow-domstylingtablescustom-placeholder.
bun completion-check must keep failing while status is pendingstyling or shadow-dom, because both have small
source footprints and should classify quickly before the parser/highlighter
rows./examples/richtext report: Cmd+Z after typing did not update
the visible editor.packages/slate-react/src/components/editable.tsx now forces render
after keyboard undo/redo and native historyUndo / historyRedo.http://localhost:3100/examples/richtext
shows model and DOM both remove Undo Me after Meta+Zbunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromiumbunx playwright test ./playwright/integration/examples/large-document-runtime.test.ts --project=chromium -g "undo|redo|delete"bun test ./packages/slate-react/test/large-doc-and-scroll.tsx --bail 1bun test ./packages/slate-react/test/projections-and-selection-contract.tsx --bail 1bun run lint:fixbun run lintbunx turbo build --filter=./packages/slate-dom --filter=./packages/slate-react --forcebunx turbo typecheck --filter=./packages/slate-dom --filter=./packages/slate-react --force| Error | Attempt | Resolution |
|---|---|---|
| Partial shelled selection did not mark the root shell-backed | Initial browser proof | Fixed Editable to mark explicit shell-backed state for browser-handle/model selections. |
| Selector/subscription shell-backed tracking regressed 5000-block typing | Runtime fix attempt | Removed root rerender subscription; kept explicit shell-backed state for broad selection paths only. |
| Browser proof used stale package output | First partial-row rerun | Rebuilt slate-dom/slate-react before rerunning Playwright. |
| Firefox/WebKit undo after direct DOM sync did not remove inserted text | Phase 3 desktop expansion | Classified as Phase 4 owner instead of hiding it under IME/selection proof. |
| iOS/Appium contenteditable input is not reliable enough for automated behavior proof | Mobile proof review | Deferred mobile runtime proof with existing tooling evidence; do not call Playwright mobile emulation real IME proof. |
| DOM-only undo proof was too weak | Phase 4 model assertion | Reverted unproven runtime experiments; next slice must establish model+DOM typing proof first. |
| Playwright contenteditable mutation did not imply Slate model mutation | Phase 4 model assertion | Added browser-handle model read/write proof; keep DOM-only typing assertions out of Phase 4 closure. |
| Native input/keydown/MutationObserver model-sync attempts stayed unproven | Phase 4 runtime experiments | Reverted runtime experiments; keep model-owned proof and classify physical non-Chromium hotkeys separately. |
| Physical non-Chromium undo hotkeys did not deliver a trustworthy model/history signal | Phase 4 browser expansion | Kept model/history proof through browser handle; track physical shortcut transport separately if product needs it. |