Back to Plate

Lexical To Slate Processing Ledger

docs/editor-test-harvester/lexical/slate-processing-ledger.md

53.0.6369.6 KB
Original Source

Lexical To Slate Processing Ledger

source report: report.md source inventory: inventory.md source test index: test-index.md plan: Slate v2 Lexical Harvest Test Processing Ralplan status: done generated_at: 2026-05-09 consolidated_at: 2026-05-09

Verdict

This pass accounts for every live Lexical inventory row at file granularity: 271 inventory rows, 137 runnable portable/portable-mixed files, and 1996 indexed test/describe/it line pointers.

The consolidation rerun found no new Lexical files, no removed Lexical files, no portable files missing from the index, no stale index files, and no unresolved top-level create-new, copy-now, or refactor-existing source rows in the selected apply lane.

The selected non-table apply lane is closed. Remaining rows are explicit future-owner deferrals: table model/navigation, raw mobile/device proof, slate-yjs collaboration browser proof, HR/block-void behavior, drag/drop, and optional extension/state/update-metadata/memory rows if those owners are accepted. Residual plugin/product rows are plate-owned when the right target is a Plate package, kit, example, docs page, or backlog item rather than raw Slate v2.

Do not copy Lexical tests one-for-one. Keep the invariant, steal the strongest proof shape, and reject Lexical internals.

Status Vocabulary

StatusMeaning
already-appliedThe selected Lexical apply lane already added or strengthened the matching Slate v2 proof.
coveredCurrent Slate v2 has a good enough proof row; no action unless a later audit finds drift.
refactor-existingStrengthen, split, rename, or broaden current Slate tests. Prefer this over duplicates.
create-newAdd a new Slate v2 unit/browser row.
deferValid behavior, but it needs raw device, yjs browser, table model, or a later accepted owner.
plate-ownedValid behavior, but it should fit Plate, not raw Slate. Name the likely Plate package/docs/example/backlog owner.
rejectNot a portable raw Slate behavior target.

Current Slate Owners

OwnerPath
Core model and query invariants.tmp/slate-v2/packages/slate/test
Clipboard model/DOM contracts.tmp/slate-v2/packages/slate/test/clipboard-contract.ts, .tmp/slate-v2/packages/slate-dom/test/clipboard-boundary.ts
Text units.tmp/slate-v2/packages/slate/test/text-units-contract.ts
Input runtime policy.tmp/slate-v2/packages/slate-react/test/model-input-strategy-contract.test.ts
DOM repair policy.tmp/slate-v2/packages/slate-react/test/dom-repair-policy-contract.ts
Browser stress rows.tmp/slate-v2/playwright/stress/generated-editing.test.ts
Paste HTML browser corpus.tmp/slate-v2/playwright/integration/examples/paste-html.test.ts
Plaintext browser input transport.tmp/slate-v2/playwright/integration/examples/plaintext.test.ts
Rich text browser behavior.tmp/slate-v2/playwright/integration/examples/richtext.test.ts
Table browser containment.tmp/slate-v2/playwright/integration/examples/tables.test.ts
Mentions/inline atom browser behavior.tmp/slate-v2/playwright/integration/examples/mentions.test.ts
Collaboration/history substrate.tmp/slate-v2/packages/slate/test/collab-history-runtime-contract.ts, .tmp/slate-v2/packages/slate-history/test/history-contract.ts

Plate-Owned Residual Routing

Residual familyStatusPlate ownerRaw Slate split
Link/autolink grammar, nested-link policy, unlink/relink UI, link styling, autolink parser/tokenizer matricesplate-ownedPlate link/autolink package, examples, docs, or backlogInline boundary, paste, and safe link insertion rows are already covered separately.
List/checklist indentation, empty-item exit, ordered metadata, checklist ARIA, list toolbar policyplate-ownedPlate list/checklist packages and list docsStructural list fragments, wrappers, and path/query behavior stay in Slate v2.
Markdown import/export, transformer grammar, MDX/custom transformers, markdown-link policy, code-fence serializer UXplate-ownedPlate markdown serializer/transformer package and docsMarkdown shortcut browser rows stay in Slate v2.
Mention/hashtag/keyword/date-time/emoji/equation/media plugin grammar and stylingplate-ownedPlate feature packages and examplesDecoration, inline atom, void, and markable-void substrate proofs stay in Slate v2.
React Composer, typeahead, nested composer, menu, plugin host, toolbar/product shell behaviorplate-owned when reusablePlate React/plugin ergonomics, kits, and examplesNo raw Slate target unless a framework-agnostic invariant is split out.

Processing Rows

Core Package Behavior

SourceStatusSlate ownerNext decision
../lexical/packages/lexical-code-shiki/src/__tests__/unit/LexicalCodeNodeTabs.test.tsalready-applied for Slate code-highlighting Tab behavior; reject/defer for Lexical command matrix.tmp/slate-v2/playwright/integration/examples/code-highlighting.test.tsSource-read complete with the matching lexical-code tab suite. Added browser proof that Tab inside a Slate code line inserts the example's configured spaces and advances the caret. Lexical INDENT_CONTENT_COMMAND/OUTDENT_CONTENT_COMMAND, backward-selection preservation matrix, Shiki tokenizer/theme loading, node class APIs, and product command dispatch stay out or require a future accepted code-block indent owner.
../lexical/packages/lexical-code/src/__tests__/unit/LexicalCodeNode.test.tsalready-applied for Slate code-highlighting multi-line indent/outdent; reject/defer for Lexical code-node internals.tmp/slate-v2/playwright/integration/examples/code-highlighting.test.ts, .tmp/slate-v2/site/examples/ts/code-highlighting.tsxSource-read complete. Added browser proof that Tab and Shift+Tab indent/outdent every selected Slate code line, and updated the example handler so collapsed Tab still inserts configured spaces while expanded code-line selections update line starts. Lexical constructor/createDOM/updateDOM/exportJSON, code language metadata policy, tokenizer/highlighter transform policy, command dispatch APIs, Alt+Arrow line shifting, Home/End visual-caret policy, node keys, raw mobile, collaboration, table-model, and issue claims stay out.
../lexical/packages/lexical-code/src/__tests__/unit/LexicalCodeNodeTabs.test.tsalready-applied for Slate code-highlighting Tab behavior; reject/defer for Lexical command matrix.tmp/slate-v2/playwright/integration/examples/code-highlighting.test.tsSame tab matrix as the Shiki package without Shiki loading. The accepted Slate behavior is the code-highlighting example's Tab-to-configured-spaces browser row. Lexical indent/outdent command semantics, backward-selection matrix, and code node class policy stay out unless a future code-block indent owner accepts them.
../lexical/packages/lexical-history/src/__tests__/unit/LexicalHistory.test.tsxalready-applied for accepted Slate history rows; reject/defer for Lexical command/shared-history internals.tmp/slate-v2/packages/slate-history/test/history-contract.tsSource-read complete. Added history package proofs that a new edit after undo clears redo history, selected block property changes undo and redo cleanly, and no-op updates are ignored while node property commits are undoable. Existing rows cover insert grouping, push/merge/skip metadata, composition merge/skip, restored selections, structural batches, delete/insertBreak/move undo, and custom props. Lexical CAN_UNDO/CAN_REDO command notifications, CLEAR_HISTORY command shape, shared parent/nested editor state, node-key/node-selection internals, React harness details, raw mobile, collaboration, table-model, and issue claims stay out.
../lexical/packages/lexical-html/src/__tests__/unit/LexicalHtml.test.tsalready-applied for selected-fragment clipboard export and paragraph alignment import; reject/defer for standalone HTML serializer and custom node export APIs.tmp/slate-v2/packages/slate-dom/test/clipboard-boundary.ts, .tmp/slate-v2/playwright/integration/examples/paste-html.test.ts, .tmp/slate-v2/site/examples/ts/paste-html-import.tsSource-read complete. Current Slate DOM clipboard contracts already prove selected-fragment payload export/import, and paste-html browser proof already covers legacy align, CSS text-align precedence, and invalid align rejection. Lexical $generateHtmlFromNodes as a standalone full-editor HTML serializer, node class exportDOM/importDOM, and custom DocumentFragment export APIs stay out until a generic Slate HTML serializer owner exists.
../lexical/packages/lexical-list/src/__tests__/unit/utils.test.tsalready-applied for public path/list ancestry behavior; reject for Lexical helper API shape.tmp/slate-v2/packages/slate/test/query-contract.tsSource-read complete. Added package proof that public Path/Node queries expose nested list depth, non-root top list ancestry, descendant list ancestors, and terminal/non-terminal list-item paths. Lexical $getListDepth, $getTopListNode, $isLastItemInList, command APIs, list class APIs, extension wiring, DOM serializer shape, raw mobile, collaboration, table-model, and issue claims stay out.
../lexical/packages/lexical-playground/__tests__/regression/231-empty-text-nodes.spec.mjsalready-applied for token-like destructive delete; reject for hashtag/plugin/CSS/collab harness.tmp/slate-v2/packages/slate/test/delete-contract.ts, normalization/leaf lifecycle/rendered DOM ownersSource-read complete. Added package proof that repeated Backspace through token-like marked text collapses to a canonical empty block with selection at [0, 0] offset 0. Existing lifecycle owners cover empty block anchors and invalid empty leaf cleanup.
../lexical/packages/lexical-playground/__tests__/regression/3433-merge-markdown-lists.spec.mjsalready-applied for markdown-created adjacent list merge.tmp/slate-v2/playwright/integration/examples/markdown-shortcuts.test.ts, .tmp/slate-v2/site/examples/ts/markdown-shortcuts.tsxSource-read complete. Added browser proof that a markdown-created list immediately before an existing list becomes one list with two before one; the example now merges adjacent bulleted-list wrappers after applying the list shortcut.
../lexical/packages/lexical-playground/__tests__/regression/4661-insert-column-selection.spec.mjsdefertable model ownerDepends on table/column selection model; do not hide under generic selection tests.
../lexical/packages/lexical-playground/__tests__/regression/4697-repeated-table-selection.spec.mjsdefertable model ownerSame table selection model boundary as #2558.
../lexical/packages/lexical-rich-text/src/__tests__/unit/LexicalHeadingNode.test.tsalready-applied for heading Enter behavior; reject for class/DOM API rows.tmp/slate-v2/playwright/integration/examples/richtext.test.ts, .tmp/slate-v2/site/examples/ts/richtext.tsx, core split/transform ownersSource-read complete. Browser proof covers middle heading split, heading-end paragraph insertion, and empty-heading paragraph insertion. The richtext example handles end/empty paragraph-after policy while core split covers middle split. Constructor/createDOM/updateDOM/setTag/$create/$is/node key/theme rows stay out.
../lexical/packages/lexical-rich-text/src/__tests__/unit/LexicalQuoteNode.test.tsalready-applied for empty blockquote Enter behavior; reject for class/DOM API rows.tmp/slate-v2/playwright/integration/examples/richtext.test.ts, .tmp/slate-v2/site/examples/ts/richtext.tsxSource-read complete. Browser proof covers Enter in an empty blockquote creating a paragraph after the quote. Constructor/createDOM/updateDOM/$create/node key/theme rows stay out.
../lexical/packages/lexical-selection/src/__tests__/unit/$sliceSelectedTextNodeContent.test.tsalready-applied for selected text fragment slicing; reject for helper API internals.tmp/slate-v2/packages/slate/test/clipboard-contract.tsSource-read complete. Package proof now covers a selection spanning unmarked and bold text leaves, returning sliced fragment leaves without mutating source text. Lexical helper API shape, node keys, token/segmented internals, DOM/browser transport, raw mobile, collaboration, table-model, and issue claims stay out.
../lexical/packages/lexical-utils/src/__tests__/unit/LexicalUtilsInsertNodeToNearestRoot.test.tsxalready-applied for highest-block insertion; covered/reject for the rest.tmp/slate-v2/packages/slate/test/transforms-contract.ts, insertNodes fixturesSource-read complete. Added direct package proof that insertNodes with mode: 'highest' splits the highest selected block and inserts the block node at the root level. Existing insertNodes path/block/selection fixtures cover paragraph middle/start/end, empty paragraph, root start/child/end, and default selection insertion rows. Lexical command dispatch, node keys, decorator node class shape, shadow-root wording, and list HTML specifics stay out or route to list/plugin owners.
../lexical/packages/lexical-utils/src/__tests__/unit/LexicalUtilsSplitNode.test.tsxalready-applied for root split rejection; covered for split rows.tmp/slate-v2/packages/slate/test/transforms-contract.ts, splitNodes fixtures, operations contractsSource-read complete. Added public transform proof that Editor.splitNodes rejects the editor root with a direct root-split error instead of leaking an internal root-path error. Existing splitNodes fixtures and operation/snapshot contracts cover paragraph middle/start/end, multi-text element split, nested block split, highest-mode ancestor split, marks/property preservation, selection rebase, and root operation rejection. Lexical node keys, $splitNode helper API, HTML output shape, and list-specific DOM rows stay out or route to list/plugin owners.

Serialization, Parsing, Marks, And Rich Text

SourceStatusSlate ownerNext decision
../lexical/packages/lexical-list/src/__tests__/unit/LexicalListItemNode.test.tsalready-applied for non-empty list-item split; defer/reject for plugin-policy and Lexical internals.tmp/slate-v2/packages/slate/test/snapshot-contract.ts, existing list fragment/delete ownersSource-read complete. Package proof now covers insertBreak inside a non-empty list item splitting the item while preserving the list wrapper. Lexical class/DOM/update/create/type-guard/export rows stay rejected; replace/remove nested-list normalization, indent/style inheritance, and ordered-list restart policy stay deferred to explicit list-plugin/model owners.
../lexical/packages/lexical-list/src/__tests__/unit/LexicalListNode.test.tsalready-applied for numbered-list wrapper creation; defer/reject for plugin-policy and Lexical internals.tmp/slate-v2/packages/slate/test/snapshot-contract.ts, existing list fragment/query ownersSource-read complete. Package proof now covers converting selected top-level blocks to list items and wrapping them in a numbered-list wrapper. Lexical class/DOM/depth classes/update/create/type-guard/subclass rows stay rejected; append/splice coercion, checklist role cleanup, and list-value transforms stay deferred to explicit list-plugin/model owners.
../lexical/packages/lexical-list/src/__tests__/unit/ListExtension.test.tsplate-owned/rejectPlate list/checklist package if extension ergonomics are acceptedLexical extension wiring is not raw Slate. Reopen only for Plate list/plugin ergonomics or if a framework-agnostic list invariant is split out.
../lexical/packages/lexical-list/src/__tests__/unit/formatList.test.tscovered/plate-owned/reject.tmp/slate-v2/packages/slate/test/snapshot-contract.ts, markdown/richtext/browser list owners, Plate list-exit/list-normalization/list-indent ownersSource-read complete. Existing Slate owners cover root list formatting, numbered/bulleted wrapper creation, and non-empty list continuation. Empty-list-item exit/split, whitespace-only exit, decorator-list extension, table-cell insertion, strict subclass preservation, and indent/outdent helper behavior are Plate plugin/model/table/product policies unless a raw invariant is split out.
../lexical/packages/lexical-list/src/__tests__/unit/registerListStrictIndentTransform.test.tscovered/defer.tmp/slate-v2/playwright/integration/examples/paste-html.test.ts, future list-normalization/HTML serializer ownerSource-read complete. Existing paste-html browser corpus already covers compact malformed nested-list HTML import. Lexical's exact strict indentation rewrite and $generateHtmlFromNodes output shape stay deferred until Slate accepts a list-normalization or generic HTML serializer owner.
../lexical/packages/lexical-markdown/src/__tests__/unit/LexicalMarkdown.test.tscovered/plate-owned/reject.tmp/slate-v2/playwright/integration/examples/markdown-shortcuts.test.ts, Plate markdown serialization/shortcut ownerSource-read complete. Current Slate v2 has markdown shortcut and preview examples, not a markdown import/export package. Heading/list/quote shortcut behavior is already covered by browser examples; broad import/export, normalization, nested fences, whitespace, hard breaks, link/mark escaping, MDX/custom transformers, list-marker metadata, checklist, and code-fence Enter behavior are Plate markdown owner rows unless a raw shortcut invariant is split out.
../lexical/packages/lexical-markdown/src/__tests__/unit/MarkdownTransformers.test.tsplate-owned/rejectPlate markdown-link transformer owner; existing inline-link clipboard/browser owners for adjacent raw behaviorSource-read complete. The file tests Lexical markdown link transformer behavior: preserving text before a parsed markdown link, avoiding greedy matches, and not creating a markdown link inside an existing link. Current Slate v2 has raw inline-link boundary and clipboard proofs; markdown-link parser/serializer policy belongs in Plate.
../lexical/packages/lexical-playground/__tests__/e2e/ClearFormatting.spec.mjsalready-applied.tmp/slate-v2/playwright/integration/examples/richtext.test.ts, .tmp/slate-v2/site/examples/ts/richtext.tsxSource-read complete. Added richtext clear-formatting browser proof and example command for selected mark removal plus block alignment reset while preserving blockquote structure. Link, mention, hashtag, indent/outdent, toolbar-shell styling, raw mobile, collaboration, table-model, and issue rows stay out.
../lexical/packages/lexical-playground/__tests__/e2e/CodeBlock.spec.mjsalready-applied for selected paragraph-to-code-block conversion and existing code-line editing rows; defer/reject for residual code-fence/navigation/product rows.tmp/slate-v2/playwright/integration/examples/code-highlighting.test.ts, .tmp/slate-v2/site/examples/ts/code-highlighting.tsx, .tmp/slate-v2/packages/slate/test/snapshot-contract.tsSource-read complete. Added browser proof that selecting paragraph text and using the code-block control creates a code block with code-line content while preserving existing code blocks. Existing code-highlighting rows cover Enter, collapsed Tab, and selected multi-line Tab/Shift+Tab. Markdown code fences, language parser matrix, line movement, visual-caret navigation, theme DOM, raw mobile, collaboration, table-model, and issue rows stay out.
../lexical/packages/lexical-playground/__tests__/e2e/ElementFormat.spec.mjsalready-applied for empty-paragraph center alignment; defer/reject for link+indent/product rows.tmp/slate-v2/playwright/integration/examples/richtext.test.ts, .tmp/slate-v2/site/examples/ts/richtext.tsx, future link/block-format and indent ownersSource-read complete. Added richtext browser proof that a fresh empty paragraph can be center-aligned from the toolbar while preserving collapsed selection. The richtext example now targets the containing block explicitly for collapsed alignment. Lexical link+indent exact row stays deferred because current Slate has no combined link/block-format owner and no indent owner; toolbar shell/theme rows stay rejected.
../lexical/packages/lexical-playground/__tests__/e2e/Headings/HeadingsBackspaceAtStart.spec.mjsalready-applied.tmp/slate-v2/playwright/integration/examples/richtext.test.tsSource-read complete. Added browser proof that Backspace at offset 0 of the first heading is a no-op: the heading text, heading element, and collapsed selection stay intact. Lexical Playground setup, toolbar shell, raw mobile, collaboration, table-model, and issue rows stay out.
../lexical/packages/lexical-playground/__tests__/e2e/Headings/HeadingsEnterAtEnd.spec.mjsalready-applied.tmp/slate-v2/playwright/integration/examples/richtext.test.ts, .tmp/slate-v2/site/examples/ts/richtext.tsxSource-read complete. Existing richtext browser proof covers Enter at the end of a heading converting the next block to a paragraph while preserving the heading. The richtext example owns this through handleExitBlockEnter. Lexical Playground setup, toolbar shell, theme DOM, raw mobile, collaboration, table-model, and issue rows stay out.
../lexical/packages/lexical-playground/__tests__/e2e/Headings/HeadingsEnterInMiddle.spec.mjsalready-applied.tmp/slate-v2/playwright/integration/examples/richtext.test.tsSource-read complete. Existing richtext browser proof covers Enter in the middle of a heading splitting it into two headings. Lexical Playground setup, toolbar shell, theme DOM, raw mobile, collaboration, table-model, and issue rows stay out.
../lexical/packages/lexical-playground/__tests__/e2e/Indentation.spec.mjscovered/defer/rejectexisting code-highlighting and list outdent owners; future paragraph/list/table indent ownerSource-read complete. Existing Slate rows cover code-line Tab/Shift+Tab and basic list outdent model flow. Paragraph/table indent depth, max-depth caps, nested list indent limits, negative indent import/outdent cleanup, and toolbar shell stay deferred or rejected until Slate accepts an indent/list/table policy owner.
../lexical/packages/lexical-playground/__tests__/e2e/List.spec.mjsalready-applied for toolbar list toggle/conversion; covered/plate-owned/reject for residual list-plugin policy.tmp/slate-v2/playwright/integration/examples/richtext.test.ts, .tmp/slate-v2/packages/slate/test/snapshot-contract.ts, Plate list-plugin/list-exit/list-indent ownersSource-read complete. Added richtext browser proof that selected blocks can be turned into a bulleted list, toggled back to paragraphs, turned into a numbered list, and converted back to a bulleted list from the toolbar. Existing snapshot/browser owners cover basic list wrapper creation, numbered/bulleted list formatting, non-empty list continuation, and markdown-created adjacent list merge. Checklist, indent/outdent depth, empty-item exit, list collapse-at-start, ordered start metadata, format-menu list splitting, autolink/list policy, and exact Lexical DOM output are Plate list/product rows unless a raw invariant is split out.
../lexical/packages/lexical-playground/__tests__/e2e/Markdown.spec.mjsalready-applied for ordered-list start shortcut; covered/defer/reject for residual markdown transformer policy.tmp/slate-v2/playwright/integration/examples/markdown-shortcuts.test.ts, .tmp/slate-v2/site/examples/ts/markdown-shortcuts.tsx, future markdown serializer/transformer ownersSource-read complete. Added browser proof and example support for numeric ordered-list markdown shortcuts such as 25. , preserving the rendered <ol start="25">. Existing markdown-shortcuts rows cover headings, blockquote, bulleted lists, list continuation, and adjacent markdown-created list merge. Markdown import/export cycles, inline text transformers, emoji/image/equation decorators, code-formatted text transformer exclusions, selection-after-link-transform, list-marker export/copy, HR, code fences, raw mobile, collaboration, table-model, and theme DOM output stay deferred or rejected until explicit future owners accept them.
../lexical/packages/lexical-playground/__tests__/e2e/TextFormatting.spec.mjsalready-applied for mark hotkey insertion/toggle-off; covered/defer/reject for residual product formatting.tmp/slate-v2/packages/slate/test/snapshot-contract.ts, .tmp/slate-v2/playwright/integration/examples/richtext.test.ts, .tmp/slate-v2/site/examples/ts/richtext.tsx, future typography/product ownersSource-read complete. Added package proof that Editor.toggleMark and tx.marks.toggle clear inherited collapsed marks before the next insertion. Fixed tx.marks.toggle default value and richtext hotkey default prevention. Added browser proof that bold, italic, underline, and code hotkeys create formatted inserted text and clear active marks before subsequent text. Existing owners cover expanded mark add/remove, toolbar bold, clear formatting, warm toolbar mark selection, mark click/caret gauntlets, and partial selected-mark clearing. Capitalization, font-size/family, date-time/decorator formatting, toolbar active-state CSS, raw mobile, collaboration, table-model, and Lexical DOM output stay deferred or rejected until explicit future owners accept them.
../lexical/packages/lexical-playground/__tests__/e2e/TextEntry.spec.mjsalready-applied for heading-start paragraph insertion and marked-boundary Enter; covered/defer/reject for residual text-entry rows.tmp/slate-v2/playwright/integration/examples/markdown-shortcuts.test.ts, .tmp/slate-v2/site/examples/ts/markdown-shortcuts.tsx, .tmp/slate-v2/playwright/integration/examples/richtext.test.ts, plaintext/richtext input and generated stress owners, future soft-break ownerSource-read complete. Added browser proof that Enter at the start of a markdown-created heading inserts a paragraph before the heading and preserves selection in the heading, plus proof that native Enter at the boundary between plain and bold text splits into a plain paragraph followed by a bold paragraph. Basic typing, select-all replacement, partial replacement, character delete, word delete, and selection sync map to current plaintext/richtext input and generated stress rows. Soft-break/newline-node navigation stays deferred to an explicit soft-break/line-break owner; Lexical emoji/theme spans, browser/OS labels, raw mobile, collaboration, table-model, and issue claims stay out.
../lexical/packages/lexical/src/__tests__/unit/CodeBlock.test.tsalready-applied for code-source HTML import; covered/defer/reject for residual mixed HTML rows.tmp/slate-v2/playwright/integration/examples/paste-html.test.ts, .tmp/slate-v2/site/examples/ts/paste-html-import.ts, future HTML typography/serializer ownersSource-read complete. Added DataTransfer browser proof for Quip-style <pre>, VS Code-style white-space: pre line <div>s, and GitHub-style code tables importing as one code block without source gutters. The importer now extracts code-source text, preserves line breaks, normalizes non-breaking spaces, and strips trailing source newlines. Existing paste-html rows cover single-line inline <code> and supported text formatting. Source-token colors/bold keyword styling, broad Google Docs title inference, sub/sup typography, raw mobile, collaboration, table-model, and issue rows stay deferred or rejected until explicit future owners accept them.
../lexical/packages/lexical/src/__tests__/unit/LexicalEditorListener.test.tscovered/defer/reject.tmp/slate-v2/packages/slate/test/snapshot-contract.ts, .tmp/slate-v2/packages/slate/test/transaction-contract.ts, .tmp/slate-v2/packages/slate/test/collab-history-runtime-contract.ts, .tmp/slate-v2/packages/slate/test/apply-onchange-hard-cut-contract.tsSource-read complete. Slate already covers the portable subscriber lifecycle through Editor.subscribe/editor.subscribe unsubscribe, Editor.subscribeSource routing, and Editor.registerCommitListener cleanup/public commit rows. Lexical registerRootListener, registerEditableListener, private _listeners, setRootElement, and setEditable cleanup callback semantics are API/root-shell policy and stay deferred or rejected unless Slate accepts an explicit React root/editable lifecycle owner.
../lexical/packages/lexical/src/__tests__/unit/LexicalListPlugin.test.tsxalready-applied for empty-list toolbar toggle; defer/reject for residual plugin/list-policy rows.tmp/slate-v2/playwright/integration/examples/richtext.test.ts, .tmp/slate-v2/packages/slate/test/snapshot-contract.ts, future list-indent/list-normalization ownerSource-read complete. Added richtext browser proof that a fresh empty paragraph toggles into one bulleted-list item and back to one empty paragraph while preserving collapsed selection. Existing browser/snapshot owners cover selected block list toggle/conversion, list wrapper creation, and basic list outdent. Lexical React plugin setup, command dispatch shape, contenteditable/theme DOM snapshots, empty-list indent/outdent, and regression #7036 block-type-after-nested-list behavior stay deferred or rejected until Slate accepts explicit list-indent, list-normalization, or list-plugin policy owners.

Clipboard And Paste

SourceStatusSlate ownerNext decision
../lexical/packages/lexical-playground/__tests__/e2e/CopyAndPaste/html/HTMLCopyAndPaste.spec.mjsalready-applied for multiline paragraph and code-BR rows; defer for HR rows.tmp/slate-v2/playwright/integration/examples/paste-html.test.ts, .tmp/slate-v2/site/examples/ts/paste-html-import.tsSource-read complete. Added browser proof for multiline HTML paragraphs with extra raw newlines, and extended code-source HTML proof to <code> elements with `
` line breaks. HR insertion/splitting stays deferred to a future HR/block-void plus block-fragment owner.
../lexical/packages/lexical-playground/__tests__/e2e/CopyAndPaste/html/ImageHTMLCopyAndPaste.spec.mjsalready-applied.tmp/slate-v2/playwright/stress/generated-editing.test.tsMulti-image paste/undo applied; reopen only for distinct image attributes.
../lexical/packages/lexical-playground/__tests__/e2e/CopyAndPaste/html/LinksHTMLCopyAndPaste.spec.mjsalready-applied for accepted raw rows; plate-owned/reject for plugin policypaste-html, clipboard-contract, inline-link owners, and Plate link ownerSource-read complete. Simple anchor import, noisy link-in-list import, partial link fragment copy, and paste at inline-link boundaries are applied. Autolink URL paste, paste-inside-link splitting, nested link prevention, and multi-block paste through a link are Plate link-policy rows unless a raw inline-fragment invariant is split out.
../lexical/packages/lexical-playground/__tests__/e2e/CopyAndPaste/html/ListsHTMLCopyAndPaste.spec.mjsalready-applied for accepted HTML list import rows; defer/reject for plugin-policy rows.tmp/slate-v2/playwright/integration/examples/paste-html.test.ts, .tmp/slate-v2/packages/slate/test/clipboard-contract.tsSource-read complete. Existing paste-html browser rows cover basic unordered-list import, compact nested ul variants, and nested <div> boundaries inside list items. Clipboard fragment contracts cover structural fragment selection placement. Checklist private attributes stay rejected; top-level HR-in-list waits for a future HR/block-void plus list-split owner; Lexical toolbar indent/outdent assertions stay deferred or rejected under explicit list-indent policy.
../lexical/packages/lexical-playground/__tests__/e2e/CopyAndPaste/html/TablesHTMLCopyAndPaste.spec.mjsalready-applied for accepted import rows; defer for table layout/model rowspaste-html and future table model ownersSource-read complete. Google Docs, Quip, and Google Sheets table HTML import rows are applied. Custom widths, merge grids, nested block/inline table-cell normalization, merged cells, unequal rows, and empty rows stay deferred to accepted table layout/model owners.
../lexical/packages/lexical-playground/__tests__/e2e/CopyAndPaste/html/TextFormatHTMLCopyAndPaste.spec.mjsalready-appliedpaste-html/richtext ownersGoogle Docs BIU spans and guarded semantic <b> handling applied; highlight markup rejected as app mark policy.
../lexical/packages/lexical-playground/__tests__/e2e/CopyAndPaste/lexical/ContextMenuCopyAndPaste.spec.mjsrejectnoneBrowser context-menu product flow is not a raw Slate invariant unless a native clipboard gap is split out.
../lexical/packages/lexical-playground/__tests__/e2e/CopyAndPaste/lexical/CopyAndPaste.spec.mjsapplied for paragraph-into-quote; already-applied/covered for accepted residual rows; defer/reject for product policy.tmp/slate-v2/packages/slate-dom/test/clipboard-boundary.ts, .tmp/slate-v2/packages/slate/src/transforms-text/insert-fragment.ts, clipboard-contract, paste-html, inline-link, richtext, and stress ownersSource-read complete. Added DOM clipboard proof that a multi-paragraph fragment pasted into an empty block quote keeps the first text block in the quote and promotes the tail paragraph after it. The fragment insertion empty-block path now preserves the target block for the first pasted text block and keeps later text blocks source-shaped. Existing owners cover multi-block copy/paste, full-document replacement, inline link fragments, multiline plain-text splitting, font-size HTML, and empty-selection copy/cut preservation. Heading source-wrapper paste, hashtag/product spans, decorator embeds, exact plaintext rendering, native transport flake tags, raw mobile, collaboration, and table-model rows stay out.
../lexical/packages/lexical-playground/__tests__/e2e/CopyAndPaste/lexical/ListsCopyAndPaste.spec.mjsapplied.tmp/slate-v2/packages/slate/test/clipboard-contract.ts; .tmp/slate-v2/packages/slate/src/transforms-text/insert-fragment.tsAdded native list fragment package rows for partial list item fragments, list-fragment insertion into selected text, paragraph fragments inside list items, and paragraph fragments at list end.
../lexical/packages/lexical-playground/__tests__/e2e/Extensions.spec.mjsalready-applied.tmp/slate-v2/playwright/integration/examples/plaintext.test.tsexecCommand and synthetic ClipboardEvent rows applied; keep Firefox skip honest.
../lexical/packages/lexical-playground/__tests__/unit/ImageHTML.test.tsapplied.tmp/slate-v2/playwright/integration/examples/paste-html.test.ts, .tmp/slate-v2/site/examples/ts/paste-html-import.ts, stress image rowsSource-read complete. Added browser proof for Lexical image HTML export shapes with no caption and with plain-text figcaption. The paste-html importer now unwraps paragraph wrappers that only contain block elements, so <p></p> imports as a block image instead of nesting a block void under a paragraph. Caption text imports as a following paragraph. Solution note: docs/solutions/logic-errors/2026-05-09-block-only-html-paragraphs-must-not-wrap-block-voids.md. Exact Lexical alt, height, width, serializer API, caption editor, native clipboard transport, raw mobile, collaboration, table-model, and export claims stay out.
../lexical/packages/lexical-rich-text/src/__tests__/unit/LexicalTabNode.test.tscoveredmark/text insertion ownersSource-read complete. Lexical INSERT_TAB_COMMAND mark inheritance is rich-text command policy; generic Slate keeps literal tab insertion as text, with mark-preservation covered by existing mark/text insertion behavior.
../lexical/packages/lexical/src/__tests__/unit/HTMLCopyAndPaste.test.tsapplied for accepted block-shape rows; already-applied for mark/iOS rows; plate-owned/reject for checklist rows.tmp/slate-v2/playwright/integration/examples/paste-html.test.ts, .tmp/slate-v2/site/examples/ts/paste-html-import.ts, Plate checklist/list-plugin ownerSource-read complete. Added browser proof for core HTML block shapes: plain DOM text, malformed paragraph pair, single div, nested spans/divs, nested span in div, and nested div in span. The paste-html importer now treats generic div as a block-boundary fragment while preserving list-item boundary handling. Existing proof covers strong paste mark inheritance and the iOS prediction plain-text fallback. Google Docs/GitHub/Joplin checklist rows are Plate checklist policy unless a raw HTML invariant is split out.
../lexical/packages/lexical/src/nodes/__tests__/unit/LexicalTabNode.test.tsxalready-applied for tab/newline paste; reject/defer for the rest.tmp/slate-v2/packages/slate-dom/test/clipboard-boundary.ts, .tmp/slate-v2/playwright/integration/examples/paste-html.test.tsAdded package proof that multiline plain-text fallback preserves literal tabs while splitting blocks, and browser proof that Google Docs Apple-tab-span HTML preserves tab text across the paragraph plus loose-line shape. Lexical TabNode class/schema/serialization/type-guard rows stay out; tab-indent behavior routes to future code/list/input owners.

Clipboard HTML Row-Level Source Drill

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-playground/__tests__/e2e/CopyAndPaste/html/HTMLCopyAndPaste.spec.mjs
  • ../lexical/packages/lexical-playground/__tests__/e2e/CopyAndPaste/html/TextFormatHTMLCopyAndPaste.spec.mjs
  • ../lexical/packages/lexical-playground/__tests__/e2e/CopyAndPaste/html/LinksHTMLCopyAndPaste.spec.mjs
  • ../lexical/packages/lexical-playground/__tests__/e2e/CopyAndPaste/html/ListsHTMLCopyAndPaste.spec.mjs
  • ../lexical/packages/lexical-playground/__tests__/e2e/CopyAndPaste/html/TablesHTMLCopyAndPaste.spec.mjs
  • .tmp/slate-v2/site/examples/ts/paste-html-import.ts
  • .tmp/slate-v2/playwright/integration/examples/paste-html.test.ts

Current Slate paste-html already owns strong, code, Google Docs font-size spans, iOS prediction plain-text fallback, Google Sheets table import, and generated clipboard/drop gauntlets. The residuals below are the only accepted clipboard HTML work from these four Lexical files.

Source testDecisionSlate ownerExpected Slate proof
HTMLCopyAndPaste: Copy + paste multi line html with extra newlinesalready-appliedpaste-html browser owner and importerBrowser row now proves four pasted paragraphs, strips raw newline noise from normal HTML text, drops whitespace-only inter-block text, removes the empty paste target, and preserves inline <b> / <i> formatting in the final paragraph.
HTMLCopyAndPaste: Copy + paste a code block with BRalready-applied for code-source import; defer for source token styling/language UIpaste-html browser owner and importerThe source-code HTML corpus now includes a <code data-language> element with `
` line breaks and imports it as one code block. Token class styling, gutters, and language UI stay out of this paste parser row.
HTMLCopyAndPaste: paragraph between horizontal rulesdeferfuture HR/block-void plus selection ownerpaste-html has no accepted HR element owner. Inserting a paragraph between two decorator/void HRs needs explicit HR and selection policy before copying.
HTMLCopyAndPaste: paste top-level HR in the middle of a paragraphdeferfuture HR/block-void plus block-fragment ownerSplitting an existing paragraph around a pasted HR is portable, but only after Slate accepts an HR/block-void import and block-fragment insertion owner.
TextFormat: Copy + paste html with BIU formattingalready-applied.tmp/slate-v2/playwright/integration/examples/paste-html.test.ts, .tmp/slate-v2/site/examples/ts/paste-html-import.tsBrowser row now proves Google Docs-style spans produce bold, italic, underline, and combined bold+italic+underline while preserving font-size: 11pt.
TextFormat: Copy + paste html with highlight formattingreject for <mark> highlight; already-applied for guarded semantic <b> handlingpaste-html example onlyThe example has no highlight leaf/render contract, so copying Lexical highlight markup would import app policy. Standard <b> now maps to bold unless inline font-weight explicitly marks the wrapper as non-bold.
Links: Copy + paste an anchor elementalready-appliedpaste-html browser ownerBrowser row now proves <a href="https://facebook.com">Facebook!</a> imports one safe link with href https://facebook.com/ and text. Lexical toolbar unlink/relink assertions stay rejected.
Links: Copy + paste in front of or after a linkalready-applied.tmp/slate-v2/playwright/integration/examples/inlines.test.tsBrowser row now proves plain-text and rich-HTML paste at inline-link boundaries stay outside the link instead of expanding it.
Links: Copy + paste link by selecting its (partial) contentalready-applied.tmp/slate-v2/packages/slate/test/clipboard-contract.tsPackage row now proves a selected partial link fragment preserves link attributes when inserted into another text position.
Links: Copy + paste empty link #3193already-appliedpaste-html browser ownerBrowser row now uses a minimized noisy social-HTML fixture: block before list, two list items, and a safe link in the first item. Emoji/image/theme noise stays rejected.
Links: Paste a link into textrejectnonePlain-text URL autolinking is plugin/product behavior, not raw HTML paste.
Links: Paste text into a linkreject for generic core; defer for app link policyfuture link-plugin ownerGeneric Slate should not special-case link so pasted text inside an inline link loses link affinity. A link plugin can choose that policy later.
Links: Paste formatted text into a linkreject for generic core; defer for app link policyfuture link-plugin ownerMarks are portable, but "do not inherit surrounding link" is link-plugin policy unless the public link example accepts it explicitly.
Links: Paste a link into a linkdeferfuture link-plugin ownerNested link prevention is a link-plugin normalization decision, not a generic inline-fragment law.
Links: Paste multiple blocks into a linkdeferfuture link-plugin/block-fragment ownerMulti-block paste through an inline link needs an accepted link/block-fragment policy before adding browser proof.
Lists: Copy + paste a list elementalready-appliedpaste-html browser ownerBrowser row now proves basic <ul><li>Hello</li><li>world!</li></ul> import. Lexical toolbar indent/outdent assertions stay rejected.
Lists: nested ul variantsalready-appliedpaste-html browser owner, list fragment contract owner if model behavior differsBrowser corpus now covers a nested list item, a directly nested ul, and li text plus child ul. Toolbar indent/outdent assertions stay rejected.
Lists: Copy + paste a checklistrejectnoneLexical private __lexicallisttype="check" and checklist ARIA/theme output are app/list-plugin policy, not generic HTML paste.
Lists: Paste top level element in the middle of listdeferfuture HR/void plus list split ownerPortable shape, but paste-html has no HR element owner and the test is about splitting an existing list around a decorator. Not this clipboard parser slice.
Lists: Copy + paste a nested divs in a listalready-appliedpaste-html browser ownerBrowser row now proves nested <div> content inside list items preserves paragraph boundaries without unwrapping the list item.
Tables: Copy + paste (Table - Google Docs)already-appliedpaste-html browser ownerBrowser row now proves Google Docs table HTML imports rows/cells, multi-paragraph cell content, and 11pt text. Column widths stay unclaimed.
Tables: Copy + paste (Table - Google Docs with custom widths)deferfuture table layout/model ownerWidth preservation needs table column/layout policy. Current paste-html intentionally ignores COL and COLGROUP.
Tables: Copy + paste (Table - Quip)already-appliedpaste-html browser ownerBrowser row now proves Quip table HTML imports rows/cells and preserves `b
b` as newline text inside the second cell. Width claims stay out.
Tables: Copy + paste (Table - Google Sheets)covered.tmp/slate-v2/playwright/integration/examples/paste-html.test.tsCurrent browser row imports Google Sheets table cells and style marks.
Tables: Copy + paste - Merge Gridsdeferfuture table selection/model ownerMulti-cell replacement in an existing table is table-model behavior, not generic HTML paste.
Tables: Copy + paste nested block and inline html in a tabledeferfuture table-cell block-normalization ownerValuable, but it needs an accepted table-cell block-normalization policy before adding proof.
Tables: merged cells, unequal rows, and empty rowdeferfuture table model/parser ownerRowspan/colspan grid filling and empty-row synthesis are table model decisions. Do not hide them under the paste-html example.

Selected clipboard HTML source rows for this phase are applied. Inline-link boundary copy/paste rows are now applied for the raw Slate owners. Paste-inside link splitting stays deferred to an explicit link-plugin policy; table custom widths, merge grids, rowspan/colspan, empty rows, and table-cell block normalization stay deferred to accepted table/layout owners.

Lexical Core HTMLCopyAndPaste Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical/src/__tests__/unit/HTMLCopyAndPaste.test.ts
  • .tmp/slate-v2/playwright/integration/examples/paste-html.test.ts
  • .tmp/slate-v2/site/examples/ts/paste-html-import.ts
Source testDecisionSlate ownerExpected Slate proof
plain DOM text nodealready-appliedpaste-html browser ownerBrowser proof now covers HTML-only text import producing one paragraph.
a paragraph elementalready-appliedpaste-html browser ownerBrowser proof now covers malformed <p>Hello!<p> producing the visible paragraph plus the parser-created empty paragraph.
a single divappliedpaste-html browser owner and importerBrowser proof failed red as one 123456 paragraph, then passed after generic div import became a block-boundary fragment.
multiple nested spans and divsappliedpaste-html browser owner and importerBrowser proof now preserves the nested div boundary as a b c d e then f g h.
nested span in a divappliedpaste-html browser owner and importerBrowser proof now splits 123 and 456 instead of flattening them.
nested div in a spanappliedpaste-html browser owner and importerBrowser proof now splits 123 and 456 even when the block boundary is nested under an inline wrapper.
Google Docs, GitHub, and Joplin checklist rowsdefer/rejectfuture checklist/list-plugin ownerThe rows depend on checklist schema, private attributes, ARIA/theme output, and checkbox normalization. Current paste-html list owner only accepts generic list import.
pasting inheritancealready-appliedpaste-html browser ownerExisting rich HTML paste proof now asserts typed text after <strong>Hello Bold</strong> stays inside <strong>.
iOS prediction plain-text fallbackalready-appliedpaste-html browser owner and DOM clipboard runtimeExisting browser proof covers identical text/html and text/plain payloads inserting plain text into a formatted selection with the selection preserved.

Lexical Playground Native CopyAndPaste Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-playground/__tests__/e2e/CopyAndPaste/lexical/CopyAndPaste.spec.mjs
  • .tmp/slate-v2/packages/slate-dom/test/clipboard-boundary.ts
  • .tmp/slate-v2/packages/slate/test/clipboard-contract.ts
  • .tmp/slate-v2/packages/slate/src/transforms-text/insert-fragment.ts
  • .tmp/slate-v2/playwright/integration/examples/paste-html.test.ts
  • .tmp/slate-v2/playwright/integration/examples/inlines.test.ts
  • .tmp/slate-v2/playwright/integration/examples/richtext.test.ts
  • .tmp/slate-v2/playwright/integration/examples/highlighted-text.test.ts
  • .tmp/slate-v2/playwright/stress/generated-editing.test.ts
Source testDecisionSlate ownerExpected Slate proof
Basic copy + pastecoveredDOM clipboard boundary and generated clipboard/stress rowsCurrent rows cover model-backed fragment write/read, multi-block insertion into a text block, selection placement, and native clipboard stress. Exact Lexical rich/plain DOM theme output stays out.
Copy and paste headingdefer/reject exact source wrapperfuture block-format paste policy, if acceptedCurrent Slate rule is target-owned for single text-block fragment replacement, including empty targets. Preserving a copied heading wrapper into an empty paragraph would contradict the documented target-block policy unless a new block-format paste owner accepts it.
Copy and paste between sectionscovered/defer product spansclipboard-contract and inline-token future ownersFull-document replace and mixed inline fragment extraction/insertion are covered. Lexical hashtag classes/theme output are product rows and route to future inline-token owners if needed.
Copy and paste an inline element into a leaf nodealready-appliedclipboard-contract and inlines browser ownerPackage proof preserves partial inline link fragments; browser rows cover paste at inline-link boundaries without expanding the link.
Copy + paste multi-line plain text into rich text produces separate paragraphscovered/defer exact heading tail policyslate-dom plain-text fallback; future richtext block-split policy if acceptedCurrent package proof splits multiline plain text at a collapsed rich-text selection. Lexical's exact "tail line becomes paragraph after heading" is app block-format policy; generic Slate currently preserves the target block type for split lines.
Pasting a decorator node on a blank line inserts before the linedefer/rejectfuture decorator/block-void paste ownerYouTube embed decorator, block cursor DOM, and product shell are not raw Slate behavior. Block void/image paste rows are covered elsewhere.
Copy and paste paragraph into quoteapplied.tmp/slate-v2/packages/slate-dom/test/clipboard-boundary.ts, .tmp/slate-v2/packages/slate/src/transforms-text/insert-fragment.tsAdded DOM clipboard proof that two copied paragraphs pasted into an empty block quote produce a block quote with the first paragraph text plus a following paragraph tail. First focused proof failed red because Slate replaced the quote with paragraphs.
Google Docs/MS Word font-size rowsalready-appliedpaste-html browser owner and importerPaste-html browser rows cover Google Docs font-size spans and pt/px normalization.
Cut then copy empty selection preserves clipboardalready-appliedhighlighted-text browser ownerBrowser proof preserves clipboard text when copy or cut runs on a collapsed text selection and proves the document is unchanged.

LexicalHistory Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-history/src/__tests__/unit/LexicalHistory.test.tsx
  • .tmp/slate-v2/packages/slate-history/test/history-contract.ts
  • .tmp/slate-v2/packages/slate-history/test/integrity-contract.ts
  • .tmp/slate-v2/packages/slate/test/transaction-contract.ts
  • .tmp/slate-v2/packages/slate/test/collab-history-runtime-contract.ts
Source testDecisionSlate ownerExpected Slate proof
LexicalHistory after clearingreject for command event API; covered for empty-stack statehistory contractSlate exposes history stacks and undo/redo methods, not CAN_UNDO/CAN_REDO or CLEAR_HISTORY command notifications. Empty stacks and stack identity are already covered by current history setup/undo rows.
LexicalHistory.Redo after Quote Nodealready-applied.tmp/slate-v2/packages/slate-history/test/history-contract.tsAdded package proof that a selected block property change is undoable and redoable, preserving tree and selection-visible state. Lexical quote-node class and JSON shape stay out.
LexicalHistory in sequence: change, undo, redo, undo, changealready-applied.tmp/slate-v2/packages/slate-history/test/history-contract.tsAdded package proof that a new edit after undo clears redo history and redo becomes a no-op. Lexical CAN_UNDO/CAN_REDO command payloads stay out.
undoStack selection points to the same editorrejectnoneLexical shared history across parent/nested editors and NodeSelection class ownership are not generic Slate v2 history behavior.
Changes to TextNode leaf are detected properly #6409already-applied.tmp/slate-v2/packages/slate-history/test/history-contract.tsAdded package proof that empty/no-op updates are not saved, while node property commits enter history and undo back to the original document.
SharedHistoryExtension can create a parent editorreject/deferfuture nested-editor/shared-history owner, if acceptedLexical extension dependency injection, decorator child editor DOM mounting, and shared history state across nested editors are framework/product integration details, not a raw Slate history contract.

LexicalHtml Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-html/src/__tests__/unit/LexicalHtml.test.ts
  • .tmp/slate-v2/packages/slate-dom/test/clipboard-boundary.ts
  • .tmp/slate-v2/packages/slate/test/clipboard-contract.ts
  • .tmp/slate-v2/playwright/integration/examples/paste-html.test.ts
  • .tmp/slate-v2/site/examples/ts/paste-html-import.ts
Source testDecisionSlate ownerExpected Slate proof
[Lexical -> HTML]: Empty editor statereject/deferfuture generic HTML serializer owner, if acceptedLexical asserts $generateHtmlFromNodes emits `<p>
</p>` for an empty editor. Current Slate v2 has clipboard/DOM payload owners, not a standalone full-editor HTML serializer contract. Do not hide serializer API design under clipboard tests. | | `[Lexical -> HTML]: Use provided selection` | `covered` for selected-fragment export; `reject` Lexical serializer API shape | `.tmp/slate-v2/packages/slate-dom/test/clipboard-boundary.ts` | Existing package rows prove `writeSelection` emits Slate fragment and HTML payloads for the current selection and can paste them into a target selection. Lexical's direct `$generateHtmlFromNodes(editor, selection)` API shape stays out. | | `[Lexical -> HTML]: Default selection (undefined) should serialize entire editor state` | `reject/defer` | future generic HTML serializer owner, if accepted | Whole-editor HTML string export is not currently a Slate v2 public owner. Raw document JSON portability is covered separately by the public state API; it is not this HTML serializer row. | | `If alignment is set on the paragraph, don't overwrite from parent empty format` | `already-applied` | `.tmp/slate-v2/playwright/integration/examples/paste-html.test.ts`, `.tmp/slate-v2/site/examples/ts/paste-html-import.ts` | Current browser row proves legacy `align="right"` imports to paragraph `text-align: right` and invalid alignment is ignored. | | `If alignment is set on the paragraph, it should take precedence over its parent block alignment` | `already-applied` | `.tmp/slate-v2/playwright/integration/examples/paste-html.test.ts`, `.tmp/slate-v2/site/examples/ts/paste-html-import.ts` | Current browser row proves CSS `style="text-align: center"` wins over legacy parent/right alignment for paragraph import. | | `It should output correctly nodes whose export is DocumentFragment` | `reject` | none | Lexical custom node `exportDOM` returning `DocumentFragment` is a class-extension serializer API. Slate v2 should only add this if a generic HTML serializer owner exists. |

LexicalList Utils Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-list/src/__tests__/unit/utils.test.ts
  • ../lexical/packages/lexical-list/src/utils.ts
  • .tmp/slate-v2/packages/slate/test/query-contract.ts
  • .tmp/slate-v2/packages/slate/test/snapshot-contract.ts
  • .tmp/slate-v2/packages/slate/test/clipboard-contract.ts
  • .tmp/slate-v2/packages/slate/test/delete-contract.ts
  • .tmp/slate-v2/playwright/integration/examples/paste-html.test.ts
  • .tmp/slate-v2/playwright/integration/examples/markdown-shortcuts.test.ts
  • .tmp/slate-v2/playwright/integration/examples/check-lists.test.ts
Source testDecisionSlate ownerExpected Slate proof
getListDepth should return the 1-based depth of a list with one levelsalready-applied.tmp/slate-v2/packages/slate/test/query-contract.tsAdded package proof that Path.levels plus public Node lookup exposes list depth for a top-level logical list, even when the list is inside a non-root container.
getListDepth should return the 1-based depth of a list with two levelsalready-applied.tmp/slate-v2/packages/slate/test/query-contract.tsSame proof covers a nested list as the second list ancestor in the path chain.
getListDepth should return the 1-based depth of a list with five levelsalready-applied for the mechanism; no five-level duplicate.tmp/slate-v2/packages/slate/test/query-contract.tsSlate does not need a depth-count copy of every Lexical fixture depth. The new proof locks the public path mechanism for arbitrary nested list levels.
getTopListNode direct root / non-root / deeply nested rowsalready-applied.tmp/slate-v2/packages/slate/test/query-contract.tsAdded package proof that list ancestors resolve to the first logical list path even when the list is not a root child and when the inspected item is deeply nested.
isLastItemInList nested and non-nested true/false rowsalready-applied.tmp/slate-v2/packages/slate/test/query-contract.tsAdded package proof that terminal and non-terminal list-item paths are observable through Node.has(editor, Path.next(path)), including a nested item whose ancestor still has a following sibling.

Lexical Regression #231 Empty Text Nodes Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-playground/__tests__/regression/231-empty-text-nodes.spec.mjs
  • .tmp/slate-v2/packages/slate/test/delete-contract.ts
  • .tmp/slate-v2/packages/slate/test/normalization-contract.ts
  • .tmp/slate-v2/packages/slate/test/leaf-lifecycle-contract.ts
  • .tmp/slate-v2/packages/slate-react/test/rendered-dom-shape-contract.tsx
  • docs/solutions/logic-errors/2026-04-25-slate-v2-destructive-delete-must-clean-empty-leaves-before-render.md
Source testDecisionSlate ownerExpected Slate proof
Does not generate segment error when editing empty text nodesalready-applied for token-like delete lifecycle; reject for hashtag plugin/CSS/collab harness.tmp/slate-v2/packages/slate/test/delete-contract.ts, existing normalization/leaf/render ownersPackage proof now deletes backward through { token: true, text: '#foo' } after leading a and lands on a canonical empty paragraph with selection at [0, 0] offset 0. Existing owners cover empty block anchoring, invalid empty marked leaf cleanup, and rendered empty-block shape.

Lexical Regression #3433 Merge Markdown Lists Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-playground/__tests__/regression/3433-merge-markdown-lists.spec.mjs
  • .tmp/slate-v2/playwright/integration/examples/markdown-shortcuts.test.ts
  • .tmp/slate-v2/site/examples/ts/markdown-shortcuts.tsx
  • .tmp/slate-v2/packages/slate/test/transforms/insertFragment/of-lists/merge-lists.tsx
  • .tmp/slate-v2/packages/slate/test/snapshot-contract.ts
  • .tmp/slate-v2/packages/slate/test/transforms-contract.ts
Source testDecisionSlate ownerExpected Slate proof
can merge markdown lists created immediately before existing listsalready-applied.tmp/slate-v2/playwright/integration/examples/markdown-shortcuts.test.ts, .tmp/slate-v2/site/examples/ts/markdown-shortcuts.tsxBrowser proof now creates an existing list item one, converts the immediately preceding block with - two, and asserts one ul with two then one. The example merges adjacent bulleted-list wrappers after wrapping the current block as a list item. Lexical Playground HTML/CSS, plain-text skip, collaboration harness, and issue claim stay out.

LexicalHeadingNode Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-rich-text/src/__tests__/unit/LexicalHeadingNode.test.ts
  • .tmp/slate-v2/playwright/integration/examples/richtext.test.ts
  • .tmp/slate-v2/site/examples/ts/richtext.tsx
  • .tmp/slate-v2/packages/slate/test/snapshot-contract.ts
  • .tmp/slate-v2/packages/slate/test/transforms-contract.ts
  • docs/solutions/logic-errors/2026-04-12-structured-enter-and-backspace-need-editor-owned-keydown-paths.md
  • docs/solutions/logic-errors/2026-04-07-slate-v2-split-node-should-keep-left-branch-id-and-rebase-inward.md
Source testDecisionSlate ownerExpected Slate proof
HeadingNode.constructor, HeadingNode.createDOM, HeadingNode.updateDOM, HeadingNode.setTag, $createHeadingNode, $isHeadingNoderejectnoneLexical class lifecycle, tag setter helpers, node keys, and theme class output are not portable Slate behavior. Slate owns block type plus rendering through examples and element renderers.
HeadingNode.insertNewAfter() in the middle of a headingalready-applied.tmp/slate-v2/playwright/integration/examples/richtext.test.ts, core split ownersBrowser proof now splits hello world at offset 5 into two h1 elements. Generic Slate split behavior owns the model row; the richtext browser row proves the example transport.
HeadingNode.insertNewAfter() at heading endalready-applied.tmp/slate-v2/playwright/integration/examples/richtext.test.ts, .tmp/slate-v2/site/examples/ts/richtext.tsxBrowser proof now shows Enter at the end of a heading creates a paragraph after the heading instead of another heading.
HeadingNode.insertNewAfter() in an empty headingalready-applied.tmp/slate-v2/playwright/integration/examples/richtext.test.ts, .tmp/slate-v2/site/examples/ts/richtext.tsxBrowser proof now shows Enter in an empty heading leaves the heading and creates a paragraph after it.

LexicalQuoteNode Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-rich-text/src/__tests__/unit/LexicalQuoteNode.test.ts
  • .tmp/slate-v2/playwright/integration/examples/richtext.test.ts
  • .tmp/slate-v2/site/examples/ts/richtext.tsx
  • .tmp/slate-v2/packages/slate/test/snapshot-contract.ts
  • .tmp/slate-v2/packages/slate/test/transforms-contract.ts
  • docs/solutions/logic-errors/2026-04-12-structured-enter-and-backspace-need-editor-owned-keydown-paths.md
Source testDecisionSlate ownerExpected Slate proof
QuoteNode.constructor, QuoteNode.createDOM, QuoteNode.updateDOM, $createQuoteNoderejectnoneLexical class lifecycle, node keys, and theme class output are not portable Slate behavior. Slate owns blockquote rendering through the richtext example.
QuoteNode.insertNewAfter() from an empty quotealready-applied.tmp/slate-v2/playwright/integration/examples/richtext.test.ts, .tmp/slate-v2/site/examples/ts/richtext.tsxBrowser proof now shows Enter in an empty blockquote keeps one blockquote and creates a paragraph after it. The richtext example shares one exit-on-Enter policy for headings and blockquote.

Lexical Selection $sliceSelectedTextNodeContent Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-selection/src/__tests__/unit/$sliceSelectedTextNodeContent.test.ts
  • .tmp/slate-v2/packages/slate/test/clipboard-contract.ts
  • .tmp/slate-v2/packages/slate/src/interfaces/node.ts
  • .tmp/slate-v2/packages/slate/src/core/public-state.ts
  • docs/solutions/logic-errors/2026-04-03-slate-v2-clipboard-boundary-proof-must-split-fragment-semantics-and-dom-transport.md
  • docs/solutions/logic-errors/2026-04-09-slate-node-fragment-must-clone-and-prune-in-root-relative-space.md
Source testDecisionSlate ownerExpected Slate proof
full selection returns both original Lexical text nodescovered for selected text content; reject object identity.tmp/slate-v2/packages/slate/test/clipboard-contract.tsSlate already exposes selected fragments through state.fragment.get(). It does not promise Lexical node object identity.
partial first/last text selection clones only sliced textalready-applied.tmp/slate-v2/packages/slate/test/clipboard-contract.tsPackage proof now selects 01234 + bold 56789 from offset 1 to 4 in the second leaf and asserts fragment text 1234 plus bold 5678.
sliced clone has no side effects on the source text nodealready-applied.tmp/slate-v2/packages/slate/test/clipboard-contract.tsThe same package proof mutates the returned fragment leaves and asserts the editor snapshot still contains the original unmarked and bold text leaves.

LexicalListItemNode Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-list/src/__tests__/unit/LexicalListItemNode.test.ts
  • .tmp/slate-v2/packages/slate/test/snapshot-contract.ts
  • .tmp/slate-v2/packages/slate/test/clipboard-contract.ts
  • .tmp/slate-v2/packages/slate/test/delete-contract.ts
  • docs/solutions/logic-errors/2026-04-05-list-unit-fragment-proofs-should-treat-list-item-fragments-as-sibling-units-and-assert-real-paste-landings.md
  • docs/solutions/best-practices/2026-05-09-lexical-list-utils-harvest-rows-need-path-ancestry-contracts.md
Source testDecisionSlate ownerExpected Slate proof
constructor/createDOM/updateDOM/$create/$is/exportJSON/value/theme rowsrejectnoneLexical node lifecycle, DOM class/value output, node keys, and JSON schema are not portable Slate behavior.
ListItemNode.insertNewAfter(): non-empty list itemsalready-applied.tmp/slate-v2/packages/slate/test/snapshot-contract.tsPackage proof now shows insertBreak inside onetwo splits the list item into one and two under the same bulleted-list, with selection at the start of the new item.
replace first/last/middle/only list item with paragraphdeferfuture list-exit/list-normalization ownerUseful list behavior, but it is a list-plugin policy in this checkout rather than a generic core transform law. Do not hide first/middle/last list splitting under a broad node replacement test.
remove list item with non-nested, nested, and deeply nested siblingsdeferfuture list-normalization ownerThese rows encode Lexical's nested-list repair strategy. Slate needs an explicit list model owner before porting the merge/promote matrix.
ListItemNode.setIndent(), fractional indent, marker style inheritancedefer/rejectfuture list-indent/plugin ownerIndent/outdent and marker style inheritance are plugin-level list behavior, not raw Slate core. Fractional indent coercion is Lexical API policy.
splitting an ordered list with reset or preserved numberingdeferfuture ordered-list restart ownerOrdered-list restart preservation is a public list policy decision. Keep it out until the list owner accepts restart metadata semantics.

LexicalListNode Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-list/src/__tests__/unit/LexicalListNode.test.ts
  • .tmp/slate-v2/packages/slate/test/snapshot-contract.ts
  • .tmp/slate-v2/packages/slate/test/clipboard-contract.ts
  • .tmp/slate-v2/packages/slate/test/query-contract.ts
  • docs/solutions/logic-errors/2026-04-05-wrapper-unit-insert-seams-should-generalize-from-bulleted-list-to-compatible-list-containers-before-adding-new-geometry.md
  • docs/solutions/logic-errors/2026-03-30-markdown-ordered-list-restarts-must-emit-listrestartpolite.md
Source testDecisionSlate ownerExpected Slate proof
constructor/getTag/createDOM/updateDOM/$create/$is/subclass/config rowsrejectnoneLexical node lifecycle, DOM depth classes, node keys, and subclass transform wiring are not portable Slate behavior.
ListNode.append()/splice() wraps list items, lists, paragraphs, inline nodes, and text nodescovered/defercurrent list formatting and fragment owners; future list-normalization owner for exact coercionSlate already proves list-item wrapper units and list formatting flows. Lexical's append/splice helper coercion matrix needs an explicit list-normalization owner before copying.
bullet vs number list wrapper creationalready-applied.tmp/slate-v2/packages/slate/test/snapshot-contract.tsExisting proof covers bulleted-list formatting; new package proof covers numbered-list formatting by wrapping selected top-level blocks as list-item children.
checklist role cleanup and nested checklist attribute clearingdeferfuture checklist/list-plugin ownerChecklist role, ARIA, and checked metadata are plugin/rendering policy, not raw Slate core.
list item value transform and ordered-list start/restart behaviordeferfuture ordered-list restart ownerSlate needs explicit restart metadata semantics before porting Lexical's value/start transform rows.

lexical-list formatList Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-list/src/__tests__/unit/formatList.test.ts
  • .tmp/slate-v2/packages/slate/test/snapshot-contract.ts
  • .tmp/slate-v2/packages/slate/test/delete-contract.ts
  • .tmp/slate-v2/packages/slate/test/clipboard-contract.ts
  • .tmp/slate-v2/packages/slate/test/query-contract.ts
  • .tmp/slate-v2/playwright/integration/examples/markdown-shortcuts.test.ts
  • .tmp/slate-v2/playwright/integration/examples/richtext.test.ts
  • .tmp/slate-v2/site/examples/ts/richtext.tsx
  • .tmp/slate-v2/site/examples/ts/markdown-shortcuts.tsx
Source testDecisionSlate ownerExpected Slate proof
$insertList: empty root selection and existing root childcovered/already-applied.tmp/slate-v2/packages/slate/test/snapshot-contract.ts, richtext/markdown list browser ownersSlate already proves selected top-level blocks can be converted to list-item children and wrapped in bulleted-list or numbered-list; browser examples prove toolbar/markdown list creation paths.
$insertList: empty shadow root selection in table celldeferfuture table-cell list/model ownerLexical shadow-root table behavior depends on table model policy. Do not hide it under generic root list formatting.
$insertList: formatting empty list items from bullet to numberdeferfuture list-normalization and ordered-list restart ownerConverting empty nested list items and preserving/recomputing list numbering is list-plugin/model policy, not a generic Slate core transform law in this checkout.
$insertList: element-anchored selection after paragraph plus linebreak conversiondefer/reject Lexical shapefuture rich linebreak/list selection owner if acceptedLexical's LineBreakNode and element selection shape do not map directly to Slate's text leaf ranges. Reopen only if Slate accepts a linebreak/list selection policy beyond existing list formatting rows.
$handleListInsertParagraph: empty or whitespace-only final list item exits listdeferfuture list-exit/list-normalization ownerUseful editor behavior, but it is a list-plugin policy here. Current raw Slate proof only covers non-empty insertBreak list-item split and browser markdown continuation.
$handleListInsertParagraph: non-whitespace list item extends listalready-applied.tmp/slate-v2/packages/slate/test/snapshot-contract.ts, .tmp/slate-v2/playwright/integration/examples/markdown-shortcuts.test.tsPackage proof covers insertBreak inside non-empty onetwo splitting to two list-item siblings; markdown browser proof covers native desktop list continuation text.
$handleListInsertParagraph: decorator node extends listdeferfuture decorator/void list-plugin ownerLexical decorator nodes are product/rendering policy. Raw Slate needs an accepted void/decorator-in-list owner before copying this row.
$handleListInsertParagraph: empty middle item splits surrounding listdeferfuture list-exit/list-normalization ownerSplitting one list into previous-list, paragraph, next-list is a plugin/model decision. Keep it explicit instead of burying it in generic insertBreak.
$handleIndent and $handleOutdent preserving extended list subclassesdefer/reject subclass APIfuture list-indent/plugin ownerSlate already has a basic list outdent transform proof; Lexical helper APIs and subclass preservation are not portable raw Slate behavior.

lexical-list registerListStrictIndentTransform Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-list/src/__tests__/unit/registerListStrictIndentTransform.test.ts
  • .tmp/slate-v2/playwright/integration/examples/paste-html.test.ts
  • .tmp/slate-v2/site/examples/ts/paste-html-import.ts
  • docs/solutions/best-practices/2026-05-09-lexical-tab-node-harvest-rows-need-clipboard-browser-proof-boundaries.md
Source testDecisionSlate ownerExpected Slate proof
applyStrictListIndentation malformed nested ul import casescovered/deferpaste-html nested-list browser corpus; future list-normalization owner for exact rewriteCurrent Slate browser coverage already pastes compact nested-list variants, including a direct nested ul child and li text plus child ul, without flattening visible list content. The Lexical row also asserts exact normalized HTML serialization with value attributes and strict nested wrapper placement; Slate does not currently expose that generic HTML serializer/list-normalization contract.
$generateHtmlFromNodes expected nested-list outputdeferfuture generic HTML serializer owner, if acceptedThis is Lexical serializer output shape, not a raw Slate invariant. Reopen only if Slate accepts a full-editor HTML serializer contract.
registerListStrictIndentTransform(editor) setuprejectnoneLexical transform registration and command wiring are framework internals.

LexicalMarkdown Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-markdown/src/__tests__/unit/LexicalMarkdown.test.ts
  • .tmp/slate-v2/playwright/integration/examples/markdown-shortcuts.test.ts
  • .tmp/slate-v2/site/examples/ts/markdown-shortcuts.tsx
  • .tmp/slate-v2/site/examples/ts/markdown-preview.tsx
Source test familyDecisionSlate ownerExpected Slate proof
heading, blockquote, and unordered-list markdown shortcut creationcovered/already-applied.tmp/slate-v2/playwright/integration/examples/markdown-shortcuts.test.ts, .tmp/slate-v2/site/examples/ts/markdown-shortcuts.tsxBrowser rows already prove blockquote presence, list item creation/continuation, adjacent markdown-created list merge, and h1 shortcut creation.
full markdown import/export matrix for headings, quotes, lists, ordered starts, marks, links, code, escapes, whitespace, hard breaks, nested code fences, and multiline paragraphsdeferfuture markdown serialization ownerSlate v2 currently has no markdown parser/serializer package. Do not add model tests that pretend a public markdown import/export contract exists.
custom transformers, MDX HTML transformers, replace returning false, and transformer orderingreject/deferfuture markdown extension API owner, if acceptedThese rows test Lexical transformer API shape and extension policy. Reopen only if Slate v2 accepts a comparable markdown transformer API.
list marker memory and checklist marker behaviordefer/rejectfuture list/checklist markdown ownerMarker preservation, checklist syntax, and list metadata are plugin/serializer policy. They are not raw Slate behavior in this checkout.
Enter-key code fence shortcut creating a code blockdeferfuture code-block markdown shortcut/browser ownerUseful browser behavior, but current Slate markdown-shortcuts example owns quote/list/headings only. Do not smuggle code-block shortcut policy into core or unrelated examples.
normalizeMarkdown line-merge, table, HTML-like tag, whitespace, and MDX handlingdeferfuture markdown normalizer/parser ownerPure markdown preprocessing utility behavior; no current Slate v2 owner exists.
import should leave no selectionreject/deferfuture markdown import ownerA headless markdown import helper can decide selection semantics. Current Slate v2 has no such import API.

MarkdownTransformers Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-markdown/src/__tests__/unit/MarkdownTransformers.test.ts
  • .tmp/slate-v2/playwright/integration/examples/inlines.test.ts
  • .tmp/slate-v2/packages/slate/test/clipboard-contract.ts
  • docs/solutions/best-practices/2026-05-09-inline-link-harvest-rows-need-link-policy-boundaries.md
  • docs/solutions/logic-errors/2026-04-17-markdown-link-automd-must-move-selection-after-inserted-link.md
  • docs/solutions/logic-errors/2026-04-11-link-paste-autolink-must-stay-literal-inside-markdown-source-entry.md
Source testDecisionSlate ownerExpected Slate proof
text before a markdown link is preserveddeferfuture markdown-link transformer ownerThis is markdown shortcut parsing, not raw link model behavior. Existing paste/clipboard link rows prove HTML/fragment link boundaries, not markdown automd.
formatted text before a markdown link is preserveddeferfuture markdown-link transformer ownerSame owner as above. Mark preservation before markdown link insertion belongs in a markdown-link plugin/serializer once accepted.
link parser is not too greedy after a preceding unprocessed matchdeferfuture markdown-link transformer ownerValuable parser regression, but Slate v2 has no markdown link transformer API in this checkout.
markdown link should not be created inside another linkdefer/reject generic corefuture markdown-link plugin owner; existing inline-link boundary owners for raw behaviorGeneric Slate should not special-case markdown syntax inside a custom inline link. A markdown-link plugin can reject nested link transforms later; current raw inline-link paste/copy boundaries remain covered separately.

ClearFormatting Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-playground/__tests__/e2e/ClearFormatting.spec.mjs
  • .tmp/slate-v2/playwright/integration/examples/richtext.test.ts
  • .tmp/slate-v2/site/examples/ts/richtext.tsx
  • .tmp/slate-v2/packages/slate/src/editor/remove-mark.ts
  • .tmp/slate-v2/packages/slate/test/snapshot-contract.ts
  • .tmp/slate-v2/packages/slate/test/primitive-method-runtime-contract.ts
Source test familyDecisionSlate ownerExpected Slate proof
clear selected BIU/code marksalready-applied.tmp/slate-v2/site/examples/ts/richtext.tsx, .tmp/slate-v2/playwright/integration/examples/richtext.test.tsRichtext now exposes a clear-formatting toolbar command that removes the example's text marks from the current selection. Browser proof locks selected multi-block mark removal without clearing unselected formatted text.
preserve semantic block structure while clearing explicit formattingalready-applied.tmp/slate-v2/site/examples/ts/richtext.tsx, .tmp/slate-v2/playwright/integration/examples/richtext.test.tsBrowser proof clears underline and alignment from selected blockquotes while keeping blockquote elements intact.
clear left/center/right/justify alignmentalready-applied.tmp/slate-v2/site/examples/ts/richtext.tsx, .tmp/slate-v2/playwright/integration/examples/richtext.test.tsClear-formatting command resets the richtext example's align block prop over the selected blocks.
selected text spanning more than one paragraphalready-applied.tmp/slate-v2/playwright/integration/examples/richtext.test.ts, existing mark model contractsBrowser proof selects from the middle of paragraph one through the middle of paragraph two, clears selected marks, and keeps the unselected Foo and qux ranges bold/italic.
preserve default styling of links, hashtags, and mentionsdefer/reject product rowsfuture clear-formatting link/mention plugin owner, if acceptedThe richtext example has no link, hashtag, or mention schema. Existing link/mention rows cover raw inline behavior, not a generic clear-formatting plugin. Do not add link/mention policy to raw Slate core.
clear indent/outdent formattingdeferfuture indent/list/code/block-format ownerThe current richtext example owns alignment but not indent/outdent state. Keep this as a later owner decision.
Lexical additional-style dropdown and theme/DOM class outputrejectnoneProduct shell and theme markup are not portable Slate behavior.

CodeBlock Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-playground/__tests__/e2e/CodeBlock.spec.mjs
  • .tmp/slate-v2/playwright/integration/examples/code-highlighting.test.ts
  • .tmp/slate-v2/site/examples/ts/code-highlighting.tsx
  • .tmp/slate-v2/packages/slate/test/snapshot-contract.ts
Source testDecisionSlate ownerExpected Slate proof
Can create code block with markdowndeferfuture markdown code-fence shortcut ownerCurrent Slate markdown-shortcuts example owns quote/list/heading shortcuts, not fenced code-block creation. Do not hide code-fence parsing under the code-highlighting example.
Can create code block with markdown and wrap existing textdeferfuture markdown code-fence shortcut ownerSame code-fence parser boundary, with selected text wrapping as an additional browser behavior once the owner exists.
Can select multiple paragraphs and convert to code blockcovered/refactor-existing.tmp/slate-v2/packages/slate/test/snapshot-contract.ts, code-highlighting browser ownerGeneric wrap/range model rows already cover multi-block wrapping mechanics. Browser coverage now locks the user-facing selected-paragraph code-block control; broaden only if the code-highlighting example gains a clean multi-paragraph fixture owner.
Can select partial paragraphs and convert to code blockcovered/refactor-existingsnapshot wrap owners, future richer code-highlighting fixturePartial cross-block conversion is a transform/wrap split policy. Current browser proof intentionally locks the control and code-line output without creating a brittle product fixture.
Can select a line within line breaks and convert to code blockdeferfuture line-break/code-block conversion ownerSlate v2 models soft line breaks as text/newline behavior, not Lexical LineBreakNode children. Needs a deliberate code-block conversion policy before adding proof.
Can switch highlighting language in a toolbardefercode-highlighting browser ownerThe example has LanguageSelect, but this slice does not add a shallow select-value assertion. Add a semantic projection row only if the language switch proof checks token output, not just product control wiring.
Can maintain indent when creating new linesdeferfuture code indentation ownerCurrent code-highlighting Enter proof creates a code line in the same block. Auto-indent-on-newline is a distinct editor policy.
Can indent text via tab when selecting the line with Shift+Downalready-applied.tmp/slate-v2/playwright/integration/examples/code-highlighting.test.tsExisting browser proof covers selected code-line indentation with Tab.
Can (un)indent multiple lines at oncealready-applied.tmp/slate-v2/playwright/integration/examples/code-highlighting.test.tsExisting browser proof covers selected multi-line Tab and Shift+Tab.
Can move around lines with option+arrow keysdeferfuture code-line movement ownerSlate v2 code-highlighting does not expose line move commands.
prevents selection and typing outside code block boundariesdeferfuture code-block selection boundary ownerCurrent Slate has general selection/delete boundaries, but no accepted code-block-specific clamp policy.
When pressing CMD/Ctrl + Left/Right...deferfuture visual-caret/navigation ownerNative visual navigation is browser-specific and needs a deliberate code navigation proof owner.
Can create code block with language diff / diff-javascriptdeferfuture markdown code-fence language ownerCode-fence language parsing belongs with markdown code-block shortcuts, not the current Prism example.
Lexical Playground toolbar/theme/output detailsrejectnoneToolbar layout, Shiki/theme DOM, screenshots, and command dispatch are product shell, not portable Slate v2 behavior.

ElementFormat Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-playground/__tests__/e2e/ElementFormat.spec.mjs
  • .tmp/slate-v2/playwright/integration/examples/richtext.test.ts
  • .tmp/slate-v2/site/examples/ts/richtext.tsx
  • .tmp/slate-v2/playwright/integration/examples/inlines.test.ts
  • .tmp/slate-v2/site/examples/ts/inlines.tsx
Source testDecisionSlate ownerExpected Slate proof
Can center align an empty paragraphalready-applied.tmp/slate-v2/playwright/integration/examples/richtext.test.ts, .tmp/slate-v2/site/examples/ts/richtext.tsxBrowser proof creates a fresh empty paragraph, clicks center alignment, asserts CSS text-align: center, and verifies the collapsed selection remains on that empty block. The richtext example explicitly targets the containing block for collapsed alignment.
Can indent/align paragraph when caret is within linkdefer/reject splitfuture link/block-format owner and future indent owner; current inlines and richtext owners remain separateThe source mixes link caret position, indent policy, and alignment. Current Slate has inline-link behavior and richtext block alignment separately, but no combined owner and no indent API. Do not add product indent or link-specific block-format policy to raw richtext.
Lexical dropdown/theme/DOM class shellrejectnoneProduct shell, screenshots, theme classes, and toolbar layout are not portable Slate behavior.

HeadingsBackspaceAtStart Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-playground/__tests__/e2e/Headings/HeadingsBackspaceAtStart.spec.mjs
  • .tmp/slate-v2/playwright/integration/examples/richtext.test.ts
  • .tmp/slate-v2/site/examples/ts/richtext.tsx
  • .tmp/slate-v2/packages/slate/test/delete-contract.ts
  • docs/solutions/logic-errors/2026-04-12-structured-enter-and-backspace-need-editor-owned-keydown-paths.md
Source testDecisionSlate ownerExpected Slate proof
Headings - stays as a heading when you backspace at the start of a heading with no previous sibling nodes presentalready-applied.tmp/slate-v2/playwright/integration/examples/richtext.test.tsBrowser proof creates a single heading, collapses at [0, 0] offset 0, presses Backspace, and asserts the heading text, single h1, zero paragraphs, and collapsed selection remain unchanged. Runtime already behaved correctly; this pass added the missing proof.
Lexical Playground initialization, dropdown clicks, theme class HTMLrejectnoneProduct shell and theme DOM are not portable Slate behavior.
raw mobile/collaboration/table-model/issue variantsdefer/rejectfuture explicit owners onlyThis source row is a desktop richtext behavior. It does not claim raw device, collaboration, table-model, or issue closure.

HeadingsEnterAtEnd Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-playground/__tests__/e2e/Headings/HeadingsEnterAtEnd.spec.mjs
  • .tmp/slate-v2/playwright/integration/examples/richtext.test.ts
  • .tmp/slate-v2/site/examples/ts/richtext.tsx
  • docs/solutions/logic-errors/2026-04-12-structured-enter-and-backspace-need-editor-owned-keydown-paths.md
Source testDecisionSlate ownerExpected Slate proof
Headings - changes to a paragraph when you press enter at the end of a headingalready-applied.tmp/slate-v2/playwright/integration/examples/richtext.test.ts, .tmp/slate-v2/site/examples/ts/richtext.tsxExisting browser proof in handles heading Enter behavior from the browser creates a single heading, collapses at the end, presses Enter, and asserts one h1 plus a following paragraph. handleExitBlockEnter owns the example policy for heading end and empty heading exit.
Lexical Playground initialization, dropdown clicks, theme class HTMLrejectnoneProduct shell and theme DOM are not portable Slate behavior.
raw mobile/collaboration/table-model/issue variantsdefer/rejectfuture explicit owners onlyThis source row is a desktop richtext behavior. It does not claim raw device, collaboration, table-model, or issue closure.

HeadingsEnterInMiddle Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-playground/__tests__/e2e/Headings/HeadingsEnterInMiddle.spec.mjs
  • .tmp/slate-v2/playwright/integration/examples/richtext.test.ts
  • .tmp/slate-v2/site/examples/ts/richtext.tsx
  • docs/solutions/logic-errors/2026-04-12-structured-enter-and-backspace-need-editor-owned-keydown-paths.md
Source testDecisionSlate ownerExpected Slate proof
Headings - stays as a heading when you press enter in the middle of a headingalready-applied.tmp/slate-v2/playwright/integration/examples/richtext.test.tsExisting browser proof in handles heading Enter behavior from the browser creates one heading, collapses in the middle, presses Enter, and asserts two h1 blocks with the text split around the caret.
Lexical movement helpers, initialization, dropdown clicks, theme class HTMLrejectnoneMovement helper timing, product shell, and theme DOM are not portable Slate behavior.
raw mobile/collaboration/table-model/issue variantsdefer/rejectfuture explicit owners onlyThis source row is a desktop richtext behavior. It does not claim raw device, collaboration, table-model, or issue closure.

Indentation Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-playground/__tests__/e2e/Indentation.spec.mjs
  • .tmp/slate-v2/playwright/integration/examples/richtext.test.ts
  • .tmp/slate-v2/site/examples/ts/richtext.tsx
  • .tmp/slate-v2/playwright/integration/examples/code-highlighting.test.ts
  • .tmp/slate-v2/packages/slate/test/snapshot-contract.ts
  • docs/solutions/logic-errors/2026-05-09-slate-v2-code-highlighting-tab-must-indent-selected-lines.md
Source testDecisionSlate ownerExpected Slate proof
Can create content and indent and outdent it allcovered/defer/reject splitcode-highlighting browser owner, list outdent model owner, future paragraph/list/table indent ownerExisting Slate code-highlighting rows cover code-line Tab/Shift+Tab indentation. Existing snapshot row covers basic list outdent by lifting selected list items back to paragraphs. Paragraph padding indent, table-cell paragraph indent, all-content toolbar behavior, and exact Lexical DOM output wait for explicit indent/list/table owners.
Can only indent paragraph until the max depthdeferfuture paragraph indent ownerCurrent richtext example owns alignment, not paragraph indent depth. Do not invent an indent prop or max-depth law in raw richtext.
Can only indent until the max depth when list is emptydeferfuture list indent ownerNested empty-list indentation and max-depth policy are list-plugin behavior.
Can only indent until the max depth when list has contentdeferfuture list indent ownerSame max-depth list policy, with text content.
Can only indent until the max depth a list with nested listsdeferfuture list indent ownerMulti-selected nested-list max-depth behavior is valid product pressure, but Slate has no accepted list-indent API in this checkout.
Cannot have negative indents (#7410)defer/reject splitfuture paragraph-indent import/outdent plus list-format ownerPreventing negative indent after HTML padding import and repeated outdent needs an accepted indent importer/outdent policy. The final bullet-list conversion is product/list formatting behavior, not generic raw Slate today.
Lexical toolbar/dropdown clicks, table shell, theme classes, screenshot-style HTMLrejectnoneProduct shell and theme DOM are not portable Slate behavior.

List Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-playground/__tests__/e2e/List.spec.mjs
  • .tmp/slate-v2/playwright/integration/examples/richtext.test.ts
  • .tmp/slate-v2/site/examples/ts/richtext.tsx
  • .tmp/slate-v2/packages/slate/test/snapshot-contract.ts
  • .tmp/slate-v2/playwright/integration/examples/markdown-shortcuts.test.ts
Source test familyDecisionSlate ownerExpected Slate proof
Create list, toggle list off, and convert unordered/ordered list typesalready-applied.tmp/slate-v2/playwright/integration/examples/richtext.test.ts, .tmp/slate-v2/site/examples/ts/richtext.tsxBrowser proof now selects two richtext blocks, applies a bulleted list, toggles it back to paragraphs, applies a numbered list, and converts it back to a bulleted list from the toolbar.
Multi-block list wrapping and quote-to-list replacementcovered.tmp/slate-v2/packages/slate/test/snapshot-contract.ts, richtext browser ownerSnapshot rows already prove selected top-level blocks can become list-item children inside bulleted and numbered list wrappers. The new browser row proves the toolbar path. Exact quote-class replacement is product rendering, not a separate raw model law.
Partial copy from a list into a paragraphcovered/defer splitclipboard contract and future list-fragment browser ownerCurrent clipboard rows cover selected text/fragment slicing and list HTML paste. A native browser row for partial list copy can be added later only if it proves a gap beyond existing clipboard/list owners.
Backspace outdent, Enter outdent, empty list item exit, collapse-at-start, nested-list break removaldeferfuture list-exit/list-indent ownerThese are useful editor behaviors, but this checkout has no accepted generic list-exit or list-indent API. Do not smuggle Lexical's plugin policy into raw Slate.
Nested list indentation, max-depth, indent/outdent toolbar helpers, ordered-list restart/start metadatadeferfuture list-plugin/list-normalization ownerValid list-engine pressure, but it needs an explicit owner for indentation depth, numbering metadata, and normalization.
Markdown ordered-list start and paragraph markdown inside a listdeferfuture markdown/list shortcut ownerCurrent markdown browser rows cover list shortcuts and adjacent markdown-list merge, not ordered start numbers or "do not process heading markdown inside list" policy.
Checklist focus, checklist toggle, checklist keyboard navigationreject/deferfuture checklist plugin ownerChecklist ARIA/focus behavior is plugin/product policy, not generic richtext/list toolbar behavior.
Format menu converting list items to Normal paragraphsdeferfuture format-menu/list-split ownerSlate richtext has toolbar block buttons, not Lexical's format dropdown or its exact list splitting policy.
New indented list item preserving bold and autolink inside collapsed list itemdeferfuture list-insertion plus mark/link ownerThe mark/link invariants are valuable, but the list insertion/indent policy is not accepted in this slice. Existing mark/link owners remain separate.
Toolbar shell, theme classes, DOM value numbering, screenshots, collaboration variantsrejectnoneThese are Lexical Playground output details, not portable Slate v2 behavior claims.

Markdown Playground Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-playground/__tests__/e2e/Markdown.spec.mjs
  • .tmp/slate-v2/playwright/integration/examples/markdown-shortcuts.test.ts
  • .tmp/slate-v2/site/examples/ts/markdown-shortcuts.tsx
  • .tmp/slate-v2/site/examples/ts/markdown-preview.tsx
  • .tmp/slate-v2/playwright/integration/examples/richtext.test.ts
Source test familyDecisionSlate ownerExpected Slate proof
Numeric ordered-list shortcut, including non-1 start numbersalready-applied.tmp/slate-v2/playwright/integration/examples/markdown-shortcuts.test.ts, .tmp/slate-v2/site/examples/ts/markdown-shortcuts.tsxBrowser proof now types 25. , inserts text, and asserts a numbered list with start="25" and one item. The example parses \d+. shortcuts and wraps list items in numbered-list.
Heading, blockquote, bulleted-list shortcuts and list continuationcovered/already-appliedmarkdown-shortcuts browser ownerExisting rows cover h1, quote, bullet list creation, list continuation, and adjacent markdown-created bulleted-list merge. H3-H6 are supported by the example shortcut table but not duplicated as separate proof rows in this slice.
Markdown import/export cycles, full markdown code-block import, export next to newlinedeferfuture markdown serializer/import-export ownerCurrent Slate v2 exposes markdown shortcut and preview examples, not a full markdown serializer package. Do not hide import/export API design under shortcut tests.
Inline text transformers: bold/italic/strike nesting, intraword rules, markdown links, emojideferfuture markdown text-transformer/link ownerUseful future rows, but current Slate shortcut example owns block shortcuts only. Raw inline-link clipboard/browser owners are separate and should not claim markdown-link parsing.
Image/equation/decorator markdown imports and several text match transformers on one linereject/deferfuture product decorator/markdown ownerImage/equation decorators are product/plugin behavior. They need explicit owners before any Slate proof.
Code-formatted text exclusion for text transformers #7349deferfuture markdown text-transformer ownerValuable bug class, but no current markdown inline transformer owner exists.
Selection after link text-match transformdeferfuture markdown-link ownerSelection placement after generated inline link needs an accepted markdown-link transform before proof.
List marker export/copy-paste preservationdeferfuture markdown serializer/list ownerThis is markdown export/copy policy, not the block shortcut owner.
HR and code-fence shortcutsdeferfuture HR/code-block shortcut ownerCurrent markdown-shortcuts example does not expose HR or code-block shortcut ownership. Code-block editing is covered elsewhere.
Toolbar shell, markdown action button UI, theme classes, collaboration variantsrejectnoneProduct shell and Lexical Playground DOM output are not portable raw Slate behavior.

TextFormatting Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-playground/__tests__/e2e/TextFormatting.spec.mjs
  • .tmp/slate-v2/packages/slate/src/editor/toggle-mark.ts
  • .tmp/slate-v2/packages/slate/src/core/public-state.ts
  • .tmp/slate-v2/packages/slate/test/snapshot-contract.ts
  • .tmp/slate-v2/playwright/integration/examples/richtext.test.ts
  • .tmp/slate-v2/site/examples/ts/richtext.tsx
Source test familyDecisionSlate ownerExpected Slate proof
Active bold/italic/underline/code hotkeys create formatted inserted text and clear before later textalready-applied.tmp/slate-v2/packages/slate/test/snapshot-contract.ts, .tmp/slate-v2/playwright/integration/examples/richtext.test.ts, .tmp/slate-v2/site/examples/ts/richtext.tsxPackage proofs now lock Editor.toggleMark and tx.marks.toggle clearing inherited collapsed marks. Browser proof now types with bold, italic, underline, and code hotkeys and proves later plain text stays unmarked.
Expanded selected text bold/italic and repeated toggle-offcoveredsnapshot contract plus richtext browser ownersCurrent package rows cover expanded add/remove and mark preservation across mixed leaves. Existing richtext rows cover toolbar bold and selected-word toggle-off behavior.
Multiple partially overlapping marks and backward formatting at a text-node boundarycovered/defer splitsnapshot contract and browser mark gauntletsCore rows cover expanded mark add/remove across mixed leaves. Generated browser mark gauntlets cover selection/repair risks. Exact Lexical DOM split shape is not a separate Slate claim.
Underline plus strikethroughcovered/defer splitexisting underline owner; future strikethrough ownerRichtext owns underline but does not expose strikethrough. Do not invent a strikethrough product control in this slice.
Capitalization, font-size, font-family, input fields, reset-on-space/tab/enterreject/deferfuture typography/product ownerThese are Lexical Playground typography/product controls, not raw Slate mark behavior.
Date-time/decorator node formatting at text-node edge #2523deferfuture decorator/markable-void ownerSlate has markable void package coverage, but the date-time plugin/browser product row needs an explicit owner before claiming it.
Toolbar active-state CSS displaydefer/rejectfuture toolbar UI ownerActive CSS class assertions belong to product UI, not raw mark behavior, unless a toolbar-state owner accepts them.
Multiline selection toolbar underline active statedeferfuture toolbar UI ownerUseful UI signal, but not this mark model/browser input slice.
Product shell, theme classes, screenshots, collaboration variantsrejectnoneThese are Lexical Playground output details, not portable Slate v2 behavior claims.

LexicalTabNode Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical/src/nodes/__tests__/unit/LexicalTabNode.test.tsx
  • ../lexical/packages/lexical-rich-text/src/__tests__/unit/LexicalTabNode.test.ts
  • .tmp/slate-v2/packages/slate-dom/test/clipboard-boundary.ts
  • .tmp/slate-v2/playwright/integration/examples/paste-html.test.ts
Source testDecisionSlate ownerExpected Slate proof
can paste plain text with tabs and newlines in plain textalready-applied.tmp/slate-v2/packages/slate-dom/test/clipboard-boundary.tsPackage row now proves DOM clipboard plain-text fallback keeps literal \t text while splitting multiline paste into separate blocks and placing selection at the end of the final line. Lexical's single-plain-text-paragraph rendering is not Slate rich-text behavior.
can paste plain text with tabs and newlines in rich textalready-applied.tmp/slate-v2/packages/slate-dom/test/clipboard-boundary.tsSame package row covers rich-text block splitting with literal tab preservation.
can paste HTML with tabs and new lines (2)already-applied.tmp/slate-v2/playwright/integration/examples/paste-html.test.tsBrowser row now proves Google Docs Apple-tab-span HTML preserves two visible Hello\tworld lines across the paragraph plus loose-line source shape.
commented #4429 span with raw tab/newlinecoveredpaste-html/browser ownerCovered by the accepted Google Docs tab row plus existing body-inline normalization. The commented Lexical TODO stays source context, not a separate claim.
tab at block start / multi-block tab indentdeferfuture code/list/input keyboard ownerIndentation policy is plugin/product behavior unless a code/list owner accepts it.
tab in the middle / replacing selected text with tabdeferfuture text insertion or keyboard ownerLiteral tab keyboard insertion is valid, but this slice only accepted clipboard/browser paste. Do not route Lexical command API into generic Slate core.
TabNode serialization/type guards/selection-boundary normalizationreject for class/schema; defer for adjacent literal-tab selectionnone / future text-boundary ownerSlate stores \t as normal text, not a TabNode class. Adjacent tab/text selection replacement can be mined later as a generic text-boundary row if a source-read owner accepts it.
rich-text INSERT_TAB_COMMAND mark inheritancecovered/reject command APIexisting mark/text insertion ownersGeneric mark preservation belongs to mark insertion behavior. Lexical command and TabNode format bits are not Slate API.

IME, Composition, And Input Runtime

SourceStatusSlate ownerNext decision
../lexical/packages/lexical-playground/__tests__/e2e/AutoScroll.spec.mjsalready-applied.tmp/slate-v2/playwright/integration/examples/richtext.test.ts, .tmp/slate-v2/packages/slate-react/src/components/editable.tsxBrowser rows now prove the caret stays visible while typing through line breaks in a scrollable editor root and parent. Default scroll fallback now handles Chrome zero-rect caret ranges by scrolling the leaf.
../lexical/packages/lexical-playground/__tests__/e2e/Composition.spec.mjsalready-appliedIME stress rows, richtext/mentions/rendering browser rows, history contractHigh-value IME rows applied; only residual exact names need audit.
../lexical/packages/lexical-playground/__tests__/e2e/Events.spec.mjsapplied.tmp/slate-v2/playwright/integration/examples/plaintext.test.ts, .tmp/slate-v2/packages/slate-react/src/editable/runtime-before-input-events.ts, .tmp/slate-v2/packages/slate-react/src/editable/mutation-controller.ts, .tmp/slate-v2/packages/slate-react/src/editable/selection-reconciler.tsSource-read complete. Added browser proof for Mac-style beforeinput substitutions: autocapitalization via a native insertText followed by insertReplacementText, and double-space period replacement after emoji via an expanded insertText target range. Runtime now flushes queued native text repair before the next model-owned beforeinput, model text input applies provided replacement target ranges even after native repair moves current selection, and expanded insertText target ranges are honored even when model selection is preferred.
../lexical/packages/lexical-playground/__tests__/e2e/Focus.spec.mjsalready-applied.tmp/slate-v2/playwright/integration/examples/richtext.test.tsBrowser row now proves Slate keeps the model selection when focus moves outside the editor. Lexical plain-text tab-out row stays out unless a raw tab navigation owner is accepted.
../lexical/packages/lexical-playground/__tests__/e2e/Keyboard.spec.mjsalready-applied for insertTranspose beforeinput.tmp/slate-v2/packages/slate-react/test/model-input-strategy-contract.test.ts, .tmp/slate-v2/playwright/integration/examples/plaintext.test.ts, .tmp/slate-v2/packages/slate-react/src/editable/model-input-strategy.ts, .tmp/slate-v2/packages/slate-react/src/editable/mutation-controller.ts, .tmp/slate-v2/packages/slate-react/src/editable/editing-kernel.tsSource-read complete. Added a first-class model-owned transpose-character command for insertTranspose, package proof that two adjacent transposes move abc to bca, and plaintext browser proof that synthetic beforeinput follows the runtime event path and preserves the collapsed selection after the swapped pair. Lexical Playground setup, OS/browser transpose flake tags, rich fixture shell, raw mobile, collaboration, table-model, and issue claims stay out.
../lexical/packages/lexical-playground/__tests__/e2e/KeyboardShortcuts.spec.mjsalready-applied for accepted richtext/code-block shortcut rows; defer/reject for product typography, checklist, and indent rows.tmp/slate-v2/playwright/integration/examples/richtext.test.ts, .tmp/slate-v2/site/examples/ts/richtext.tsx, .tmp/slate-v2/playwright/integration/examples/code-highlighting.test.ts, .tmp/slate-v2/site/examples/ts/code-highlighting.tsxSource-read complete. Added browser proof and example handlers for richtext paragraph/heading block shortcuts, alignment shortcut handling, clear-formatting shortcut, and code-block conversion shortcut. Existing mark hotkeys, clear-formatting, toolbar block/list/alignment, and code-block rows cover the adjacent behavior. Heading 3, checklist, lowercase/uppercase/capitalize, strikethrough/subscript/superscript, font-size controls, paragraph indent/outdent, toolbar active-state DOM, raw mobile, collaboration, table-model, and issue claims stay deferred or rejected until explicit owners accept them.
../lexical/packages/lexical-playground/__tests__/e2e/Mutations.spec.mjsalready-appliedDOM repair policy plus .tmp/slate-v2/playwright/integration/examples/richtext.test.tsRichtext browser rows already cover native text mutation, selection, and repair traces; dom-repair-policy-contract.ts now locks structural child-list rollback while leaving character-data text sync alone. No desktop structural repair or raw Android device claim.
../lexical/packages/lexical-playground/__tests__/e2e/TextEntry.spec.mjsalready-applied for accepted heading-start and marked-boundary Enter rows; covered/defer/reject for residual text-entry rows.tmp/slate-v2/playwright/integration/examples/markdown-shortcuts.test.ts, .tmp/slate-v2/site/examples/ts/markdown-shortcuts.tsx, .tmp/slate-v2/playwright/integration/examples/richtext.test.ts, plaintext/richtext browser and stress ownersSource-read complete. Added browser proof and markdown-shortcuts keydown policy for heading-start Enter inserting a paragraph before the heading, plus richtext browser proof for native Enter splitting between plain and bold text. Basic typing/replacement/delete rows are covered; soft-break/newline-node and whitespace-normalization rows stay deferred to explicit future owners.
../lexical/packages/lexical-playground/__tests__/regression/8153-safari-ime-delete-selection.spec.mjsdeferWebKit/browser IME ownerNeeds honest WebKit composition/delete proof; do not promote from Chromium or model-only tests.

KeyboardShortcuts Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-playground/__tests__/e2e/KeyboardShortcuts.spec.mjs
  • ../lexical/packages/lexical-playground/__tests__/keyboardShortcuts/index.mjs
  • .tmp/slate-v2/site/examples/ts/richtext.tsx
  • .tmp/slate-v2/playwright/integration/examples/richtext.test.ts
  • .tmp/slate-v2/site/examples/ts/code-highlighting.tsx
  • .tmp/slate-v2/playwright/integration/examples/code-highlighting.test.ts
  • .tmp/slate-v2/packages/slate-dom/src/utils/hotkeys.ts
Source test familyDecisionSlate ownerExpected Slate proof
paragraph/heading block shortcutsalready-applied for paragraph, heading-one, and heading-two; defer heading-threerichtext example/browser ownerBrowser proof now drives editor key events through the richtext example and proves mod+alt+1, mod+alt+0, and mod+alt+2 convert the selected block between heading/paragraph forms. Heading three stays out because the current richtext example renders only heading one and two.
alignment shortcutsalready-applied for accepted richtext alignment ownerrichtext example/browser ownerThe richtext example now maps alignment hotkeys through the same toggleBlock owner as toolbar alignment, and browser proof covers a delivered alignment shortcut changing the selected heading alignment. Exact Lexical toolbar dropdown text stays rejected.
clear-formatting shortcutalready-appliedrichtext example/browser ownerBrowser proof applies a mark by shortcut, clears by mod+\, removes the selected mark, clears block alignment, and preserves the semantic heading block.
insert code block shortcutalready-appliedcode-highlighting example/browser ownerThe code-highlighting example now reuses its code-block conversion command for mod+shift+c and mod+alt+c; browser proof converts a selected paragraph into a code block with code-line content.
bold/italic/underline/code mark shortcutscovered/already-appliedexisting richtext mark-hotkey browser and package mark ownersTextFormatting.spec.mjs already added package and browser proof for active mark hotkeys, default prevention, inserted formatted text, and clearing active marks before later text.
list shortcutscovered/defer splitexisting richtext toolbar list owner; future stable list shortcut owner if acceptedCurrent browser proof covers toolbar list toggle/conversion and empty paragraph list toggle. Lexical digit-based mod+shift+7/8/9 shortcut bindings are layout/product keymap policy; checklist is not accepted in the richtext example.
lowercase/uppercase/capitalize, strikethrough, subscript, superscript, font-size controlsdefer/rejectfuture typography/product ownerThese are Lexical Playground product formatting controls, not raw Slate editor behavior in this checkout.
indent/outdent shortcutsdeferfuture paragraph/list/table indent ownerCurrent Slate owners cover code-line Tab/Shift+Tab and basic list outdent model flow. Paragraph padding indent/outdent by mod+[/mod+] needs an explicit indent policy owner.
toolbar active state, dropdown text, theme classes, browser/OS labelsrejectnoneProduct shell assertions and upstream harness labels are not portable Slate behavior.
raw mobile, collaboration, table-model, issue closuredefer/rejectfuture explicit owners onlyThis slice makes no raw-device, yjs/collaboration, table-model, or Slate issue claim.

Lexical Playground TextEntry Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-playground/__tests__/e2e/TextEntry.spec.mjs
  • .tmp/slate-v2/playwright/integration/examples/markdown-shortcuts.test.ts
  • .tmp/slate-v2/playwright/integration/examples/richtext.test.ts
  • .tmp/slate-v2/playwright/integration/examples/plaintext.test.ts
  • .tmp/slate-v2/packages/slate/test/snapshot-contract.ts
  • current richtext/plaintext browser stress owners
Source testDecisionSlate ownerExpected Slate proof
Can type 'Hello' as a header and insert a paragraph beforeappliedmarkdown-shortcuts browser owner and example keydown policyBrowser proof now creates a heading through the markdown shortcut, places the DOM selection at the heading start, presses Enter, and asserts one empty paragraph before the heading with selection preserved at the start of the heading. The example now converts the split empty heading to a paragraph for heading-start Enter. Solution note: docs/solutions/logic-errors/2026-05-09-heading-start-enter-must-normalize-split-block-type.md.
Can insert a paragraph between two text nodesappliedrichtext browser ownerBrowser proof now types plain text, toggles bold, types bold text, places the DOM selection at the plain/bold boundary, presses native Enter, and asserts a plain paragraph followed by a bold paragraph with selection at the start of the bold text.
basic typing, fill/replace, select-all replacement, partial replacement, character Backspace, and word deletioncoveredplaintext/richtext browser rows, delete contracts, generated destructive edit and word-delete stress ownersExisting owners already prove typed insertion, select-all replacement through editor state, selected range Delete/Backspace, character deletion, word movement/delete, and follow-up insertion with synchronized model/DOM selection. No duplicate one-line browser rows were added.
paragraphed text entry and selectioncovered/defer splitrichtext browser stress and IME rows; future emoji/product transform ownerCurrent generated editing rows prove paragraph text entry plus selection movement and replacement across rich text. Lexical emoji shortcode/theme rendering is product transform output and stays out.
first paragraph Backspace after trimmable spacesdeferfuture whitespace-normalization/backspace policy owner if acceptedLexical trims playground whitespace before the paragraph Backspace assertion. Slate should not silently adopt that as generic text-entry law without an explicit whitespace-normalization owner.
soft-break/newline-node navigation and deletion rowsdeferfuture soft-break/line-break ownerSlate v2 currently stores hard block splits for insertSoftBreak in the proved core path; Lexical LineBreakNode selection behavior needs a deliberate line-break owner before copying.
Lexical Playground shell, theme DOM, browser/OS labels, raw mobile, collaboration, table-model, and issue claimsreject/defernone / future explicit ownersThis slice makes no raw-device, yjs, table-model, theme DOM, browser-flake, or issue-closure claim.

Lexical Playground Events Row-Level Source Read

Source-drilled on 2026-05-09 against:

  • ../lexical/packages/lexical-playground/__tests__/e2e/Events.spec.mjs
  • .tmp/slate-v2/playwright/integration/examples/plaintext.test.ts
  • .tmp/slate-v2/packages/slate-react/test/model-input-strategy-contract.test.ts
  • .tmp/slate-v2/packages/slate-react/test/selection-reconciler-contract.ts
  • .tmp/slate-v2/packages/slate-react/src/editable/runtime-before-input-events.ts
  • .tmp/slate-v2/packages/slate-react/src/editable/mutation-controller.ts
  • .tmp/slate-v2/packages/slate-react/src/editable/selection-reconciler.ts
Source testDecisionSlate ownerExpected Slate proof
Autocapitalization (MacOS specific)appliedplaintext browser input transport plus model-input strategyBrowser proof dispatches a native insertText beforeinput, mutates DOM as the browser would, then dispatches insertReplacementText before the input repair. First proof failed red with only I, then with iSI; runtime now imports queued native text before the replacement and applies the replacement to its provided target range, producing IS.
Add period with double-space after emoji (MacOS specific) #3953appliedplaintext browser input transport plus selection reconcilerBrowser proof dispatches expanded insertText target range over the trailing space after 🙂 . First proof failed red as 🙂 . ; selection reconciliation now honors expanded insertText target ranges even when model selection is preferred, producing 🙂. .
Lexical Playground emoji shortcode rendering, theme spans, page.pause, OS label, and plain-text/rich-text fixture shellrejectnoneProduct shell and test harness details are not raw Slate behavior. The portable invariant is the beforeinput target-range substitution flow.

Selection, Inline Atoms, Voids, And Caret Movement

SourceStatusSlate ownerNext decision
../lexical/packages/lexical-playground/__tests__/e2e/AutoLinks.spec.mjsapplied for single-URL paste boundary; defer/reject for autolink plugin policy.tmp/slate-v2/playwright/integration/examples/inlines.test.ts, future link/autolink plugin ownerSource-read complete. Added inlines browser proof that pasting a single URL at a collapsed Slate selection creates one safe inline link, moves the caret outside the link, and keeps follow-up typing outside the link. Broad URL/email parser matrices, delimiter tokenization, invalid URL grammar, unlink/relink UI, unlinked-autolink preservation, emoji shortcode destruction, styling/font rows, toolbar setup, exact DOM/theme output, raw mobile, collaboration, table-model, and issue claims stay deferred or rejected under future link/autolink plugin owners.
../lexical/packages/lexical-playground/__tests__/e2e/Hashtags.spec.mjsapplied for accepted dynamic text-token editing rows; defer/reject for hashtag plugin policy.tmp/slate-v2/playwright/integration/examples/highlighted-text.test.ts, .tmp/slate-v2/site/examples/ts/highlighted-text.tsxSource-read complete. Existing highlighted-text rows already covered dynamic hashtag-style decoration, Space splitting, Delete/Backspace boundaries, transient-prefix navigation, decorated range copy/cut, and decorated-text IME/editing. Added browser proof that deleting the delimiter between #hello and world expands the decorated token, restoring the delimiter shrinks it back, and deleting the leading # drops the decoration while keeping the caret stable. Lexical's hashtag plugin grammar, invalid-match matrix, markdown import/export shell, format inheritance styling, exact DOM/theme output, raw mobile, collaboration, table-model, and issue claims stay deferred or rejected.
../lexical/packages/lexical-playground/__tests__/e2e/HorizontalRule.spec.mjsdeferfuture HR/block-void ownerSource-read complete. Slate v2 has block void/image/embed proof but no HR owner in this checkout, so do not invent one under inline boundary work.
../lexical/packages/lexical-playground/__tests__/e2e/Keywords.spec.mjscovered for raw dynamic text-token editing; defer/reject for keyword plugin policy.tmp/slate-v2/playwright/integration/examples/highlighted-text.test.ts, future keyword/autocomplete plugin ownerSource-read complete. The portable rows are dynamic decorated text-token editing, delimiter merge/split updates, selection movement around the decorated range, and mark-adjacent editing. Existing highlighted-text proofs cover projected text selection/movement/editing, mark-click typing through projections, decorated IME, copy/cut semantics, hashtag-style delimiter merge/split, and deletion of selected decorated ranges. Lexical's exact congrats grammar, bracket/team token policy, keyword styling, product plugin setup, exact DOM/theme output, raw mobile, collaboration, table-model, and issue claims stay deferred or rejected.
../lexical/packages/lexical-playground/__tests__/e2e/Links.spec.mjsalready-applied for accepted raw rows; defer for plugin policy.tmp/slate-v2/playwright/integration/examples/inlines.test.ts, .tmp/slate-v2/packages/slate/test/clipboard-contract.tsSource-read complete. Boundary typing/copy/paste rows are covered; toolbar conversion, image linking, autolink URL paste, and paste-inside-link splitting are plugin/product policy.
../lexical/packages/lexical-playground/__tests__/e2e/Mentions.spec.mjsalready-applied for Slate markable-inline-void behavior; reject mutable mention text policy.tmp/slate-v2/playwright/integration/examples/mentions.test.ts, .tmp/slate-v2/packages/slate-dom/test/clipboard-boundary.tsSource-read complete. Slate proves mention insertion, IME, atomic arrow selection, and inline-void clipboard. Lexical's editable mention text deletion is not Slate's markable-inline-void contract.
../lexical/packages/lexical-playground/__tests__/e2e/Navigation.spec.mjsalready-applied for model/query rows; defer native shortcut matrix.tmp/slate-v2/packages/slate/test/query-contract.ts, future navigation browser ownerSource-read complete. Slate already proves offset/character/word/block positions, before/after, inline fragmentation, atomic void traversal, non-selectable skipping, and top-level boundary traversal. Browser word-shortcut differences across Chromium/Firefox/WebKit/Windows/macOS are native transport rows and need an explicit keyboard/navigation browser owner before copying.
../lexical/packages/lexical-playground/__tests__/e2e/Selection.spec.mjsalready-applied for accepted selection/table rows; defer table model, RTL decorator, and format persistence rows.tmp/slate-v2/packages/slate/test/delete-contract.ts, .tmp/slate-v2/playwright/integration/examples/select.test.ts, .tmp/slate-v2/playwright/integration/examples/tables.test.ts, .tmp/slate-v2/packages/slate-react/test/selection-runtime-contract.test.tsSource-read complete. Existing Slate rows cover no focus-on-load/focus preservation, triple-click block selection, line/unit delete package behavior, inline insertion boundaries, table containment/triple-click/drag containment, and blurred-editor selection preservation policy. Whole-table range expansion, RTL decorator navigation, collapsible/date-time product nodes, and text-format persistence are separate owners.
../lexical/packages/lexical-playground/__tests__/e2e/SelectionAlwaysOnDisplay.spec.mjscovered for raw blur persistence; defer/reject for always-on display overlay.tmp/slate-v2/playwright/integration/examples/richtext.test.ts, future product selection-display ownerSource-read complete. The portable Slate-owned invariant is that model selection survives focus leaving the editor; current richtext browser proof already covers this in keeps model selection when focus moves outside the editor. Lexical's fake-selection overlay, highlight-background alignment tolerance, exact DOM/theme output, plain-text skip policy, raw mobile/device, collaboration, table-model, and issue claims stay deferred or rejected as product visualization or future dedicated owners.
../lexical/packages/lexical-playground/__tests__/regression/1258-delete-forward.spec.mjsalready-applied.tmp/slate-v2/packages/slate/test/transforms/delete/unit-character/first.tsxSource-read complete. Portable row is simple forward character delete at line start; existing unit-character fixture covers it.
../lexical/packages/lexical-playground/__tests__/regression/1730-delete-backword.spec.mjsalready-applied.tmp/slate-v2/packages/slate/test/transforms/delete/unit-character/multiple-reverse.tsxSource-read complete. Portable row is simple backward character delete at line end; existing reverse unit-character fixture covers it.
../lexical/packages/lexical-playground/__tests__/regression/6974-delete-character-backward.spec.mjsalready-applied.tmp/slate-v2/packages/slate/test/transforms/delete/point/inline-void-reverse.tsxSource-read complete. Existing point delete fixture already merges a following block into a prior block ending with an inline void.
../lexical/packages/lexical-playground/__tests__/regression/7163-graphemes.spec.mjsalready-applied.tmp/slate-v2/packages/slate/test/text-units-contract.tsCovered by explicit Unicode text-unit distances plus forward/backward unit: "character" deletion rows.
../lexical/packages/lexical-playground/__tests__/regression/7246-delete-character-backward-list.spec.mjsalready-applied.tmp/slate-v2/packages/slate/test/delete-contract.tsAdded package contract that Backspace at a following paragraph start merges into the previous list item. No browser claim.
../lexical/packages/lexical-playground/__tests__/regression/7319-delete-character-backward-nodeselection.spec.mjsalready-applied for generic block-void delete; reject Lexical NodeSelection UI policy.tmp/slate-v2/packages/slate/test/transforms/delete/voids-false/block-after-multiple-reverse.tsx, .tmp/slate-v2/packages/slate/src/transforms-text/delete-text.tsAdded collapsed backward delete proof/fix so adjacent top-level block voids delete one at a time. HR styling and Lexical node-selection classes stay out.
../lexical/packages/lexical-selection/src/__tests__/unit/LexicalSelection.test.tsxalready-applied for selected rebase row; refactor-existing for block/style transforms.tmp/slate-v2/packages/slate/test/selection-rebase-contract.ts, .tmp/slate-v2/packages/slate/test/range-ref-contract.ts, block transform ownersSource-read complete. Added package proof that selection rebases to a previous inline when the selected leaf is removed. Block-selection movement, $setBlocksType, CSS patching, and table block transforms stay out of this slice.
../lexical/packages/lexical-selection/src/__tests__/unit/LexicalSelectionHelpers.test.tsalready-applied for selected rebase/fragment rows; refactor-existing for style helpers.tmp/slate-v2/packages/slate/test/selection-rebase-contract.ts, .tmp/slate-v2/packages/slate/test/clipboard-contract.ts, future mark/style ownerSource-read complete. Insert/extract/fragment behavior maps to current clipboard contracts; selected node-removal rebase is now locked in selection-rebase-contract.ts. Lexical CSS style cache and helper API details are not generic Slate core behavior.
../lexical/packages/lexical/src/__tests__/unit/LexicalSelection.test.tsalready-applied for inline insertion, select-all/extract, and point-order rows; defer token/segmented text-mode rows.tmp/slate-v2/packages/slate/test/query-contract.ts, .tmp/slate-v2/packages/slate/test/clipboard-contract.ts, .tmp/slate-v2/playwright/integration/examples/inlines.test.tsSource-read complete. Slate owners already cover inline-boundary insertion, selected fragment extraction, full-document replacement, range/point traversal, and inline boundary paste. Lexical token/segmented text modes, decorator text content, and DOM import format reset are Lexical-specific or require a separate Slate mark/style owner.
../lexical/packages/lexical/src/caret/__tests__/unit/LexicalCaret.test.tsalready-applied for traversal/order rows; already-applied plus strengthened delete proof for destructive range rows; reject Lexical caret class internals and token/segmented modes.tmp/slate-v2/packages/slate/test/query-contract.ts, .tmp/slate-v2/packages/slate/test/delete-contract.ts, .tmp/slate-v2/packages/slate/test/operations-contract.ts, .tmp/slate-v2/packages/slate/test/transforms-contract.ts, .tmp/slate-v2/packages/slate/test/text-units-contract.tsSource-read complete. Slate already proves point/path ordering, common ancestor/path behavior, before/after/positions traversal, inline/void/non-selectable boundaries, raw split operations, and text-unit movement. Added compact package proof that expanded range deletion trims both sibling-leaf edges and cross-block edges before collapsing at the anchor. Lexical caret object construction, node-key mechanics, decorator payloads, and token/segmented text modes stay out.

Tables

SourceStatusSlate ownerNext decision
../lexical/packages/lexical-playground/__tests__/e2e/Tables.spec.mjsdefer.tmp/slate-v2/playwright/integration/examples/tables.test.ts, future table model ownerCurrent containment rows are applied; whole-table/range/merge/rowspan rows need table-model decision.
../lexical/packages/lexical-playground/__tests__/regression/6870-table-left-arrow-selection.spec.mjsdeferfuture table navigation/model ownerLeft-arrow table selection is useful, but this non-table execution lane explicitly does not claim table-navigation parity. Reopen under a table navigation/model plan only.
../lexical/packages/lexical-table/src/__tests__/unit/LexicalTableCellNode.test.tsdeferfuture table model ownerReject Lexical node shape; keep only raw table-cell model invariants if accepted.
../lexical/packages/lexical-table/src/__tests__/unit/LexicalTableExtension.test.tsrejectnoneExtension/plugin wiring.
../lexical/packages/lexical-table/src/__tests__/unit/LexicalTableMobileSelection.test.tsxdeferraw-device table ownerNeeds real device/touch proof, not desktop viewport.
../lexical/packages/lexical-table/src/__tests__/unit/LexicalTableNode.test.tsxdeferfuture table model ownerTable node shape is Lexical-specific; only model invariants survive.
../lexical/packages/lexical-table/src/__tests__/unit/LexicalTablePlugin.test.tsxrejectnonePlugin wiring.
../lexical/packages/lexical-table/src/__tests__/unit/LexicalTableRowNode.test.tsdeferfuture table model ownerSame table model boundary.
../lexical/packages/lexical-table/src/__tests__/unit/LexicalTableSelection.test.tsxdeferfuture table model ownerFull table selection model; do not claim #2558 from containment proof.
../lexical/packages/lexical-table/src/__tests__/unit/LexicalTableUtils.test.tsdeferfuture table model ownerUtility invariants only after table model is accepted.

Mixed Portable Or Product-Adjacent Rows

SourceStatusSlate ownerNext decision
../lexical/packages/lexical-playground/__tests__/e2e/Autocomplete.spec.mjsrejectnoneProduct plugin. Reopen only if a raw inline insertion invariant is split out.
../lexical/packages/lexical-playground/__tests__/e2e/CharacterLimit.spec.mjsrejectnoneProduct policy.
../lexical/packages/lexical-playground/__tests__/e2e/ColumnLayoutBackspaceAtEnd.spec.mjsdefertable/layout model ownerColumn layout is product/table-like; needs accepted raw model first.
../lexical/packages/lexical-playground/__tests__/e2e/DateTime.spec.mjsrejectnoneProduct node/plugin behavior.
../lexical/packages/lexical-playground/__tests__/e2e/Emoticons.spec.mjsrejectnoneProduct transform/plugin; emoji text-unit rows are covered elsewhere.
../lexical/packages/lexical-playground/__tests__/e2e/EquationNode.spec.mjsrejectnoneProduct node/plugin behavior.
../lexical/packages/lexical-playground/__tests__/e2e/MaxLength.spec.mjsrejectnoneProduct constraint policy.
../lexical/packages/lexical-playground/__tests__/e2e/SpecialTexts.spec.mjsreject for bracket special-text transform; covered for literal bracket typingexisting plaintext/richtext text insertion ownersSource-read complete. Bracket-triggered span replacement, bracket stripping, empty theme span output, and shouldAllowHighlightingWithBrackets are Lexical Playground product transform/theme policy. The disabled-option row is plain literal text insertion and is already covered by Slate text-entry/input owners.
../lexical/packages/lexical-playground/__tests__/e2e/Toolbar.spec.mjsrejectnoneProduct shell; no raw Slate target.

Lexical Playground SpecialTexts Row-Level Source Read

Source: ../lexical/packages/lexical-playground/__tests__/e2e/SpecialTexts.spec.mjs.

Source rowDecisionSlate ownerReason
Single [MLH Fellowship] becomes one .PlaygroundEditorTheme__specialText span with brackets strippedrejectnoneProduct text-transform and theme DOM. Slate should not copy Lexical Playground's bracket-highlighting plugin.
Two bracketed special texts produce two themed spans with an empty text span betweenrejectnoneProduct transform output shape, not portable editor behavior.
Disabled bracket highlighting keeps literal [MLH Fellowship] textcoveredexisting plaintext/richtext text insertion ownersPlain bracket typing is ordinary text insertion; no missing Slate owner found.

Portable Editor Behavior And Regressions

SourceStatusSlate ownerNext decision
../lexical/packages/lexical-playground/__tests__/e2e/DraggableBlock.spec.mjsdeferdrag/drop owner if acceptedDrag product behavior needs a raw drag/drop owner before porting.
../lexical/packages/lexical-playground/__tests__/e2e/Images.spec.mjsapplied for selected image Backspace; already-applied for image movement/selection and HTML image import; defer/reject product image flows.tmp/slate-v2/playwright/integration/examples/images.test.ts, .tmp/slate-v2/playwright/integration/examples/paste-html.test.ts, .tmp/slate-v2/packages/slate/test/query-contract.tsSource-read complete. Added browser proof that Backspace deletes a clicked selected image void. Existing image browser rows cover movement into/out of image voids, vertical movement, shifted selection into images, selected-image Enter, and visual spacer behavior. Existing paste-html rows cover Lexical image HTML with optional captions. Toolbar/upload, dimensions, drag/drop product policy, multi-node NodeSelection replacement, caption editor internals, raw mobile, collaboration, table-model, and issue claims stay out.
../lexical/packages/lexical-playground/__tests__/e2e/Placeholder.spec.mjsapplied for empty placeholder value/selection; already-applied for line-break DOM shape; reject product placeholder copy variants.tmp/slate-v2/playwright/integration/examples/placeholder.test.ts, .tmp/slate-v2/packages/slate-react/test/rendered-dom-shape-contract.tsxSource-read complete. Added browser proof that a focused empty placeholder editor shows the placeholder, keeps empty model text, and selects [0,0] offset 0. Existing rendered-DOM contract covers the empty-block line-break placeholder. Lexical rich/plain/collab placeholder copy is product shell text, not core editor law.
../lexical/packages/lexical-playground/__tests__/e2e/Tab.spec.mjsalready-applied for code-block Tab and literal-tab paste; defer/reject for rich paragraph Tab+IME and native start-of-line movement.tmp/slate-v2/playwright/integration/examples/code-highlighting.test.ts, .tmp/slate-v2/packages/slate-dom/test/clipboard-boundary.ts, .tmp/slate-v2/playwright/integration/examples/paste-html.test.ts, future keyboard/IME/indent/text-boundary ownersSource-read complete. Existing code-highlighting browser proof owns Tab inside code lines. Existing clipboard and paste-html rows own literal tab preservation from plain text and Google Docs Apple-tab-span HTML. Lexical Playground's paragraph indent plus IME row, TabNode DOM output, and Ctrl/Meta+Arrow movement after typed Tab stay deferred or rejected until explicit keyboard/IME/paragraph-indent/text-boundary owners accept them.
../lexical/packages/lexical-playground/__tests__/regression/1055-fast-typing-undo.spec.mjsapplied.tmp/slate-v2/packages/slate-history/test/history-contract.tsSource-read complete. Strengthened the existing redo-invalidation stack-law row so a new edit after undo is also undoable, matching the Lexical regression invariant without importing Playground browser setup.
../lexical/packages/lexical-playground/__tests__/regression/1083-backspace-with-element-at-front.spec.mjsapplied.tmp/slate-v2/packages/slate/test/delete-contract.ts, .tmp/slate-v2/packages/slate/src/transforms-text/delete-text.tsSource-read complete. Added package proof for deleting a full selection whose visible content starts with an inline link and a partial selection that starts at an inline link. The delete transform now removes fully-selected inline ancestors when the expanded range crosses outside the inline, instead of leaving empty inline shells or invalid start points.
../lexical/packages/lexical-playground/__tests__/regression/1113-link-newline-at-end.spec.mjsapplied.tmp/slate-v2/playwright/integration/examples/inlines.test.ts, .tmp/slate-v2/site/examples/ts/inlines.tsxSource-read complete. Added browser proof that Enter after a typed URL wrapped as an inline link moves the selection outside the link and keeps follow-up text out of the link. Fixed the inlines example so collapsed link insertion moves one offset out of the inserted inline, avoiding an empty duplicate link on the next paragraph.
../lexical/packages/lexical-playground/__tests__/regression/1384-insert-nodes.spec.mjsapplied.tmp/slate-v2/packages/slate/test/clipboard-contract.ts, .tmp/slate-v2/packages/slate/src/transforms-text/insert-fragment.ts, .tmp/slate-v2/playwright/integration/examples/code-highlighting.test.tsSource-read complete. Despite the filename, the portable row is code-block clipboard insertion: a copied nested code-line fragment pasted inside an active code line must merge into that code line instead of inserting a sibling or top-level code block. Added package and browser proof; insertFragment now fits a single nested text-block child from the same structural container into the active nested text block. Lexical Playground setup, exact gutter/theme output, raw mobile, collaboration, table-model, and issue rows stay out.
../lexical/packages/lexical-playground/__tests__/regression/221-editing-hashtags.spec.mjsapplied.tmp/slate-v2/site/examples/ts/highlighted-text.tsx, .tmp/slate-v2/playwright/integration/examples/highlighted-text.test.tsSource-read complete. The accepted row maps to dynamic decorated text-token editing, not mark or inline-void behavior. Added hashtag-style projection proof for Space splitting a token, Delete at a trailing-space boundary, and Backspace from the plain tail back into the token. Lexical Playground setup, hashtag plugin product policy, exact DOM/theme output, raw mobile, collaboration, table-model, and issue rows stay out.
../lexical/packages/lexical-playground/__tests__/regression/230-navigation-around-hashtags.spec.mjsapplied.tmp/slate-v2/playwright/integration/examples/highlighted-text.test.tsSource-read complete. The accepted row maps to dynamic decorated text-token navigation after transient plain prefix insertion/deletion. Added browser proof that after deleting a prefix before #foo, ArrowRight moves the collapsed selection into the decorated token at offset 1 through the model-owned movement path. Lexical Playground hashtag plugin setup, exact DOM/theme output, raw mobile, collaboration, table-model, and issue rows stay out.
../lexical/packages/lexical-playground/__tests__/regression/3136-insert-nodes-adjacent-to-inline.spec.mjsapplied.tmp/slate-v2/packages/slate/test/clipboard-contract.ts, .tmp/slate-v2/playwright/integration/examples/inlines.test.tsSource-read complete. The accepted rows are rich paste/replacement of selected plain text immediately before and immediately after an inline link. Added core fragment proofs for both inline-adjacent replacement directions and browser proof that rich HTML paste replaces selected adjacent text without expanding or swallowing the neighboring link. Lexical Playground link toolbar setup, exact DOM/theme output, raw mobile, collaboration, table-model, and issue rows stay out.
../lexical/packages/lexical-playground/__tests__/regression/379-backspace-with-mentions.spec.mjsapplied.tmp/slate-v2/playwright/integration/examples/mentions.test.tsSource-read complete. Added browser proof that splitting immediately before a leading inline mention and pressing Backspace at that line boundary preserves both mention atoms and restores the boundary selection. Lexical Playground typeahead setup, mention styling, exact DOM/theme output, raw mobile, collaboration, table-model, and issue rows stay out.
../lexical/packages/lexical-playground/__tests__/regression/399-open-line.spec.mjsapplied.tmp/slate-v2/packages/slate-dom/src/utils/hotkeys.ts, .tmp/slate-v2/packages/slate-react/src/editable/editing-kernel.ts, .tmp/slate-v2/packages/slate-react/src/editable/mutation-controller.ts, .tmp/slate-v2/playwright/integration/examples/richtext.test.tsSource-read complete. Added a Mac Ctrl+O open-line hotkey and a dedicated model-owned open-line insert-break variant that inserts an empty paragraph before the current block and keeps selection there instead of moving into following text. Added browser proof for foo / bar that asserts ['foo', '', 'bar'], selection at the empty line, and kernel command metadata. Lexical rich/plain shell, OS labels, exact DOM/theme output, raw mobile, collaboration, table-model, and issue rows stay out.
../lexical/packages/lexical-playground/__tests__/regression/429-swapping-emoji.spec.mjsapplied.tmp/slate-v2/playwright/integration/examples/richtext.test.tsSource-read complete. Added browser proof that Enter at the start of a plain Unicode emoji line opens an empty block before it, keeps selection at the emoji-line start, and Backspace rejoins without corrupting emoji text or selection. Lexical emoji substitution UI, exact emoji span/theme DOM, flaky tag, raw mobile, collaboration, table-model, and issue rows stay out.
../lexical/packages/lexical-playground/__tests__/regression/4872-full-row-span-cell-merge.spec.mjsdeferfuture table model ownerRowspan/merge table model.
../lexical/packages/lexical-playground/__tests__/regression/4876-unmerge-cell.spec.mjsdeferfuture table model ownerUnmerge cell table model.
../lexical/packages/lexical-playground/__tests__/regression/5251-paste-into-inline-element.spec.mjsapplied.tmp/slate-v2/packages/slate/test/clipboard-contract.ts, .tmp/slate-v2/packages/slate/src/transforms-text/insert-fragment.ts, .tmp/slate-v2/packages/slate-dom/src/plugin/dom-clipboard-runtime.ts, .tmp/slate-v2/packages/slate-dom/test/clipboard-boundary.ts, .tmp/slate-v2/playwright/integration/examples/inlines.test.tsSource-read complete. The accepted row is selected inline-link text replacement by a rich clipboard payload: pasted content must stay outside the surviving link tail. Added package proof for rich fragment insertion, DOM clipboard fallback proof for HTML-with-plain-text payloads, and browser proof on the inlines example. insertFragment now handles selected one-level inline text with a single replacement operation, and DOM plain-text fallback routes expanded same-inline selections through fragment insertion instead of inheriting the inline. Lexical Playground link toolbar setup, exact DOM/theme output, browser clipboard quirks beyond DataTransfer fallback, raw mobile, collaboration, table-model, and issue rows stay out.
../lexical/packages/lexical-playground/__tests__/regression/5583-select-list-followed-by-element-node.spec.mjsapplied.tmp/slate-v2/playwright/integration/examples/dom-coverage-boundaries.test.tsSource-read complete. Added browser proof that a native drag selection from a materialized list item to a non-editable boundary placeholder imports to a valid Slate range without page errors. This preserves the portable crash guard without importing Lexical Playground drag helpers, horizontal-rule product shell, exact DOM/theme output, raw mobile/device, collaboration, table-model, or issue claims.
../lexical/packages/lexical-playground/__tests__/regression/7266-column-header-merged-cells.spec.mjsdeferfuture table model ownerColumn header / merged cells table model.
../lexical/packages/lexical-playground/__tests__/regression/7354-firefox-decorator-paste.spec.mjsalready-appliedplaintext/editable-void browser ownersFirefox decorator/native paste class covered by selected apply lane.
../lexical/packages/lexical-playground/__tests__/regression/7635-SELECTION_INSERT_CLIPBOARD_NODES_COMMAND.spec.mjsapplied.tmp/slate-v2/playwright/integration/examples/editable-voids.test.ts, .tmp/slate-v2/site/examples/ts/richtext.tsx, .tmp/slate-v2/packages/slate-react/src/editable/selection-reconciler.ts, .tmp/slate-v2/packages/slate-react/src/editable/selection-controller.tsSource-read complete. The portable row is rich clipboard insertion inside a nested editable island plus restoring the parent editor afterward, not Lexical SELECTION_INSERT_CLIPBOARD_NODES_COMMAND. Added editable-void browser proof that rich HTML paste inside the nested rich-text editor preserves bold text, stays out of the parent value, preserves the parent selection, and still lets the parent editor type afterward. RichText now owns a narrow HTML paste capability that reuses the shared deserializer while normalizing to supported rich-text blocks and marks. Selection import now rejects beforeinput/selectionchange ranges whose endpoints cross from the parent editor into a nested editor. Lexical image caption UI, Playground command harness, exact DOM/theme output, raw mobile/device, collaboration, table-model, and issue claims stay out.
../lexical/packages/lexical/src/__tests__/unit/LexicalEditor.test.tsxalready-applied for empty inline DOM line-break behavior; covered for read/update, normalization, command, move, and state rows; reject/defer for the rest.tmp/slate-v2/packages/slate-react/test/rendered-dom-shape-contract.tsx, core editor contractsAdded empty-inline DOM proof that a non-empty block does not render a visual line break inside an empty inline element. Existing read/update, transaction, normalization, operations, command, and snapshot contracts cover accepted model behavior. Lexical editor API shape, node-key maps, listener/mutation registration, update tags as Lexical internals, decorator rendering, root mounting, DOM reconciliation, and product-shell rows stay out or remain separate runtime owners.
../lexical/packages/lexical/src/__tests__/unit/LexicalEditorState.test.tsalready-applied for removed runtime-id purge; covered for read/snapshot immutability; reject for Lexical JSON/node-map internals.tmp/slate-v2/packages/slate/test/snapshot-contract.ts, read/update/headless contractsSource-read complete. Strengthened remove-node snapshot proof so removed block and text runtime IDs disappear from both current idToPath and pathToId. Existing snapshot immutability and read/update owners cover accepted state-boundary behavior. Lexical EditorState constructor, frozen node map identity, JSON schema, node keys, and parser/editor-context API rows stay out.
../lexical/packages/lexical/src/__tests__/unit/LexicalElementHelpers.test.tsrejectnoneSource-read complete. Despite the filename, this file only tests Lexical DOM class-name helpers (addClassNamesToElement / removeClassNamesFromElement) for empty, multiple, and whitespace-separated class strings. That is generic DOM utility behavior, not portable editor behavior for Slate v2.
../lexical/packages/lexical/src/__tests__/unit/LexicalExtensionCore.test.tsrejectnoneExtension core API is Lexical architecture.
../lexical/packages/lexical/src/__tests__/unit/LexicalNode.test.tsalready-applied for ancestry/sibling/common-ancestor query rows; covered for text content, empty-block normalization, and structural mutation rows; reject/defer for the rest.tmp/slate-v2/packages/slate/test/query-contract.ts, normalization/operation/transform ownersAdded compact query proof for ancestors, reverse ancestors, sibling path order, common ancestors, previous/next paths, and parent/ancestor predicates. Existing owners cover text content, empty-block normalization, selected removal/rebase, text split/merge, and move/insert/replace transforms. Lexical class API, node keys, clone/config/JSON, live-node read throws, DOM output, token/segmented/directionless text modes, and selectNext helper shape stay out or route to later keyboard/selection owners.
../lexical/packages/lexical/src/__tests__/unit/LexicalNodeState.test.tsdeferextension/state namespace owner if acceptedNode-state is Lexical-specific unless mapped to Slate extension state.
../lexical/packages/lexical/src/__tests__/unit/LexicalNormalization.test.tsxalready-applied for selection edge normalization; reject/defer for decorator and element-point internals.tmp/slate-v2/packages/slate/test/query-contract.tsSource-read complete. The portable row is not tree repair: Lexical $normalizeSelection maps element-backed endpoints to text endpoints. Added query proof that element paths, nested element paths, and backward ranges resolve to stable text points through Editor.range, Editor.edges, and Editor.point. Lexical decorator endpoint semantics and element-point API shape stay out or route to a future decorator/void/browser selection owner.
../lexical/packages/lexical/src/__tests__/unit/LexicalReconciler.test.tsrejectnoneLexical reconciliation internals.
../lexical/packages/lexical/src/__tests__/unit/LexicalSerialization.test.tsalready-applied for raw value JSON round-trip; reject for Lexical schema/parser internals.tmp/slate-v2/packages/slate/test/state-tx-public-api-contract.tsSource-read complete. Added compact public-state proof that rich raw document values round-trip through JSON and rehydrate as initialValue without runtime index metadata. Existing operation serialization fixtures cover operation JSON. Lexical editor-state JSON schema, node keys, parser API shape, and code/list/table node metadata stay out.
../lexical/packages/lexical/src/__tests__/unit/LexicalUpdateTags.test.tsdefercommit metadata/update tag owner if acceptedPossible Slate commit metadata pressure, but not a direct test port.
../lexical/packages/lexical/src/__tests__/unit/LexicalUtils.test.tsalready-applied for generic shortcut matching; covered for query/runtime/commit rows; reject/defer for the rest.tmp/slate-v2/packages/slate-dom/test/hotkeys.ts, core query/state/commit and React/browser ownersSource-read complete. Added generic isHotkey proof for semantic letter keys, uppercase keys, ASCII remapped layouts, and non-English physical-key fallback. Existing Hotkeys, query, runtime-id, state/read/update, commit metadata, focus/autoscroll, and browser selection owners cover the accepted rows. Lexical microtask helpers, random keys, token/segmented modes, node-key maps, cached type maps, node replacement/copy class APIs, listener order, and generic DOM utilities stay out or route to later dedicated owners.
../lexical/packages/lexical/src/__tests__/unit/mergeRegister.test.tsrejectnoneListener registration utility, not editor behavior.
../lexical/packages/lexical/src/caret/__tests__/unit/docs-traversals.test.tsalready-applied.tmp/slate-v2/packages/slate/test/query-contract.tsAdded package contract for sibling order, descendant depth-first paths, and lowest leaf/element range traversal; rejected Lexical caret helper API shape.
../lexical/packages/lexical/src/nodes/__tests__/unit/LexicalElementNode.test.tsxalready-applied for query/text traversal rows; covered or reject/defer for the rest.tmp/slate-v2/packages/slate/test/query-contract.ts, operations/normalization ownersAdded nested text-leaf and text-content query proof. Splice/selection rows route through existing operation/selection owners; DOM slot, indexPath, node lifecycle, and Lexical JSON schema rows stay out.
../lexical/packages/lexical/src/nodes/__tests__/unit/LexicalGC.test.tsxdefermemory/retention owner if acceptedOnly port if tied to Slate retained refs/history memory proof.
../lexical/packages/lexical/src/nodes/__tests__/unit/LexicalLineBreakNode.test.tsalready-applied for accepted linebreak/newline behavior; reject for Lexical node API rows.tmp/slate-v2/playwright/integration/examples/paste-html.test.ts, .tmp/slate-v2/packages/slate-react/test/primitives-contract.tsx, insert-break/input ownersSource-read complete. Slate has no LineBreakNode equivalent: Lexical type/schema/update/type-guard rows stay out. Accepted behavior is already covered by Quip `
` paste preserving newline text, line-break placeholder DOM proof, structural insert-break contracts, and Android newline-to-soft-break handling.
../lexical/packages/lexical/src/nodes/__tests__/unit/LexicalParagraphNode.test.tsalready-applied for paragraph alignment import; covered for split/merge; reject for Lexical node API rows.tmp/slate-v2/playwright/integration/examples/paste-html.test.ts, .tmp/slate-v2/site/examples/ts/paste-html-import.ts, insert-break/transform contractsAdded paste-html browser proof for valid paragraph alignment import: legacy align, CSS text-align precedence, and invalid align rejection. Existing insert-break/transform contracts cover split/merge shape; Lexical constructor/schema/DOM class/factory/type-guard rows stay out.
../lexical/packages/lexical/src/nodes/__tests__/unit/LexicalRootNode.test.tsalready-applied for selected top-level child removal; covered for root normalization/string rows; reject for Lexical root API/cached-text rows.tmp/slate-v2/packages/slate/test/selection-rebase-contract.ts, query-contract.ts, normalization-contract.ts, snapshot-contract.tsAdded package proof that removing a selected top-level block rebases to the next surviving block, and that removing the selected only block clears selection because Slate has no root selection point. Existing root normalization/top-level cleanup and Editor.string contracts cover Slate root behavior; Lexical constructor/schema/clone/DOM helper/root type guard/cached-text/decorator rows stay out.
../lexical/packages/lexical/src/nodes/__tests__/unit/LexicalTextNode.test.tsxalready-applied for text split/merge selection rebase; covered for text content/format/import rows; reject for Lexical text node API/rendering rows.tmp/slate-v2/packages/slate/test/operations-contract.ts, text-units-contract.ts, normalization-contract.ts, editor-methods-contract.ts, playwright/integration/examples/paste-html.test.tsAdded package proof that raw text split_node rebases expanded selections across split branches and raw text merge_node rebases selection into the surviving branch. Existing owners cover text-unit deletion, adjacent compatible text normalization, mark add/remove/toggle, and rich HTML mark import. Lexical JSON schema, node-key, mode/detail/style internals, DOM create/update/export rendering policy, node-state, and composition-key internals stay out.

Lexical Playground Placeholder Row-Level Source Read

Source: ../lexical/packages/lexical-playground/__tests__/e2e/Placeholder.spec.mjs.

Source rowDecisionSlate ownerReason
Empty editor displays placeholder while document HTML stays one empty paragraphapplied / already-applied.tmp/slate-v2/playwright/integration/examples/placeholder.test.ts, .tmp/slate-v2/packages/slate-react/test/rendered-dom-shape-contract.tsxBrowser proof now locks visible placeholder with empty model text and focused start selection. Package rendered-DOM proof owns the empty block's one line-break placeholder.
Focused empty editor selection is [0] offset 0 in Lexicalapplied.tmp/slate-v2/playwright/integration/examples/placeholder.test.tsSlate equivalent is [0, 0] offset 0 because Slate addresses the leaf text node under the empty paragraph.
Rich/plain/collab placeholder copy differs by playground moderejectnoneProduct shell text, not portable editor behavior.

Lexical Playground Images Row-Level Source Read

Source: ../lexical/packages/lexical-playground/__tests__/e2e/Images.spec.mjs.

Source rowDecisionSlate ownerReason
Keyboard deletion of a clicked selected imageapplied.tmp/slate-v2/playwright/integration/examples/images.test.tsBrowser proof now clicks the image void, confirms model selection at [1, 0], presses Backspace, and verifies the image count drops.
Arrow movement into/out of images, vertical movement, shifted selection into imagesalready-applied.tmp/slate-v2/playwright/integration/examples/images.test.ts, .tmp/slate-v2/packages/slate/test/query-contract.tsCurrent image browser rows and core void position rows already cover atomic image selection/navigation.
Lexical image HTML import with optional captionalready-applied.tmp/slate-v2/playwright/integration/examples/paste-html.test.tsCovered by the ImageHTML.test.ts slice: no-caption image and plain-text figcaption import.
URL/upload dialogs, image dimensions, drag/drop, caption editor UI, multi-node NodeSelection replacementdefer/rejectfuture explicit owners onlyProduct image workflow, renderer sizing policy, drag/drop, and Lexical NodeSelection behavior are not direct Slate core coverage.

Lexical Playground Tab Row-Level Source Read

Source: ../lexical/packages/lexical-playground/__tests__/e2e/Tab.spec.mjs.

Source rowDecisionSlate ownerReason
Tab inside a code block after markdown code-fence creationalready-applied.tmp/slate-v2/playwright/integration/examples/code-highlighting.test.tsCurrent code-highlighting browser proof already locks Tab inside a code line inserting configured whitespace and advancing the caret. The Lexical row's exact TabNode DOM/token class output is not a Slate claim.
Literal tab preservation from plain text and Google Docs HTMLalready-applied.tmp/slate-v2/packages/slate-dom/test/clipboard-boundary.ts, .tmp/slate-v2/playwright/integration/examples/paste-html.test.tsThe earlier LexicalTabNode slice already added plain-text tab/newline fallback proof and Google Docs Apple-tab-span browser proof.
Paragraph Tab followed by Chromium CDP IME compositiondefer/rejectfuture keyboard/IME/paragraph-indent ownerThis combines Lexical Playground paragraph indent policy, a TabNode text representation, Chromium-only CDP composition, and IME behavior. It is valuable source context, but not a clean raw Slate row until an explicit paragraph-indent plus IME owner accepts it.
Ctrl/Meta+ArrowLeft after typed Tab returns to start of linedeferfuture text-boundary or keyboard ownerBrowser-native line movement around a typed tab is worth a later boundary proof only if Slate accepts keyboard insertion of literal tabs as editor-owned behavior. This slice should not smuggle that policy through TabNode parity.

Lexical Playground Regression 1055 Fast Typing Undo Row-Level Source Read

Source: ../lexical/packages/lexical-playground/__tests__/regression/1055-fast-typing-undo.spec.mjs.

Source rowDecisionSlate ownerReason
Type hello, undo to empty, type hello again, undo to empty againapplied.tmp/slate-v2/packages/slate-history/test/history-contract.tsThe portable invariant is stack law: after undo, the next user edit must start a fresh undoable batch and clear redo. The existing Slate history row already proved redo invalidation; it now also undoes the follow-up edit back to the pre-edit state.
Lexical Playground HTML theme output and browser helper setuprejectnoneThe paragraph `
` DOM and helper-driven browser setup are Lexical Playground harness details. Slate coverage belongs in the history contract unless a browser history-hotkey owner is missing.

Lexical Playground Regression 1083 Backspace With Element At Front Row-Level Source Read

Source: ../lexical/packages/lexical-playground/__tests__/regression/1083-backspace-with-element-at-front.spec.mjs.

Source rowDecisionSlate ownerReason
Select all when the visible paragraph starts with a link, press Backspace, leave an empty paragraphapplied.tmp/slate-v2/packages/slate/test/delete-contract.ts, .tmp/slate-v2/packages/slate/src/transforms-text/delete-text.tsSlate normalizes an empty spacer before leading inline content, so the proof selects from that spacer through the trailing text. The delete transform now removes the fully-selected inline link and normalizes to one empty text leaf.
Select HelloWorld where Hello is an inline link after preceding text, press Backspace, preserve preceding Sayapplied.tmp/slate-v2/packages/slate/test/delete-contract.ts, .tmp/slate-v2/packages/slate/src/transforms-text/delete-text.tsThe transform now treats a fully-selected inline ancestor as a removable node only when the selection crosses outside that inline. This prevents empty inline shells from surviving expanded deletes while preserving existing inside-inline deletion behavior.
Lexical toolbar link creation, exact theme DOM, browser helper setuprejectnoneProduct shell and harness details are not portable Slate behavior.

Collaboration

SourceStatusSlate ownerNext decision
../lexical/packages/lexical-playground/__tests__/e2e/Collaboration.spec.mjsdefer.tmp/slate-v2/packages/slate/test/collab-history-runtime-contract.ts, future slate-yjs browser ownerCurrent substrate is covered; browser yjs parity waits for a real owner.

Nonportable Accounting

BucketCountProcessing
product-shell33plate-owned when the row describes reusable Plate plugin/product behavior; otherwise reject unless a later pass splits a raw invariant out of a product file.
harness12reject as direct behavior; reuse techniques only.
skip89reject with original harvest reasons preserved in inventory.md.

Priority Apply Queue

  1. Delete-character and adjacent delete regressions selected for this phase are applied or covered: simple forward/backward character rows, inline-void block join, list merge, and adjacent block-void delete. Lexical #7163 is applied.
  2. Clipboard HTML source rows selected for this phase are applied. Remaining link paste-into-existing rows are later inline-paste work; table custom widths, merge grids, rowspan/colspan, empty rows, and table-cell block normalization stay deferred.
  3. DOM mutation repair row from Mutations.spec.mjs is applied for accepted Slate owners: browser text mutation/selection traces plus package structural repair policy. No desktop structural repair or raw Android device claim.
  4. Focus/autoscroll browser rows are applied for accepted raw Slate behavior: outside-focus model selection and caret-visible root/parent scrolling while typing.
  5. Inline paste/mention/link/HR boundary rows are processed for this pass: link boundary copy/paste rows applied, mention raw Slate behavior already covered, HR deferred to a future HR/block-void owner, and link-plugin policy rows are Plate-owned unless a raw invariant is split out.
  6. Navigation, Selection, LexicalSelection, and LexicalCaret source-read rows are applied or classified. The LexicalCaret pass strengthened delete contracts for portable destructive range edges and rejected Lexical caret-object internals.
  7. docs-traversals.test.ts is applied in the Slate query contract for accepted package traversal behavior. No browser, raw mobile, collaboration, table-model, or issue claim.
  8. LexicalElementNode.test.tsx is applied/classified for this pass: query/text traversal proof added, existing operation/selection/normalization owners cover the rest of the accepted behavior, and DOM slot/node lifecycle/schema rows stay out.
  9. LexicalLineBreakNode.test.ts is source-read and classified: accepted linebreak/newline behavior is already applied by existing browser/React/input owners, while Lexical node class/schema/type-guard rows stay out.
  10. LexicalParagraphNode.test.ts is applied/classified: paragraph alignment import is now covered by paste-html browser proof and importer/rendering support; split/merge routes to existing owners; Lexical node class/schema rows stay out.
  11. LexicalRootNode.test.ts is applied/classified for this pass: selected top-level child removal proof added, root normalization/string behavior routes to existing owners, and Lexical root class/cached-text internals stay out.
  12. LexicalTextNode.test.tsx is applied/classified for this pass: split/merge selection rebase proof added, text content/format/import rows route to existing owners, and Lexical text node API/rendering rows stay out.
  13. LexicalTabNode.test.tsx and rich-text TabNode rows are applied/classified for this pass: plain-text tabs/newlines and Google Docs Apple-tab-span paste are now covered; TabNode class/schema/command API rows stay out; indent and adjacent literal-tab selection rows are deferred to their own owners.
  14. LexicalEditor.test.tsx is applied/classified for this pass: empty-inline DOM line-break proof added, existing Slate owners cover accepted read/update, transaction, normalization, command, move, and state behavior, and Lexical editor API/listener/decorator/root-mounting internals stay out.
  15. LexicalEditorState.test.ts is applied/classified for this pass: removed runtime IDs are now explicitly purged from current snapshot indexes, accepted state-boundary rows route to existing owners, and Lexical node-map/JSON/editor-context API rows stay out.
  16. LexicalElementHelpers.test.ts is rejected after source-read: it only tests DOM class-name helper utilities, not editor element/query behavior.
  17. LexicalNode.test.ts is applied/classified for this pass: ancestry/sibling/common-ancestor query proof added, existing owners cover accepted text/normalization/mutation behavior, and Lexical class/node-key/config/DOM/helper rows stay out.
  18. LexicalNormalization.test.tsx is applied/classified for this pass: selection edge normalization proof added to the query contract, and Lexical decorator/element-point internals stay out.
  19. LexicalSerialization.test.ts is applied/classified for this pass: raw document value JSON round-trip proof added, while Lexical editor-state JSON schema/parser/node-key rows stay out.
  20. LexicalUtils.test.ts is applied/classified for this pass: generic shortcut matching proof added, accepted query/runtime/commit/scroll rows route to existing owners, and Lexical utility/node-class internals stay out.
  21. LexicalUtilsInsertNodeToNearestRoot.test.tsx is applied/classified for this pass: highest-block insertion proof added, existing insertNodes fixtures cover direct paragraph/root rows, and Lexical command/node-key/decorator/shadow-root internals stay out.
  22. LexicalUtilsSplitNode.test.tsx is applied/classified for this pass: root split rejection proof added, existing splitNodes/operation fixtures cover direct split rows, and Lexical helper/API/HTML/list specifics stay out.
  23. LexicalCodeNodeTabs.test.ts from lexical-code-shiki and lexical-code is applied/classified for this pass: Slate code-highlighting Tab browser proof added, while Lexical indent/outdent command matrix, Shiki/theme policy, and backward-selection command semantics stay out.
  24. LexicalCodeNode.test.ts is applied/classified for this pass: Slate code-highlighting multi-line Tab and Shift+Tab proof added, while Lexical node class/DOM/export, language metadata, tokenizer/highlighter transform, Alt+Arrow line shifting, Home/End visual-caret, command dispatch, and node-key rows stay out or wait for separate accepted owners.
  25. LexicalHistory.test.tsx is applied/classified for this pass: redo-stack clearing, selected block property undo/redo, and node-property history capture proof added; Lexical command/CAN flags and shared nested editor history stay out.
  26. LexicalHtml.test.ts is source-read/classified for this pass: selected-fragment clipboard export and paragraph alignment import are covered by current owners; standalone HTML serializer and custom node export APIs stay rejected/deferred until a generic Slate HTML serializer owner exists.
  27. lexical-list/src/__tests__/unit/utils.test.ts is source-read/applied for this pass: list depth, top-list ancestry, and terminal item behavior are now locked as public path/query behavior; Lexical helper API shape stays out.
  28. 231-empty-text-nodes.spec.mjs is source-read/applied for this pass: repeated delete through token-like marked text now collapses to a canonical empty block; hashtag/plugin/CSS/collab rows stay out.
  29. 3433-merge-markdown-lists.spec.mjs is source-read/applied for this pass: markdown-created adjacent bulleted lists now merge in the markdown-shortcuts example; Playground/CSS/plain-text/collab rows stay out.
  30. defer table model rows until the table selection model decision is explicit.
  31. LexicalHeadingNode.test.ts is source-read/applied for this pass: browser proof now covers heading middle split, heading-end paragraph insertion, and empty-heading paragraph insertion; Lexical class/DOM/tag API rows stay out.
  32. LexicalQuoteNode.test.ts is source-read/applied for this pass: browser proof now covers empty blockquote Enter creating a paragraph after the quote; Lexical class/DOM/theme API rows stay out.
  33. $sliceSelectedTextNodeContent.test.ts is source-read/applied for this pass: selected text fragment slicing now covers partial unmarked and bold leaves plus source immutability; Lexical helper API internals stay out.
  34. LexicalListItemNode.test.ts is source-read/applied for this pass: non-empty list-item split is locked in the snapshot contract; Lexical class/DOM rows stay out, and replace/remove/indent/numbering rows stay deferred to explicit list owners.
  35. LexicalListNode.test.ts is source-read/applied for this pass: numbered-list wrapper formatting is locked in the snapshot contract; Lexical class/DOM/subclass/checklist/value rows stay out or deferred.
  36. formatList.test.ts is source-read/classified for this pass: root list formatting and non-empty continuation route to existing Slate owners; empty-item exit/split, whitespace-only exit, decorator rows, table-cell insertion, subclass preservation, indent/outdent helper APIs, and ordered-list metadata are Plate-owned list policy unless a raw invariant is split out.
  37. registerListStrictIndentTransform.test.ts is source-read/classified for this pass: compact malformed nested-list import is already represented by the paste-html browser corpus; exact strict indentation normalization, serializer output, and transform registration are Plate-owned list/serializer policy.
  38. LexicalMarkdown.test.ts is source-read/classified for this pass: current Slate browser examples cover quote/list/heading markdown shortcuts, while broad markdown import/export, normalization, nested fences, hard breaks, whitespace, list-marker/checklist metadata, MDX/custom transformer rows, and code-fence Enter shortcuts are Plate-owned markdown package rows.
  39. MarkdownTransformers.test.ts is source-read/classified for this pass: markdown link parsing, greedy-match prevention, formatted-prefix preservation, and no-nested-link transform behavior are Plate-owned markdown-link plugin/serializer rows; current raw inline-link boundary and clipboard owners remain separate.
  40. ClearFormatting.spec.mjs is source-read/applied for this pass: richtext now has a clear-formatting command and browser proof for selected mark removal, block alignment reset, semantic blockquote preservation, and cross-paragraph partial clearing. Link/mention/hashtag, indent/outdent, theme markup, raw mobile, collaboration, table-model, and issue rows stay out.
  41. CodeBlock.spec.mjs is source-read/applied for this pass: code-highlighting now has browser proof for selected paragraph-to-code-block conversion and code-line output. Existing code-highlighting rows cover Enter and Tab behavior. Markdown code fences, language parser matrix, auto-indent-on-newline, line movement, visual navigation, raw mobile, collaboration, table-model, and issue rows stay out.
  42. ElementFormat.spec.mjs is source-read/applied for this pass: richtext now proves fresh empty paragraph center alignment and explicitly targets the collapsed alignment block. Link+indent exact behavior stays deferred to future link/block-format plus indent owners; product shell rows stay rejected.
  43. HeadingsBackspaceAtStart.spec.mjs is source-read/applied for this pass: richtext now proves Backspace at the start of the first heading is a no-op preserving heading text, element type, and collapsed selection.
  44. HeadingsEnterAtEnd.spec.mjs is source-read/classified for this pass: existing richtext browser proof already covers Enter at the end of a heading creating a paragraph after the heading.
  45. HeadingsEnterInMiddle.spec.mjs is source-read/classified for this pass: existing richtext browser proof already covers Enter in the middle of a heading splitting it into two headings.
  46. Indentation.spec.mjs is source-read/classified for this pass: code-line Tab/Shift+Tab and basic list outdent are already owned; paragraph/table/list max-depth indent and negative-indent policy stay deferred to explicit indent/list/table owners; toolbar/theme rows stay rejected.
  47. List.spec.mjs is source-read/classified for this pass: toolbar list toggle/conversion is now applied in richtext browser proof; existing snapshot/browser owners cover basic list formatting; checklist, indentation depth, list-exit/collapse, ordered metadata, markdown-start, format-menu split, and autolink/list are Plate-owned list policy rows. Raw mobile, collaboration, table-model, and theme DOM rows stay deferred or rejected.
  48. Markdown.spec.mjs is source-read/applied for this pass: numeric ordered-list shortcut with start number is now applied in the markdown-shortcuts browser/example owner; import/export, inline transformers, decorator imports, code-formatted exclusion, link-transform selection, list-marker export, and HR/code-fence shortcuts are Plate-owned markdown/plugin rows. Raw mobile, collaboration, table-model, and theme DOM rows stay deferred or rejected.
  49. TextFormatting.spec.mjs is source-read/applied for this pass: mark hotkey insertion/toggle-off is now locked with package and richtext browser proof; tx.marks.toggle default/inherited mark clearing is fixed. Font-size/family, capitalization, strikethrough, decorator formatting, toolbar active-state CSS, raw mobile, collaboration, table-model, and theme DOM rows stay deferred or rejected.
  50. CodeBlock.test.ts is source-read/applied for this pass: paste-html now imports representative code-source HTML from <pre>, whitespace-preserving editor <div>s, and GitHub code tables as one code block without source gutters. Source-token styling, title inference, sub/sup typography, raw mobile, collaboration, table-model, and issue rows stay deferred or rejected.
  51. LexicalEditorListener.test.ts is source-read/classified for this pass: current Slate subscriber and commit-listener owners already cover the accepted unsubscribe/source-routing behavior; root/editable listener callback cleanup rows stay deferred or rejected as Lexical API/root-shell policy.
  52. LexicalListPlugin.test.tsx is source-read/applied for this pass: richtext now proves empty paragraph toolbar list toggle into and out of one list item; list indent/outdent and #7036 list-policy rows stay deferred/rejected to future explicit list owners.
  53. HTMLCopyAndPaste.spec.mjs is source-read/applied for this pass: paste-html now proves multiline HTML paragraphs with extra raw newlines normalize to four paragraphs with inline <b> / <i> formatting preserved, and the code-source corpus includes <code> with line breaks. HR insertion/splitting rows stay deferred to a future HR/block-void plus block-fragment owner.
  54. ListsHTMLCopyAndPaste.spec.mjs is source-read/classified for this pass: basic list HTML import, nested ul variants, and nested <div> list-item boundaries are already applied in the paste-html browser corpus; structural post-fragment selection is covered by clipboard contracts. Checklist/private attributes, toolbar indent/outdent, and HR-in-list splitting stay rejected or deferred to explicit future owners.
  55. ListsCopyAndPaste.spec.mjs is source-read/applied for this pass: package clipboard proof covers copying a partial list item plus following paragraph into an empty editor, inserting the same fragment into an empty list item by splitting the surrounding list, inserting a copied list into selected paragraph text without swallowing surrounding text, inserting two paragraphs into the middle of a list item by keeping the first paragraph as list item text and promoting the tail paragraph, and inserting two paragraphs at the end of a list as one list item plus following block. Exact Lexical DOM classes, value attributes, native clipboard transport, browser/OS flake tags, raw mobile, collaboration, table-model, and issue claims stay out of this package row.
  56. ImageHTML.test.ts is source-read/applied for this pass: paste-html now proves Lexical image HTML export shapes with no caption and with plain-text figcaption. The importer unwraps paragraph wrappers that only contain block elements so a block image is not nested under a paragraph. Caption text imports as a following paragraph. Lexical serializer API, exact alt/height/width attributes, caption editor internals, native clipboard transport, raw mobile, collaboration, table-model, and export claims stay out.
  57. HTMLCopyAndPaste.test.ts is source-read/applied for this pass: paste-html now proves core HTML block shapes from plain text, malformed paragraphs, generic div boundaries, nested spans/divs, nested span in div, and nested div in span. The importer treats generic div as a block-boundary fragment while preserving list-item div handling. Strong paste mark inheritance and iOS prediction fallback are already covered. Checklist rows stay deferred/rejected to a future checklist/list-plugin owner.
  58. CopyAndPaste.spec.mjs is source-read/applied for this pass: DOM clipboard now proves multi-paragraph fragments pasted into an empty block quote keep the first pasted text block in the target quote and promote the tail paragraph. Current owners already cover multi-block copy/paste, full-document replacement, inline link fragments, multiline plain-text splitting, font-size HTML, and collapsed-copy/cut clipboard preservation. Heading source-wrapper paste, hashtag/product spans, decorator embeds, exact plaintext rendering, native transport flake tags, raw mobile, collaboration, and table-model rows stay out or deferred.
  59. Events.spec.mjs is source-read/applied for this pass: plaintext browser proof now covers Mac-style beforeinput substitutions for autocapitalization and double-space period replacement after emoji. Runtime now flushes queued native text before the next model-owned beforeinput, text input uses provided replacement target ranges, and expanded insertText target ranges are honored even when model selection is preferred. Product shell/theme/OS harness details stay out.
  60. Keyboard.spec.mjs is source-read/applied for this pass: Slate React now owns insertTranspose as a model-owned beforeinput command, with package and plaintext browser proof that repeated adjacent character transpose turns abc into bca and leaves selection after the swapped pair. Lexical Playground setup, browser/OS flake tags, raw mobile, collaboration, table-model, and issue rows stay out.
  61. KeyboardShortcuts.spec.mjs is source-read/applied for this pass: richtext now proves paragraph/heading block shortcuts, delivered alignment shortcut handling, and clear-formatting shortcut behavior through browser events; code-highlighting now proves selected paragraph-to-code-block conversion by shortcut. Existing owners cover mark hotkeys, toolbar list conversion, clear-formatting semantics, and code-line editing. Heading three, checklist, product typography, font-size controls, paragraph/list/table indent shortcuts, active-state DOM, raw mobile, collaboration, table-model, and issue rows stay deferred or rejected.
  62. TextEntry.spec.mjs is source-read/applied for this pass: markdown-shortcuts now proves heading-start Enter creates a paragraph before the heading, and richtext now proves native Enter splits between plain and bold text into separate paragraphs while preserving bold text and selection. Basic typing/replacement/delete rows are covered by existing plaintext/richtext/browser stress owners; soft-break/newline-node behavior stays deferred to an explicit soft-break owner.
  63. SpecialTexts.spec.mjs is source-read/classified for this pass: bracket special-text highlighting is rejected as product transform/theme policy, and disabled-option literal bracket typing is covered by existing text insertion owners. No Slate code/test edit.
  64. Placeholder.spec.mjs is source-read/applied for this pass: placeholder browser proof now covers visible placeholder plus empty model text and focused start selection; existing rendered-DOM contracts own the empty-block line-break shape; Lexical rich/plain/collab placeholder copy stays rejected as product shell text.
  65. Images.spec.mjs is source-read/applied for this pass: image browser proof now covers Backspace deleting a clicked selected image void; existing image/paste/query owners cover movement, shifted selection, and Lexical image HTML import; toolbar/upload/dimensions/drag/drop/caption/multi-node NodeSelection rows stay deferred or rejected.
  66. Tab.spec.mjs is source-read/classified for this pass: existing code-highlighting, clipboard-boundary, and paste-html rows cover the accepted code/literal-tab behavior; paragraph Tab+IME, TabNode DOM output, and Ctrl/Meta+Arrow movement after typed Tab stay deferred or rejected to future explicit owners. No Slate code/test edit.
  67. 1055-fast-typing-undo.spec.mjs is source-read/applied for this pass: the history contract now proves a new edit after undo clears redo and remains undoable itself. Lexical Playground HTML/setup stays rejected.
  68. 1083-backspace-with-element-at-front.spec.mjs is source-read/applied for this pass: delete-contract now covers full and partial expanded deletes that start with a selected inline link, and delete-text removes fully-selected inline ancestors only when the expanded range crosses outside the inline. Lexical toolbar/theme setup stays rejected.
  69. 1113-link-newline-at-end.spec.mjs is source-read/applied for this pass: inlines browser proof now covers Enter after a typed URL link, and collapsed link insertion moves one offset out of the inserted inline so the next block does not inherit an empty duplicate link. Lexical Playground setup, exact DOM/theme output, raw mobile, collaboration, table-model, and issue rows stay out.
  70. 1384-insert-nodes.spec.mjs is source-read/applied for this pass: the accepted row is nested code-block clipboard insertion, not generic Lexical insert-nodes API behavior. insertFragment now merges a single nested text-block child from a same-type structural container into the active nested text block, with package proof and code-highlighting browser proof. Lexical Playground setup, exact gutter/theme output, raw mobile, collaboration, table-model, and issue rows stay out.
  71. 221-editing-hashtags.spec.mjs is source-read/applied for this pass: highlighted-text now proves dynamic hashtag-style decoration over normal editable text through Space split, Delete boundary, and Backspace boundary rows. The setup uses model-owned insertion to avoid conflating the row with a separate full-document projected-delete bug. Lexical Playground setup, hashtag product plugin, exact DOM/theme output, raw mobile, collaboration, table-model, and issue rows stay out.
  72. 230-navigation-around-hashtags.spec.mjs is source-read/applied for this pass: highlighted-text now proves ArrowRight can move into a dynamic hashtag-style decoration after transient prefix text is inserted and deleted. The row is desktop browser navigation proof only; Lexical Playground hashtag plugin setup, exact DOM/theme output, raw mobile, collaboration, table-model, and issue rows stay out.
  73. 3136-insert-nodes-adjacent-to-inline.spec.mjs is source-read/applied for this pass: clipboard-contract now proves fragment replacement of selected plain text immediately before and after an inline link, and inlines browser proof covers rich HTML paste replacing adjacent text without expanding or swallowing the link. Lexical Playground link toolbar setup, exact DOM/theme output, raw mobile, collaboration, table-model, and issue rows stay out.
  74. 379-backspace-with-mentions.spec.mjs is source-read/applied for this pass: mentions browser proof now covers Backspace removing a line boundary before an inline mention while preserving both mention atoms and restoring the boundary selection. Lexical Playground typeahead setup, mention styling, exact DOM/theme output, raw mobile, collaboration, table-model, and issue rows stay out.
  75. 399-open-line.spec.mjs is source-read/applied for this pass: Slate now owns Mac Ctrl+O as a distinct model-owned open-line command, with richtext browser proof that it opens an empty block before following text and leaves selection on that empty line. The first proof went red with no inserted line, and the first implementation went red by moving/duplicating through split-block semantics; the final direct insert owner passed focused browser proof, hotkey proof, slate-react kernel contract proof, and .tmp/slate-v2 bun check. A full richtext Chromium sweep exposed a deterministic unrelated IME mark expectation mismatch in commits IME composition through an active mark before a formatted sibling; focused 399 proof remains green.
  76. 429-swapping-emoji.spec.mjs is source-read/applied for this pass: richtext browser proof now covers Enter at the start of a plain Unicode emoji line opening an empty block before it, preserving selection at the emoji-line start, and Backspace rejoining without text or selection corruption. The accepted row is Unicode emoji-line Enter/Backspace behavior, not Lexical Playground emoji substitution UI, exact emoji span/theme DOM, flaky tagging, raw mobile, collaboration, table-model, or issue behavior.
  77. 5251-paste-into-inline-element.spec.mjs is source-read/applied for this pass: clipboard-contract now proves rich fragment insertion over selected inline-link text keeps pasted text/marks outside the surviving link tail; DOM clipboard fallback now routes selected same-inline text replacement through fragment insertion; inlines browser proof covers HTML clipboard payload text replacement outside the link. Lexical Playground link toolbar setup, exact DOM/theme output, raw mobile, collaboration, table-model, and issue rows stay out.
  78. 5583-select-list-followed-by-element-node.spec.mjs is source-read/applied for this pass: dom-coverage browser proof now covers native drag selection from a list item to a boundary placeholder, asserting no page errors and a valid imported model range. Lexical Playground drag helpers, HR product shell, exact DOM/theme output, raw mobile/device, collaboration, table-model, and issue claims stay out.
  79. 7635-SELECTION_INSERT_CLIPBOARD_NODES_COMMAND.spec.mjs is source-read/applied for this pass: editable-voids now proves rich HTML paste inside a nested rich-text editor preserves bold formatting, does not leak into the parent value, preserves parent selection, and keeps the parent editor usable after nested editing. RichText now has a narrow supported-mark/block HTML paste capability, and selection import rejects parent-to-nested DOM ranges before they can overwrite parent content. Lexical image caption UI, command API, exact DOM/theme output, raw mobile/device, collaboration, table-model, and issue claims stay out.
  80. AutoLinks.spec.mjs is source-read/applied for this pass: inlines browser proof now covers single-URL paste creating a safe inline link while follow-up typing stays outside the link. Lexical's broad autolink parser/tokenizer matrix, email detection, invalid URL grammar, unlink/relink UI, unlinked autolink state, emoji shortcode rows, styling/font rows, and toolbar shell are Plate-owned link/autolink rows. Exact DOM/theme output, raw mobile, collaboration, table-model, and issue claims stay deferred or rejected.
  81. Hashtags.spec.mjs is source-read/applied for this pass: highlighted-text now proves deleting a hashtag delimiter expands the decorated token, restoring the delimiter shrinks it, and deleting the leading # removes the decoration with stable caret placement. Existing highlighted-text rows already covered Space split, Delete/Backspace boundaries, transient-prefix navigation, copy/cut, and decorated-text IME/editing. Lexical's hashtag plugin grammar, invalid-match matrix, markdown import/export shell, and format inheritance styling are Plate-owned hashtag/markdown rows. Exact DOM/theme output, raw mobile, collaboration, table-model, and issue claims stay deferred or rejected.
  82. Keywords.spec.mjs is source-read/covered for this pass: current highlighted-text rows already prove projected text selection/movement/editing, mark-click typing through projections, decorated IME, copy/cut semantics, hashtag-style delimiter merge/split, and selected decorated-range deletion. Lexical's exact congrats grammar, bracket/team token policy, keyword styling, and product plugin setup are Plate-owned keyword/autocomplete rows. Exact DOM/theme output, raw mobile, collaboration, table-model, and issue claims stay deferred or rejected.
  83. SelectionAlwaysOnDisplay.spec.mjs is source-read/covered for this pass: the raw invariant is blurred-editor model-selection persistence, already covered by richtext browser proof. Lexical's always-on fake-selection overlay and highlight alignment policy are Plate-owned product visualization rows. Exact DOM/theme output, plain-text skip policy, raw mobile/device, collaboration, table-model, and issue claims stay deferred or rejected.
  84. defer raw mobile rows until real device/Appium proof exists.
  85. defer collaboration browser rows until a slate-yjs/browser owner exists.

Verification Gates For Future Apply Slices

bash
cd /Users/zbeyens/git/slate-v2
bun test ./packages/slate/test/text-units-contract.ts
bun test ./packages/slate-dom/test/clipboard-boundary.ts
bun test ./packages/slate-history/test/history-contract.ts
PLAYWRIGHT_RETRIES=0 bunx playwright test playwright/integration/examples/paste-html.test.ts --project=chromium
PLAYWRIGHT_RETRIES=0 bunx playwright test playwright/integration/examples/tables.test.ts --project=chromium
PLAYWRIGHT_RETRIES=0 bunx playwright test playwright/stress/generated-editing.test.ts --project=chromium -g '<accepted-family>'
bun check

Raw device rows need:

bash
cd /Users/zbeyens/git/slate-v2
SLATE_BROWSER_RAW_MOBILE_REQUIRED=1 bun test:mobile-device-proof:raw